#!/usr/bin/ruby

#
## Test Array#sum and Array#prod
#

var a = [1,2,3,4,5]

assert_eq(a.prod, 120)
assert_eq(a.sum,  15)

assert_eq(
    [1,2,Quadratic(3,4,5),3/4].sum,
    Quadratic(27/4, 4, 5),
)

assert_eq(
    [Gauss(3,4),Gauss(9,11)].sum,
    Gauss(12, 15),
)

assert_eq(
    [Quadratic(5,6,2), 2].prod,
    Quadratic(10, 12, 2)
)

assert_eq(
    [Quadratic(5,6,2), 3/4].prod,
    Quadratic(15/4, 9/2, 2)
)

assert_eq(
    [Poly(1,2,3,4), Gauss(3,4), Quadratic(9,5,2), Mod(43, 97)].sum,
    Polynomial(0 => Gauss(Quadratic(Mod(55, 97), 5, 2), 4), 1 => 2, 3 => 4)
)

assert_eq(
    [Poly(1,2,3,4), Gauss(3,4), Quadratic(9,5,2), Mod(43, 97)].prod,
    Polynomial(1 => Gauss(Quadratic(Mod(91, 97), Mod(29, 97), 2), Quadratic(Mod(89, 97), Mod(71, 97), 2)), 3 => Gauss(Quadratic(Mod(85, 97), Mod(58, 97), 2), Quadratic(Mod(81, 97), Mod(45, 97), 2)))
)

assert_eq([3/4].sum, 3/4)
assert_eq([3/4].prod, 3/4)

assert_eq([Quadratic(5,2,7)].prod, Quadratic(5,2,7))
assert_eq([Quadratic(5,2,7)].sum, Quadratic(5,2,7))

assert_eq(a.sum  { _*_ }, 55)
assert_eq(a.prod { _*_ }, 14400)

assert_eq(a.sum(:sqrt), a.sum { .sqrt })
assert_eq(a.prod(:sqrt), a.prod { .sqrt })

# This may change in the future (changed)
# assert_eq(a.sum(42),  57)
# assert_eq(a.prod(2), 240)

# Empty array
assert_eq([].sum,  0)
assert_eq([].prod, 1)

#
## Test RangeNumber#sum and RangeNumber#prod
#

var r = 1..5

assert_eq(r.prod, 120)
assert_eq(r.sum,  15)

assert_eq(r.sum  { _*_ }, 55)
assert_eq(r.prod { _*_ }, 14400)

assert_eq(r.sum(:sqrt), r.sum { .sqrt })
assert_eq(r.prod(:sqrt), r.prod { .sqrt })

# This may change in the future (changed)
# assert_eq(r.sum(42),  57)
# assert_eq(r.prod(2), 240)

# Empty range
assert_eq((5..4).sum,  0)
assert_eq((5..4).prod, 1)

# Auto-conversions
do {
    var arr = ["12", "42"]

    assert_eq(arr.prod, 12*42)
    assert_eq(arr.sum, 12+42)

    assert_eq(arr, ["12", "42"])
}

# Array gcd/lcm
do {
    var arr = ["48", "120", "42"]

    assert_eq(arr.lcm, lcm(42, 48, 120))
    assert_eq(arr.gcd, gcd(42, 48, 120))

    assert_eq(arr.lcm { _ }, lcm(42, 48, 120))
    assert_eq(arr.lcm { .to_i**2 }, lcm(42**2, 48**2, 120**2))

    assert_eq(arr.gcd { _ }, gcd(42, 48, 120))
    assert_eq(arr.gcd { .to_i**2 }, gcd(42**2, 48**2, 120**2))

    assert_eq(arr, ["48", "120", "42"])
}

# Range gcd/lcm
do {

    assert_eq(lcm(1..10), lcm(@|1..10))
    assert_eq(lcm(200..250), lcm(@|200..250))

    assert_eq(lcm(20..10), 1)
    assert_eq(gcd(20..10), 0)

    assert_eq(lcm(1..-10), 1)
    assert_eq(gcd(1..-10), 0)

    assert_eq(20..10 -> lcm { _ }, 1)
    assert_eq(20..10 -> gcd { _ }, 0)

    assert_eq(1..10    -> lcm { _ },   lcm(1..10))
    assert_eq(200..250 -> lcm { _+1 }, lcm(201..251))

    assert_eq(gcd(42..60 `by` 2), 2)
    assert_eq(gcd(42..60 `by` 3), 3)

    assert_eq(4..10 -> gcd { _! }, 24)
    assert_eq(4..10 -> flip.gcd { _! }, 24)
}

say "** Test passed!"
