require "spec" require "big" require "spec/helpers/string" private def it_converts_to_s(value : BigFloat, str, *, file = __FILE__, line = __LINE__) it "converts to #{str}", file: file, line: line do assert_prints value.to_s, str, file: file, line: line str.to_big_f.should eq(value), file: file, line: line end end private def with_precision(precision, &) old_precision = BigFloat.default_precision BigFloat.default_precision = precision begin yield ensure BigFloat.default_precision = old_precision end end describe "BigFloat" do describe ".new" do string_of_integer_value = "123456789012345678901" string_of_integer_value_as_float = "1.23456789012345678901e+20" bigfloat_of_integer_value = BigFloat.new(string_of_integer_value) string_of_float_value = "1234567890.12345678901" bigfloat_of_float_value = BigFloat.new(string_of_float_value) it "new(String)" do bigfloat_of_integer_value.to_s.should eq(string_of_integer_value_as_float) bigfloat_of_float_value.to_s.should eq(string_of_float_value) BigFloat.new("+#{string_of_integer_value}").to_s.should eq(string_of_integer_value_as_float) BigFloat.new("-#{string_of_integer_value}").to_s.should eq("-#{string_of_integer_value_as_float}") BigFloat.new("123_456_789.123_456_789").to_s.should eq("123456789.123456789") end it "raises an ArgumentError unless string denotes valid float" do expect_raises(ArgumentError) { BigFloat.new("abc") } expect_raises(ArgumentError) { BigFloat.new("+") } expect_raises(ArgumentError) { BigFloat.new("") } end it "new(BigInt)" do bigfloat_on_bigint_value = BigFloat.new(BigInt.new(string_of_integer_value)) bigfloat_on_bigint_value.should eq(bigfloat_of_integer_value) bigfloat_on_bigint_value.to_s.should eq(string_of_integer_value_as_float) end it "new(BigRational)" do bigfloat_on_bigrational_value = BigFloat.new(BigRational.new(1, 3)) bigfloat_on_bigrational_value.should eq(BigFloat.new(1) / BigFloat.new(3)) end it "new(BigFloat)" do BigFloat.new(bigfloat_of_integer_value).should eq(bigfloat_of_integer_value) BigFloat.new(bigfloat_of_float_value).should eq(bigfloat_of_float_value) end it "new(Int)" do BigFloat.new(1_u8).to_s.should eq("1.0") BigFloat.new(1_u16).to_s.should eq("1.0") BigFloat.new(1_u32).to_s.should eq("1.0") BigFloat.new(1_u64).to_s.should eq("1.0") BigFloat.new(1_i8).to_s.should eq("1.0") BigFloat.new(1_i16).to_s.should eq("1.0") BigFloat.new(1_i32).to_s.should eq("1.0") BigFloat.new(1_i64).to_s.should eq("1.0") BigFloat.new(-1_i8).to_s.should eq("-1.0") BigFloat.new(-1_i16).to_s.should eq("-1.0") BigFloat.new(-1_i32).to_s.should eq("-1.0") BigFloat.new(-1_i64).to_s.should eq("-1.0") BigFloat.new(255_u8).to_s.should eq("255.0") BigFloat.new(65535_u16).to_s.should eq("65535.0") BigFloat.new(4294967295_u32).to_s.should eq("4294967295.0") BigFloat.new(18446744073709551615_u64).to_s.should eq("1.8446744073709551615e+19") BigFloat.new(127_i8).to_s.should eq("127.0") BigFloat.new(32767_i16).to_s.should eq("32767.0") BigFloat.new(2147483647_i32).to_s.should eq("2147483647.0") BigFloat.new(9223372036854775807_i64).to_s.should eq("9.223372036854775807e+18") BigFloat.new(-128_i8).to_s.should eq("-128.0") BigFloat.new(-32768_i16).to_s.should eq("-32768.0") BigFloat.new(-2147483648_i32).to_s.should eq("-2147483648.0") BigFloat.new(-9223372036854775808_i64).to_s.should eq("-9.223372036854775808e+18") end it "raises if creating from infinity" do expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float32::INFINITY) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float64::INFINITY) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float32::INFINITY, precision: 128) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float64::INFINITY, precision: 128) } end it "raises if creating from NaN" do expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float32::NAN) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float64::NAN) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float32::NAN, precision: 128) } expect_raises(ArgumentError, "Can only construct from a finite number") { BigFloat.new(Float64::NAN, precision: 128) } end end describe "#<=>" do it "compares against NaNs" do (1.to_big_f <=> Float64::NAN).should be_nil (1.to_big_f <=> Float32::NAN).should be_nil (Float64::NAN <=> 1.to_big_f).should be_nil (Float32::NAN <=> 1.to_big_f).should be_nil typeof(1.to_big_f <=> Float64::NAN).should eq(Int32?) typeof(1.to_big_f <=> Float32::NAN).should eq(Int32?) typeof(Float64::NAN <=> 1.to_big_f).should eq(Int32?) typeof(Float32::NAN <=> 1.to_big_f).should eq(Int32?) typeof(1.to_big_f <=> 1.to_big_f).should eq(Int32) end end describe "unary #-" do it do bf = "0.12345".to_big_f (-bf).to_s.should eq("-0.12345") end it do bf = "61397953.0005354".to_big_f (-bf).to_s.should eq("-61397953.0005354") end it do bf = "395.009631567315769036".to_big_f (-bf).to_s.should eq("-395.009631567315769036") end end describe "#+" do it { ("1.0".to_big_f + "2.0".to_big_f).to_s.should eq("3.0") } it { ("0.04".to_big_f + "89.0001".to_big_f).to_s.should eq("89.0401") } it { ("-5.5".to_big_f + "5.5".to_big_f).to_s.should eq("0.0") } it { ("5.5".to_big_f + "-5.5".to_big_f).to_s.should eq("0.0") } end describe "#-" do it { ("1.0".to_big_f - "2.0".to_big_f).to_s.should eq("-1.0") } it { ("0.04".to_big_f - "89.0001".to_big_f).to_s.should eq("-88.9601") } it { ("-5.5".to_big_f - "5.5".to_big_f).to_s.should eq("-11.0") } it { ("5.5".to_big_f - "-5.5".to_big_f).to_s.should eq("11.0") } end describe "#*" do it { ("1.0".to_big_f * "2.0".to_big_f).to_s.should eq("2.0") } it { ("0.04".to_big_f * "89.0001".to_big_f).to_s.should eq("3.560004") } it { ("-5.5".to_big_f * "5.5".to_big_f).to_s.should eq("-30.25") } it { ("5.5".to_big_f * "-5.5".to_big_f).to_s.should eq("-30.25") } end describe "#/" do it { ("1.0".to_big_f / "2.0".to_big_f).to_s.should eq("0.5") } it { ("0.04".to_big_f / "89.0001".to_big_f).to_s.should eq("0.000449437697261014313467") } it { ("-5.5".to_big_f / "5.5".to_big_f).to_s.should eq("-1.0") } it { ("5.5".to_big_f / "-5.5".to_big_f).to_s.should eq("-1.0") } expect_raises(DivisionByZeroError) { 0.1.to_big_f / 0 } it { ("5.5".to_big_f / 16_u64).to_s.should eq("0.34375") } it { ("5.5".to_big_f / 16_u8).to_s.should eq("0.34375") } end describe "#//" do it { ("1.0".to_big_f // "2.0".to_big_f).to_s.should eq("0.0") } it { ("0.04".to_big_f // "89.0001".to_big_f).to_s.should eq("0.0") } it { ("-5.5".to_big_f // "5.5".to_big_f).to_s.should eq("-1.0") } it { ("5.5".to_big_f // "-5.5".to_big_f).to_s.should eq("-1.0") } expect_raises(DivisionByZeroError) { 0.1.to_big_f // 0 } it { ("5.5".to_big_f // 16_u64).to_s.should eq("0.0") } it { ("5.5".to_big_f // 16_u8).to_s.should eq("0.0") } it { ("-1".to_big_f // 2_u8).to_s.should eq("-1.0") } end describe "#**" do it { ("1.34".to_big_f ** 2).should be_close("1.7956".to_big_f, 1e-12) } it { ("-0.05".to_big_f ** 10).should be_close("0.00000000000009765625".to_big_f, 1e-12) } it { ("0.1234567890".to_big_f ** 3).should be_close("0.001881676371789154860897069".to_big_f, 1e-12) } it { ("1.34".to_big_f ** 2.to_big_i).should be_close("1.7956".to_big_f, 1e-12) } it { ("-0.05".to_big_f ** 10.to_big_i).should be_close("0.00000000000009765625".to_big_f, 1e-12) } it { ("0.1234567890".to_big_f ** 3.to_big_i).should be_close("0.001881676371789154860897069".to_big_f, 1e-12) } it { ("10".to_big_f ** -5).should be_close("0.00001".to_big_f, 1e-12) } it { ("0.1".to_big_f ** -5).should be_close("100000".to_big_f, 1e-12) } it { ("10".to_big_f ** (-5).to_big_i).should be_close("0.00001".to_big_f, 1e-12) } it { ("0.1".to_big_f ** (-5).to_big_i).should be_close("100000".to_big_f, 1e-12) } it { ("0".to_big_f ** 1.to_big_i).should eq(0.to_big_f) } it { ("0".to_big_f ** 0.to_big_i).should eq(1.to_big_f) } it { expect_raises(ArgumentError, "Cannot raise 0 to a negative power") { "0".to_big_f ** (-1).to_big_i } } end describe "#abs" do it { -5.to_big_f.abs.should eq(5) } it { 5.to_big_f.abs.should eq(5) } it { "-0.00001".to_big_f.abs.to_s.should eq("1.0e-5") } it { "0.00000000001".to_big_f.abs.to_s.should eq("1.0e-11") } end describe "#ceil" do it { 2.0.to_big_f.ceil.should eq(2) } it { 2.1.to_big_f.ceil.should eq(3) } it { 2.9.to_big_f.ceil.should eq(3) } end describe "#floor" do it { 2.1.to_big_f.floor.should eq(2) } it { 2.9.to_big_f.floor.should eq(2) } it { -2.9.to_big_f.floor.should eq(-3) } end describe "#trunc" do it { 2.1.to_big_f.trunc.should eq(2) } it { 2.9.to_big_f.trunc.should eq(2) } it { -2.9.to_big_f.trunc.should eq(-2) } end describe "#to_f" do it { 1.34.to_big_f.to_f.should eq(1.34) } it { 0.0001304.to_big_f.to_f.should eq(0.0001304) } it { 1.234567.to_big_f.to_f32.should eq(1.234567_f32) } end describe "#to_f!" do it { 1.34.to_big_f.to_f!.should eq(1.34) } it { 0.0001304.to_big_f.to_f!.should eq(0.0001304) } it { 1.234567.to_big_f.to_f32!.should eq(1.234567_f32) } end describe "#to_i" do it { 1.34.to_big_f.to_i.should eq(1) } it { 123.to_big_f.to_i.should eq(123) } it { -4321.to_big_f.to_i.should eq(-4321) } end describe "#to_i!" do it { 1.34.to_big_f.to_i!.should eq(1) } it { 123.to_big_f.to_i!.should eq(123) } it { -4321.to_big_f.to_i!.should eq(-4321) } end describe "#to_i64" do it "basic" do 1.to_big_f.to_i64.should eq 1 1.to_big_f.to_i64.should be_a(Int64) end it { expect_raises(OverflowError) { (2.0 ** 63).to_big_f.to_i64 } } it { expect_raises(OverflowError) { (BigFloat.new(2.0 ** 63, precision: 128) - 0.9999).to_i64 } } it { expect_raises(OverflowError) { (-9.223372036854778e+18).to_big_f.to_i64 } } # (-(2.0 ** 63)).prev_float end describe "#to_i64!" do it "basic" do 1.to_big_f.to_i64!.should eq 1 1.to_big_f.to_i64!.should be_a(Int64) end it "doesn't raise on overflow" do (2.0 ** 63).to_big_f.to_i64! (BigFloat.new(2.0 ** 63, precision: 128) - 0.9999).to_i64! (-9.223372036854778e+18).to_big_f.to_i64! # (-(2.0 ** 63)).prev_float end end describe "#to_u" do it { 1.34.to_big_f.to_u.should eq(1) } it { 123.to_big_f.to_u.should eq(123) } it { 4321.to_big_f.to_u.should eq(4321) } it do expect_raises(OverflowError) { -123.34.to_big_f.to_u } end end describe "#to_u!" do it { 1.34.to_big_f.to_u!.should eq(1) } it { 123.to_big_f.to_u!.should eq(123) } it { 4321.to_big_f.to_u!.should eq(4321) } end describe "#to_u64" do it "basic" do 1.to_big_f.to_u64.should eq 1 1.to_big_f.to_u64.should be_a(UInt64) end it { expect_raises(OverflowError) { (2.0 ** 64).to_big_f.to_u64 } } it { expect_raises(OverflowError) { (-1).to_big_f.to_u64 } } it { expect_raises(OverflowError) { (-0.0001).to_big_f.to_u64 } } end describe "#to_u64!" do it "basic" do 1.to_big_f.to_u64!.should eq 1 1.to_big_f.to_u64!.should be_a(UInt64) end it "doesn't raise on overflow" do (2.0 ** 64).to_big_f.to_u64! (-1).to_big_f.to_u64! (-0.0001).to_big_f.to_u64! end end describe "to_s" do it_converts_to_s "0".to_big_f, "0.0" it_converts_to_s "-0".to_big_f, "0.0" it_converts_to_s "0.000001".to_big_f, "1.0e-6" it_converts_to_s "48600000".to_big_f, "48600000.0" it_converts_to_s "12345678.87654".to_big_f, "12345678.87654" it_converts_to_s "12345678.87654321".to_big_f, "12345678.87654321" it_converts_to_s "9.000000000000987".to_big_f, "9.000000000000987" it_converts_to_s "12345678901234567".to_big_f, "1.2345678901234567e+16" it_converts_to_s "1234567890123456789".to_big_f, "1.234567890123456789e+18" it_converts_to_s ".01".to_big_f, "0.01" it_converts_to_s "-.01".to_big_f, "-0.01" it_converts_to_s ".1".to_big_f, "0.1" it_converts_to_s "-.1".to_big_f, "-0.1" it_converts_to_s "1".to_big_f, "1.0" it_converts_to_s "-1".to_big_f, "-1.0" it_converts_to_s "10".to_big_f, "10.0" it_converts_to_s "100".to_big_f, "100.0" it_converts_to_s "150".to_big_f, "150.0" it_converts_to_s (3.0).to_big_f, "3.0" it_converts_to_s 3.to_big_f, "3.0" it_converts_to_s -3.to_big_f, "-3.0" it_converts_to_s "1.23e45".to_big_f, "1.23e+45" it_converts_to_s "1e-234".to_big_f, "1.0e-234" it_converts_to_s Float64::MAX.to_s.to_big_f, "1.7976931348623157e+308" it_converts_to_s Float64::MIN_POSITIVE.to_s.to_big_f, "2.2250738585072014e-308" # since Float64-to-BigFloat conversion is always exact, but GMP floats have # a *minimum* precision equal to the machine word size, we cannot assume the # shortest round-trip property for Float64s converted this way it { assert_prints (0.1).to_big_f.to_s, "0.100000000000000005551" } it { assert_prints Float64::MAX.to_big_f.to_s, "1.79769313486231570815e+308" } it { assert_prints Float64::MIN_POSITIVE.to_big_f.to_s, "2.22507385850720138309e-308" } it { (2.to_big_f ** 7133786264).to_s.should end_with("e+2147483648") } # least power of two with a base-10 exponent greater than Int32::MAX it { (2.to_big_f ** -7133786264).to_s.should end_with("e-2147483649") } # least power of two with a base-10 exponent less than Int32::MIN it { (10.to_big_f ** 3000000000 * 1.5).to_s.should end_with("e+3000000000") } it { (10.to_big_f ** -3000000000 * 1.5).to_s.should end_with("e-3000000000") } {% unless flag?(:win32) && flag?(:gnu) %} it { (10.to_big_f ** 10000000000 * 1.5).to_s.should end_with("e+10000000000") } it { (10.to_big_f ** -10000000000 * 1.5).to_s.should end_with("e-10000000000") } {% end %} end describe "#inspect" do it { assert_prints "2.3".to_big_f.inspect, "2.3" } end describe "#round" do describe "rounding modes" do it "to_zero" do -1.5.to_big_f.round(:to_zero).should eq -1.0.to_big_f -1.0.to_big_f.round(:to_zero).should eq -1.0.to_big_f -0.9.to_big_f.round(:to_zero).should eq 0.0.to_big_f -0.5.to_big_f.round(:to_zero).should eq 0.0.to_big_f -0.1.to_big_f.round(:to_zero).should eq 0.0.to_big_f 0.0.to_big_f.round(:to_zero).should eq 0.0.to_big_f 0.1.to_big_f.round(:to_zero).should eq 0.0.to_big_f 0.5.to_big_f.round(:to_zero).should eq 0.0.to_big_f 0.9.to_big_f.round(:to_zero).should eq 0.0.to_big_f 1.0.to_big_f.round(:to_zero).should eq 1.0.to_big_f 1.5.to_big_f.round(:to_zero).should eq 1.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round(:to_zero).should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round(:to_zero).should eq "123456789123456789123.0".to_big_f "123456789123456789123.5".to_big_f.round(:to_zero).should eq "123456789123456789123.0".to_big_f "123456789123456789123.9".to_big_f.round(:to_zero).should eq "123456789123456789123.0".to_big_f "123456789123456789124.0".to_big_f.round(:to_zero).should eq "123456789123456789124.0".to_big_f "-123456789123456789123.0".to_big_f.round(:to_zero).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round(:to_zero).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.5".to_big_f.round(:to_zero).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.9".to_big_f.round(:to_zero).should eq "-123456789123456789123.0".to_big_f "-123456789123456789124.0".to_big_f.round(:to_zero).should eq "-123456789123456789124.0".to_big_f end end it "to_positive" do -1.5.to_big_f.round(:to_positive).should eq -1.0.to_big_f -1.0.to_big_f.round(:to_positive).should eq -1.0.to_big_f -0.9.to_big_f.round(:to_positive).should eq 0.0.to_big_f -0.5.to_big_f.round(:to_positive).should eq 0.0.to_big_f -0.1.to_big_f.round(:to_positive).should eq 0.0.to_big_f 0.0.to_big_f.round(:to_positive).should eq 0.0.to_big_f 0.1.to_big_f.round(:to_positive).should eq 1.0.to_big_f 0.5.to_big_f.round(:to_positive).should eq 1.0.to_big_f 0.9.to_big_f.round(:to_positive).should eq 1.0.to_big_f 1.0.to_big_f.round(:to_positive).should eq 1.0.to_big_f 1.5.to_big_f.round(:to_positive).should eq 2.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round(:to_positive).should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round(:to_positive).should eq "123456789123456789124.0".to_big_f "123456789123456789123.5".to_big_f.round(:to_positive).should eq "123456789123456789124.0".to_big_f "123456789123456789123.9".to_big_f.round(:to_positive).should eq "123456789123456789124.0".to_big_f "123456789123456789124.0".to_big_f.round(:to_positive).should eq "123456789123456789124.0".to_big_f "-123456789123456789123.0".to_big_f.round(:to_positive).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round(:to_positive).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.5".to_big_f.round(:to_positive).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.9".to_big_f.round(:to_positive).should eq "-123456789123456789123.0".to_big_f "-123456789123456789124.0".to_big_f.round(:to_positive).should eq "-123456789123456789124.0".to_big_f end end it "to_negative" do -1.5.to_big_f.round(:to_negative).should eq -2.0.to_big_f -1.0.to_big_f.round(:to_negative).should eq -1.0.to_big_f -0.9.to_big_f.round(:to_negative).should eq -1.0.to_big_f -0.5.to_big_f.round(:to_negative).should eq -1.0.to_big_f -0.1.to_big_f.round(:to_negative).should eq -1.0.to_big_f 0.0.to_big_f.round(:to_negative).should eq 0.0.to_big_f 0.1.to_big_f.round(:to_negative).should eq 0.0.to_big_f 0.5.to_big_f.round(:to_negative).should eq 0.0.to_big_f 0.9.to_big_f.round(:to_negative).should eq 0.0.to_big_f 1.0.to_big_f.round(:to_negative).should eq 1.0.to_big_f 1.5.to_big_f.round(:to_negative).should eq 1.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round(:to_negative).should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round(:to_negative).should eq "123456789123456789123.0".to_big_f "123456789123456789123.5".to_big_f.round(:to_negative).should eq "123456789123456789123.0".to_big_f "123456789123456789123.9".to_big_f.round(:to_negative).should eq "123456789123456789123.0".to_big_f "123456789123456789124.0".to_big_f.round(:to_negative).should eq "123456789123456789124.0".to_big_f "-123456789123456789123.0".to_big_f.round(:to_negative).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round(:to_negative).should eq "-123456789123456789124.0".to_big_f "-123456789123456789123.5".to_big_f.round(:to_negative).should eq "-123456789123456789124.0".to_big_f "-123456789123456789123.9".to_big_f.round(:to_negative).should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.0".to_big_f.round(:to_negative).should eq "-123456789123456789124.0".to_big_f end end it "ties_even" do -2.5.to_big_f.round(:ties_even).should eq -2.0.to_big_f -1.5.to_big_f.round(:ties_even).should eq -2.0.to_big_f -1.0.to_big_f.round(:ties_even).should eq -1.0.to_big_f -0.9.to_big_f.round(:ties_even).should eq -1.0.to_big_f -0.5.to_big_f.round(:ties_even).should eq 0.0.to_big_f -0.1.to_big_f.round(:ties_even).should eq 0.0.to_big_f 0.0.to_big_f.round(:ties_even).should eq 0.0.to_big_f 0.1.to_big_f.round(:ties_even).should eq 0.0.to_big_f 0.5.to_big_f.round(:ties_even).should eq 0.0.to_big_f 0.9.to_big_f.round(:ties_even).should eq 1.0.to_big_f 1.0.to_big_f.round(:ties_even).should eq 1.0.to_big_f 1.5.to_big_f.round(:ties_even).should eq 2.0.to_big_f 2.5.to_big_f.round(:ties_even).should eq 2.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round(:ties_even).should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round(:ties_even).should eq "123456789123456789123.0".to_big_f "123456789123456789123.5".to_big_f.round(:ties_even).should eq "123456789123456789124.0".to_big_f "123456789123456789123.9".to_big_f.round(:ties_even).should eq "123456789123456789124.0".to_big_f "123456789123456789124.0".to_big_f.round(:ties_even).should eq "123456789123456789124.0".to_big_f "123456789123456789124.5".to_big_f.round(:ties_even).should eq "123456789123456789124.0".to_big_f "-123456789123456789123.0".to_big_f.round(:ties_even).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round(:ties_even).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.5".to_big_f.round(:ties_even).should eq "-123456789123456789124.0".to_big_f "-123456789123456789123.9".to_big_f.round(:ties_even).should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.0".to_big_f.round(:ties_even).should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.5".to_big_f.round(:ties_even).should eq "-123456789123456789124.0".to_big_f end end it "ties_away" do -2.5.to_big_f.round(:ties_away).should eq -3.0.to_big_f -1.5.to_big_f.round(:ties_away).should eq -2.0.to_big_f -1.0.to_big_f.round(:ties_away).should eq -1.0.to_big_f -0.9.to_big_f.round(:ties_away).should eq -1.0.to_big_f -0.5.to_big_f.round(:ties_away).should eq -1.0.to_big_f -0.1.to_big_f.round(:ties_away).should eq 0.0.to_big_f 0.0.to_big_f.round(:ties_away).should eq 0.0.to_big_f 0.1.to_big_f.round(:ties_away).should eq 0.0.to_big_f 0.5.to_big_f.round(:ties_away).should eq 1.0.to_big_f 0.9.to_big_f.round(:ties_away).should eq 1.0.to_big_f 1.0.to_big_f.round(:ties_away).should eq 1.0.to_big_f 1.5.to_big_f.round(:ties_away).should eq 2.0.to_big_f 2.5.to_big_f.round(:ties_away).should eq 3.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round(:ties_away).should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round(:ties_away).should eq "123456789123456789123.0".to_big_f "123456789123456789123.5".to_big_f.round(:ties_away).should eq "123456789123456789124.0".to_big_f "123456789123456789123.9".to_big_f.round(:ties_away).should eq "123456789123456789124.0".to_big_f "123456789123456789124.0".to_big_f.round(:ties_away).should eq "123456789123456789124.0".to_big_f "123456789123456789124.5".to_big_f.round(:ties_away).should eq "123456789123456789125.0".to_big_f "-123456789123456789123.0".to_big_f.round(:ties_away).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round(:ties_away).should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.5".to_big_f.round(:ties_away).should eq "-123456789123456789124.0".to_big_f "-123456789123456789123.9".to_big_f.round(:ties_away).should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.0".to_big_f.round(:ties_away).should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.5".to_big_f.round(:ties_away).should eq "-123456789123456789125.0".to_big_f end end it "default (=ties_even)" do -2.5.to_big_f.round.should eq -2.0.to_big_f -1.5.to_big_f.round.should eq -2.0.to_big_f -1.0.to_big_f.round.should eq -1.0.to_big_f -0.9.to_big_f.round.should eq -1.0.to_big_f -0.5.to_big_f.round.should eq 0.0.to_big_f -0.1.to_big_f.round.should eq 0.0.to_big_f 0.0.to_big_f.round.should eq 0.0.to_big_f 0.1.to_big_f.round.should eq 0.0.to_big_f 0.5.to_big_f.round.should eq 0.0.to_big_f 0.9.to_big_f.round.should eq 1.0.to_big_f 1.0.to_big_f.round.should eq 1.0.to_big_f 1.5.to_big_f.round.should eq 2.0.to_big_f 2.5.to_big_f.round.should eq 2.0.to_big_f with_precision(256) do "123456789123456789123.0".to_big_f.round.should eq "123456789123456789123.0".to_big_f "123456789123456789123.1".to_big_f.round.should eq "123456789123456789123.0".to_big_f "123456789123456789123.5".to_big_f.round.should eq "123456789123456789124.0".to_big_f "123456789123456789123.9".to_big_f.round.should eq "123456789123456789124.0".to_big_f "123456789123456789124.0".to_big_f.round.should eq "123456789123456789124.0".to_big_f "123456789123456789124.5".to_big_f.round.should eq "123456789123456789124.0".to_big_f "-123456789123456789123.0".to_big_f.round.should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.1".to_big_f.round.should eq "-123456789123456789123.0".to_big_f "-123456789123456789123.5".to_big_f.round.should eq "-123456789123456789124.0".to_big_f "-123456789123456789123.9".to_big_f.round.should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.0".to_big_f.round.should eq "-123456789123456789124.0".to_big_f "-123456789123456789124.5".to_big_f.round.should eq "-123456789123456789124.0".to_big_f end end end end describe "#integer?" do it { BigFloat.zero.integer?.should be_true } it { 1.to_big_f.integer?.should be_true } it { 1.2.to_big_f.integer?.should be_false } end it "#hash" do b = 123.to_big_f b.hash.should eq(b.to_f64.hash) end it "clones" do x = 1.to_big_f x.clone.should eq(x) end end describe "BigFloat Math" do it ".ilogb" do Math.ilogb(0.2.to_big_f).should eq(-3) Math.ilogb(123.45.to_big_f).should eq(6) Math.ilogb(2.to_big_f ** 1_000_000_000).should eq(1_000_000_000) {% unless flag?(:win32) && flag?(:gnu) %} Math.ilogb(2.to_big_f ** 100_000_000_000).should eq(100_000_000_000) Math.ilogb(2.to_big_f ** -100_000_000_000).should eq(-100_000_000_000) {% end %} expect_raises(ArgumentError) { Math.ilogb(0.to_big_f) } end it ".logb" do Math.logb(0.2.to_big_f).should eq(-3.to_big_f) Math.logb(123.45.to_big_f).should eq(6.to_big_f) Math.logb(2.to_big_f ** 1_000_000_000).should eq(1_000_000_000.to_big_f) {% unless flag?(:win32) && flag?(:gnu) %} Math.logb(2.to_big_f ** 100_000_000_000).should eq(100_000_000_000.to_big_f) Math.logb(2.to_big_f ** -100_000_000_000).should eq(-100_000_000_000.to_big_f) {% end %} expect_raises(ArgumentError) { Math.logb(0.to_big_f) } end it ".ldexp" do Math.ldexp(0.2.to_big_f, 2).should eq(0.8.to_big_f) Math.ldexp(0.2.to_big_f, -2).should eq(0.05.to_big_f) Math.ldexp(1.to_big_f, 1_000_000_000).should eq(2.to_big_f ** 1_000_000_000) {% unless flag?(:win32) && flag?(:gnu) %} Math.ldexp(1.to_big_f, 100_000_000_000).should eq(2.to_big_f ** 100_000_000_000) Math.ldexp(1.to_big_f, -100_000_000_000).should eq(0.5.to_big_f ** 100_000_000_000) {% end %} end it ".scalbn" do Math.scalbn(0.2.to_big_f, 2).should eq(0.8.to_big_f) Math.scalbn(0.2.to_big_f, -2).should eq(0.05.to_big_f) Math.scalbn(1.to_big_f, 1_000_000_000).should eq(2.to_big_f ** 1_000_000_000) {% unless flag?(:win32) && flag?(:gnu) %} Math.scalbn(1.to_big_f, 100_000_000_000).should eq(2.to_big_f ** 100_000_000_000) Math.scalbn(1.to_big_f, -100_000_000_000).should eq(0.5.to_big_f ** 100_000_000_000) {% end %} end it ".scalbln" do Math.scalbln(0.2.to_big_f, 2).should eq(0.8.to_big_f) Math.scalbln(0.2.to_big_f, -2).should eq(0.05.to_big_f) Math.scalbln(1.to_big_f, 1_000_000_000).should eq(2.to_big_f ** 1_000_000_000) {% unless flag?(:win32) && flag?(:gnu) %} Math.scalbln(1.to_big_f, 100_000_000_000).should eq(2.to_big_f ** 100_000_000_000) Math.scalbln(1.to_big_f, -100_000_000_000).should eq(0.5.to_big_f ** 100_000_000_000) {% end %} end it ".frexp" do Math.frexp(0.to_big_f).should eq({0.0, 0}) Math.frexp(1.to_big_f).should eq({0.5, 1}) Math.frexp(0.2.to_big_f).should eq({0.8, -2}) Math.frexp(2.to_big_f ** 63).should eq({0.5, 64}) Math.frexp(2.to_big_f ** 64).should eq({0.5, 65}) Math.frexp(2.to_big_f ** 200).should eq({0.5, 201}) Math.frexp(2.to_big_f ** -200).should eq({0.5, -199}) Math.frexp(2.to_big_f ** 0x7FFFFFFF).should eq({0.5, 0x80000000}) Math.frexp(2.to_big_f ** 0x80000000).should eq({0.5, 0x80000001}) Math.frexp(2.to_big_f ** 0xFFFFFFFF).should eq({0.5, 0x100000000}) Math.frexp(1.75 * 2.to_big_f ** 0x123456789).should eq({0.875, 0x12345678A}) Math.frexp(2.to_big_f ** -0x80000000).should eq({0.5, -0x7FFFFFFF}) Math.frexp(2.to_big_f ** -0x80000001).should eq({0.5, -0x80000000}) Math.frexp(2.to_big_f ** -0x100000000).should eq({0.5, -0xFFFFFFFF}) Math.frexp(1.75 * 2.to_big_f ** -0x123456789).should eq({0.875, -0x123456788}) Math.frexp(-(2.to_big_f ** 0x7FFFFFFF)).should eq({-0.5, 0x80000000}) Math.frexp(-(2.to_big_f ** -0x100000000)).should eq({-0.5, -0xFFFFFFFF}) end it ".copysign" do Math.copysign(3.to_big_f, 2.to_big_f).should eq(3.to_big_f) Math.copysign(3.to_big_f, 0.to_big_f).should eq(3.to_big_f) Math.copysign(3.to_big_f, -2.to_big_f).should eq(-3.to_big_f) Math.copysign(0.to_big_f, 2.to_big_f).should eq(0.to_big_f) Math.copysign(0.to_big_f, 0.to_big_f).should eq(0.to_big_f) Math.copysign(0.to_big_f, -2.to_big_f).should eq(0.to_big_f) Math.copysign(-3.to_big_f, 2.to_big_f).should eq(3.to_big_f) Math.copysign(-3.to_big_f, 0.to_big_f).should eq(3.to_big_f) Math.copysign(-3.to_big_f, -2.to_big_f).should eq(-3.to_big_f) end it ".sqrt" do Math.sqrt(BigFloat.new("1" + "0"*48)).should eq(BigFloat.new("1" + "0"*24)) end end