#!/usr/bin/ruby

#
## https://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test
#

func is_prime(n { .is_odd && (_ > 2) }, k) {
    var s = 0
    var d = n.dec
    (d >>= 1; ++s) while d.is_even

    k.times {
        var a = irand(2, n-1)
        var x = expmod(a, d, n)
        next if (x ~~ [1, n-1])

        (s-1).times {
            x.expmod!(2, n)
            return false if x.is_one
            break if (x == n-1)
        }
        return false if (x != n-1)
    }

    return true
}

func is_prime((2), _k) { true }
func is_prime(_n, _k)  { false }

var numbers = [
    61_794_479,
    2867561004669023153611,
    803_086_491,
    171_659_461_843,
    902_802_468_593,
    3_539_679_283_117,
    12_905_496_217_051,
    103_497_586_783_721,
];

numbers.each { |n|
    var p = is_prime(n, 12);
    say ("#{n} is" + (p ? ' ' : ' NOT ') + 'prime');
    assert_eq(p, n.is_prime);
}

var p = gather {
    for n in (1..100) {
        is_prime(n, 10) && take(n)
    }
}

assert_eq(p, primes(100))
