#!/usr/bin/ruby
#
## Tests for ilog(), ilog2() and ilog10().
#
for n in (1..100) {
assert_eq(ilog(3**n, 3), n)
assert_eq(ilog2(2**n), n)
assert_eq(ilog10(10**n), n)
assert_eq(ilog10(10**n + 1), n)
assert_eq(ilog10(10**n - 1), n-1)
assert_eq(ilog(3**n), log(3**n).int)
assert_eq(ilog2(exp(n)), log2(exp(n)).int)
assert_eq(ilog(exp(n), 3), log(exp(n), 3).int)
assert_eq(ilog(100**n, 100), n)
assert_eq(ilog(100**n + 1, 100), n)
assert_eq(ilog(100**n - 1, 100), n-1)
}
assert_eq(gather {
var x = 0
{ take(x.next_pow!(3)) } * 5
}, [1, 3, 9, 27, 81])
assert_eq(gather {
var x = 0
{ take(x.next_pow!(4)) } * 5
}, [1, 4, 16, 64, 256])
assert_eq(gather {
var x = 0
{ take(x.next_pow!(2)) } * 5
}, [1, 2, 4, 8, 16])
assert_eq(2**4096 -> next_pow(2), 2**4097)
assert_eq(2**4096 - 1 -> next_pow(2), 2**4096)
assert_eq(2**4096 + 1 -> next_pow(2), 2**4097)
assert_eq(3**2000 -> next_pow(3), 3**2001)
assert_eq(3**2000 - 1 -> next_pow(3), 3**2000)
assert_eq(3**2000 + 1 -> next_pow(3), 3**2001)
assert_eq(
@(1..10).map_reduce{|a| a.next_pow(2) },
0..9 -> map {|n| 2**n }
)
assert_eq(99**4096 -> prev_pow(99), 99**4095)
assert_eq(99**4096 - 1 -> prev_pow(99), 99**4095)
assert_eq(99**4096 + 1 -> prev_pow(99), 99**4096)
assert_eq(102**2000 -> prev_pow(102), 102**1999)
assert_eq(102**2000 - 1 -> prev_pow(102), 102**1999)
assert_eq(102**2000 + 1 -> prev_pow(102), 102**2000)
assert_eq(
@(3..10).map_reduce{|a| a.next_pow(3) }.map { .prev_pow(3) },
0..7 -> map {|n| 3**n },
)
assert_eq(4.prev_pow(3), 3)
assert_eq(3.prev_pow(3), 1)
assert_eq(2.prev_pow(3), 1)
assert(1.prev_pow(3).is_nan)
assert_eq(0.next_pow(3), 1)
assert_eq(1.next_pow(3), 3)
assert_eq(2.next_pow(3), 3)
assert_eq(3.next_pow(3), 9)
assert_eq(ilog(2147483646, 1319909920001892772), 0)
assert_eq(ilog(1319909920001892772, 2147483646), 1)
assert_eq(ilog(2**64, 2**32 - 1), 2)
assert_eq(ilog(2**64 - 1, 2**32), 1)
assert_eq(ilog(2**64, 2**32 + 1), 1)
assert_eq(ilog(2**64, 2**32), 2)
assert_eq(ilog(2**64 - 1, 2**32 - 1), 2)
assert_eq(ilog(18446744073709551614, 2**32 - 1), 2)
assert_eq(ilog(18446744073709551614, 2**32), 1)
assert_eq({ .ilog2 }.map(1..20), { .log2.floor }.map(1..20))
assert_eq({ .ilog(3) }.map(1..20), { .log(3).floor }.map(1..20))
assert_eq({ .ilog10 }.map(1..20), { .log10.floor }.map(1..20))
assert_eq(ilog(2, 2), 1)
# Run some random tests
for n in (1..66), k in (1..66) {
var a = irand(1, 1<<n)
var b = irand(2, 1<<k)
try {
var x = a.ilog(b)
var y = a.log(b).floor
if (ipow(b, x) == a) { # perfect power
## ok
}
else {
assert_eq(x, y)
}
}
catch {|m|
die "Failed for ilog(#{a}, #{b}) with error: #{m}"
}
}
say "** Test passed!"