#!/usr/bin/ruby

# Tests for some Number methods of the form nth_*.

assert_eq(300.of{.nth_semiprime}.slice(1), 300.dec.by{.is_semiprime})
assert_eq(300.of{.nth_prime_power}.slice(1), 300.dec.by{.is_prime_power})
assert_eq(300.of{.nth_prime}.slice(1), 300.dec.by{.is_prime})

assert_eq(nth_almost_prime(500, 500), 487939787489518647498841089183363998627293204988294345182353119556829944026571800837287448137330088425304046352764423084811447303871041402011783643791360)

assert_eq(20.of { .nth_perfect_power }, 20.by { .is_perfect_power })

with (20.of { .nth_perfect_power }) {|a|
    var b = a.map { .nth_perfect_power }
    assert(a.all { .is_perfect_power })
    assert(b.all { .is_perfect_power })
    assert_eq(b.map { .perfect_power_count }, a)
    assert_eq(a.map { .perfect_power_count }, @^20)
}

assert_eq(nth_perfect_power(1e30), 999999999799999998042589213648741079622476300756355004439076)

assert_eq(
    { nth_almost_prime(_, _) }.map(1..29)
    %n[2, 6, 18, 40, 108, 224, 480, 1296, 2688, 5632, 11520, 25600, 53248, 124416, 258048, 540672, 1105920, 2228224, 4587520, 9830400, 19922944, 40894464, 95551488, 192937984, 396361728, 822083584, 1660944384, 3397386240, 6845104128]
)

assert_eq(
    { nth_squarefree_almost_prime(_, _) }.map(1..10)
    %n[2, 10, 66, 462, 4290, 53130, 903210, 17687670, 406816410, 11125544430]
)

assert_eq(
    { nth_omega_prime(_, _) }.map(1..9)
    %n[2, 10, 60, 420, 4290, 53130, 903210, 17687670, 406816410]
)

for k in (1..5) {
    assert_eq(
        20.of { nth_almost_prime(_, k) }.slice(1),
        19.by { .is_almost_prime(k) }
    )

    assert_eq(
        20.of { nth_squarefree_almost_prime(_, k) }.slice(1),
        19.by { .is_almost_prime(k) && .is_squarefree }
    )

    assert_eq(
        20.of { nth_omega_prime(_, k) }.slice(1),
        19.by { .is_omega_prime(k) }
    )

    assert_eq(
        Math.seq(1, { .tail.next_powerful(k) }).while { _ <= 1e4 },
        k.powerful(1e4)
    )

    assert_eq(
        Math.seq(next_almost_prime(0, k), { .tail.next_almost_prime(k) }).while { _ <= 1e3 },
        k.almost_primes(1e3)
    )

    assert_eq(
        Math.seq(next_omega_prime(0, k), { .tail.next_omega_prime(k) }).while { _ <= 1e4 },
        k.omega_primes(1e4)
    )

    assert_eq(
        Math.seq(next_squarefree_almost_prime(0, k), { .tail.next_squarefree_almost_prime(k) }).while { _ <= 1e4 },
        k.squarefree_almost_primes(1e4)
    )
}

assert_eq(
    Math.seq(next_squarefree_semiprime(0), { .tail.next_squarefree_semiprime }).while { _ <= 1e4 },
    squarefree_semiprimes(1e4)
)

assert_eq(
    Math.seq(next_semiprime(0), { .tail.next_semiprime }).while { _ <= 1e4 },
    semiprimes(1e4)
)

assert_eq(
    Math.seq(next_prime_power(0), { .tail.next_prime_power }).while { _ <= 1e4 },
    prime_powers(1e4)
)

assert_eq(
    Math.seq(next_prime(0), { .tail.next_prime }).while { _ <= 1e4 },
    primes(1e4)
)

assert_eq(
    Math.seq(next_squarefree(0), { .tail.next_squarefree }).while { _ <= 1e4 },
    squarefree(1e4)
)

assert_eq(
    Math.seq(next_composite(0), { .tail.next_composite }).while { _ <= 1e4 },
    composites(1e4)
)

assert_eq(nth_almost_prime( 3, 100),  2852213850513516153367582212096)
assert_eq(nth_almost_prime( 1, 123),  10633823966279326983230456482242756608)
assert_eq(nth_almost_prime( 2, 124),  31901471898837980949691369446728269824)
assert_eq(nth_almost_prime( 2,  50),  1688849860263936)
assert_eq(nth_almost_prime(50, 100),  26145293629707231405869503610880)

assert_eq(nth_squarefree_almost_prime(15, 14), 20483443417467030)
assert_eq(nth_squarefree_almost_prime(10, 15), 880788066951082290)

assert_eq(nth_omega_prime(15, 14), 20483443417467030)
assert_eq(nth_omega_prime(10, 15), 880788066951082290)

assert_eq(next_semiprime(2**64 - 10), 2**64 + 1)
assert_eq(next_semiprime(2**63 - 10), 9223372036854775817)

assert_eq(next_squarefree_semiprime(2**64 - 10), 2**64 + 1)
assert_eq(next_squarefree_semiprime(2**63 - 10), 9223372036854775817)

for j in (15, 20), k in (1..10) {
    var n = irand(10**j)
    var t = next_almost_prime(n, k)
    assert(t.is_almost_prime(k))
    assert_eq(range(n+1, t).grep {.is_almost_prime(k)}, [t])
}

for n in (1 .. (Number.HAS_PRIME_UTIL ? 8 : 5)), k in (2..14 -> map{|b| b**n }) {

    if (Number(Number.ULONG_MAX) < 2**32) {
        n < 8 || next
    }

    do {
        var t = nth_semiprime(k)
        assert(t.is_semiprime)
        assert_eq(t.semiprime_count, k)
    }

    do {
        var t = nth_prime_power(k)
        assert(t.is_prime_power)
        assert_eq(t.prime_power_count, k)
    }

    do {
        var t = nth_perfect_power(k)
        assert(t.is_perfect_power)
        assert_eq(t.perfect_power_count, k)
    }

    do {
        var t = nth_prime(k)
        assert(t.is_prime)
        assert_eq(t.prime_count, k)
    }
}

for j in (2..5), n in (2..5 -> map{|b| b**j }), k in (2..5) {
    do {
        var t = nth_powerful(n, k)
        assert(t.is_powerful(k))
        assert_eq(k.powerful_count(t), n)
    }

    do {
        var t = nth_almost_prime(n, k)
        assert(t.is_almost_prime(k))
        assert_eq(k.almost_prime_count(t), n)
    }

    do {
        var t = nth_squarefree_almost_prime(n, k)
        assert(t.is_squarefree_almost_prime(k))
        assert(t.is_almost_prime(k))
        assert(t.is_omega_prime(k))
        assert(t.is_squarefree)
        assert_eq(k.squarefree_almost_prime_count(t), n)
    }

    do {
        var t = nth_omega_prime(n, k)
        assert(t.is_omega_prime(k))
        assert_eq(k.omega_prime_count(t), n)
    }
}

assert_eq(3.powerfree_count(1099999), 915099)

for j in (2..8), n in (2..15 -> map{|b| b**j }), k in (2..10) {
    do {
        var t = nth_powerfree(n, k)
        assert(t.is_powerfree(k))
        assert_eq(k.powerfree_count(t), n)
    }

    do {
        var t = nth_nonpowerfree(n, k)
        assert(t.is_nonpowerfree(k))
        assert_eq(k.nonpowerfree_count(t), n)
    }
}

say "** Test passed!"
