include :assert

add_results setup name: "number tests" {
  test "number_times" {
    assert_equal 5 { 5.times { :a } }
    assert_equal [:a, :a, :a] { a = []; 3.times { a << :a }; a }
    assert_equal [] { a = []; 0.times { a << :a }; a }
    assert_equal [0, 1, 2] { a = []; 3.times { i | a << i }; a }
    assert_equal [:0, :1, :2] { a = []; 3.times { i | a << i.to_s }; a }
  }

  test "addition_subtraction" {
    assert_equal 0 { 1 - 1 }
    assert_equal 0 { 1 + -1 }
    assert_equal 2 { 1 + 1 }
    assert_equal 3 { 1 + 1 + 1 }
    assert_equal -2 { 1 - 1 - 1 - 1 }
    assert_equal 0 { a = 1; b = 2; c = 3; c - a - b }
    assert_equal 0 { 1 + 3 - 4 + 10 - 5 - 5 }
    assert_equal 1 { 0.5 + 0.5 }
  }

  test "bignum_addition" {
    assert_equal 1073741824 { 1073741823 + 1 }
    assert_equal 1073741824 { 1 + 1073741823 }
    assert_equal 2147483646 { 1073741823 + 1073741823 }
    assert_equal 0 { 1073741823 + -1073741823 }
    assert_equal 0 { -1073741823 + 1073741823 }
  }

  test "bignum_subtraction" {
    assert_equal 1073741823 { 1073741824 - 1 }
    assert_equal 0 { 1073741823 - 1073741823 }
    assert_equal 0 { -1073741823 - -1073741823 }
    assert_equal 1073741824 { 1 - -1073741823 }
  }

  test "precedence" {
    assert_equal 0 { (1 + 3 * 4 - 10 / 2) / 8 - 1 }
    assert_equal 0 { (3 * 5 + 5 * 1 + 1 * 40 / 2) - 40 }
    assert_equal 33 { 1 + 2 ^ 5 }
  }

  test "division" {
    assert_equal 0 { 0 / 100 }
    assert_equal 1 { 100 / 100 }
    assert_equal 5 { 100 / 20 }
    assert_equal 1 { 100 / 2 / 2 / 5 / 5 }
    assert_equal 0.5 { 1 / 2 }
  }

  test "bignum_division" {
    assert_equal 1 { 1.1 / 1.1 }
    assert_equal 1 { 1000000000000 / 1000000000000 }
  }

  test "multiply" {
    assert_equal 1 { 1 * 1 }
    assert_equal -2 { 1 * -2 }
    assert_equal 1 { 2 * 0.5 * 2 * 0.5 * 1 }
    assert_equal 1.5 { a = 6; b = 0.25; a * b }
  }

  test "exponentiation" {
    assert_equal 256 { 2 ^ 8 }
  }

  test "bignum_multiply" {
    assert_equal 10000000 { 10000000 * 1 }
    assert_equal 20000000 { 10000000 * 2 }
    assert_equal 20000000 { 2 * 10000000 }
    assert_equal "2.1397102397e+20" { (10000000000 * 21397102397).to_s }
  }

  test "modulo" {
    assert_equal 1 { 3 % 2 }
    assert_equal 2 { 10 % 8 }
  }

  test "number_compare" {
    assert { true? 1 < 2 }
    assert_false { true? 1 > 2 }
    assert { true? 1 <= 1 }
    assert { true? 1 >= 1 }
    assert { a = 300; b = 200; b + 100 == a }
    assert { a = 300; b = 200; b + 300 == a + 200 }
    assert_false { [1,2,3].length <= 1 }
    assert_false { 1 == "1" }
    assert { 1 != "1" }
  }

  test "bignum_compare" {
    assert { 100000000 > 1 }
    assert { 100000000 >= 1 }
    assert_false { 100000000 < 1 }
    assert_false { 100000000 <= 1 }
    assert_false { 100000000 == 1 }
    assert_false { 1 > 1000000000 }
    assert_false { 1 >= 1000000000 }
    assert_false { 1 == 1000000000 }
    assert { 1 <= 1000000000 }
    assert { 1 < 1000000000 }
    assert { 1000000000 == 1000000000 }
    assert_false { 10000000 > 1000000000 }
    assert_false { 10000000 >= 1000000000 }
    assert_false { 10000000 == 1000000000 }
    assert { 10000000 <= 1000000000 }
    assert { 10000000 < 1000000000 }
  }

  test "number_to_f" {
    assert_equal 5.5 { 5.5.to_f }
    assert_equal "1.9238012973112e+14" { 192380129731123.3.to_f.to_s }
  }

  test "number_to_i" {
    assert_equal 5 { 5.5.to_i }
    assert_equal 0 { (1 / 2).to_i }
    assert_equal "1.9238012973112e+14" { 192380129731123.3.to_i.to_s }
  }

  test "number.to" {
    assert_equal [1 2 3 4 5 6] { 1.to 6 }
    assert_equal [6 5 4 3 2 1] { 6.to 1 }
    assert_equal [-1 0 1] { (-1).to 1 }
    assert_equal [1 2 3 4 5 6] { a = []; 1.to 6 { n | a << n }; a  }
    assert_equal [6 5 4 3 2 1] { a = []; 6.to 1 { n | a << n }; a  }
    assert_equal [-1 0 1] { a = []; (-1).to 1 { n | a << n }; a  }
  }
  
  test "number.of" {
    assert_equal [:a :a :a :a] { 4.of :a }
    assert_equal [:a :a :a :a] { 4.of { :a } }
    assert_equal [1 2 3 4] { x = 0; 4.of { x = x + 1; x } }
    assert_equal [] { 0.of :anything }
  }

  test "number.to_char" {
    assert_equal "a" { 97.to_char }
    assert_equal 97 { 97.to_char.to_byte }
  }
}