From 81b038eed250a2ce44b2c55edebb43a2b63a3ce5 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Wed, 12 Dec 2018 16:32:13 -0300 Subject: [PATCH 1/7] Add convert as primitive to be used on #to_* methods cast will be used for .as(T) expressions only. --- src/compiler/crystal/codegen/primitives.cr | 3 +++ src/primitives.cr | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/compiler/crystal/codegen/primitives.cr b/src/compiler/crystal/codegen/primitives.cr index b749f7c573f5..8cf04da4cb99 100644 --- a/src/compiler/crystal/codegen/primitives.cr +++ b/src/compiler/crystal/codegen/primitives.cr @@ -18,6 +18,9 @@ class Crystal::CodeGenVisitor when "binary" codegen_primitive_binary node, target_def, call_args when "cast" + # TODO 0.28.0 delete :cast + codegen_primitive_cast node, target_def, call_args + when "convert" codegen_primitive_cast node, target_def, call_args when "allocate" codegen_primitive_allocate node, target_def, call_args diff --git a/src/primitives.cr b/src/primitives.cr index f6adf07b3074..413f0faa903d 100644 --- a/src/primitives.cr +++ b/src/primitives.cr @@ -280,6 +280,8 @@ end to_u8: UInt8, to_u16: UInt16, to_u32: UInt32, to_u64: UInt64, to_u128: UInt128, to_f32: Float32, to_f64: Float64, } %} + # TODO 0.28.0 replace with @[Primitive(:convert)] + # Returns `self` converted to `{{type}}`. @[Primitive(:cast)] def {{name.id}} : {{type}} From 4ae8cc9e3a008d18e0a41ebccc6afbd11def2567 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Wed, 12 Dec 2018 17:00:36 -0300 Subject: [PATCH 2/7] Add Int#to_*! methods --- spec/compiler/codegen/convert_spec.cr | 23 ++++++++++++++++++++++ src/compiler/crystal/codegen/primitives.cr | 2 ++ src/primitives.cr | 7 +++++++ 3 files changed, 32 insertions(+) create mode 100644 spec/compiler/codegen/convert_spec.cr diff --git a/spec/compiler/codegen/convert_spec.cr b/spec/compiler/codegen/convert_spec.cr new file mode 100644 index 000000000000..69afd94b4927 --- /dev/null +++ b/spec/compiler/codegen/convert_spec.cr @@ -0,0 +1,23 @@ +require "../../spec_helper" + +describe "Code gen: convert primitives" do + describe "to_*!" do + it "works from negative values to unsigned types" do + run(%( + -1.to_u! == 4294967295_u32 + )).to_b.should be_true + end + + it "works from greater values to smaller types" do + run(%( + 47866.to_i8! == -6_i8 + )).to_b.should be_true + end + + it "preserves negative sign" do + run(%( + -1_i8.to_i! == -1_i32 + )).to_b.should be_true + end + end +end diff --git a/src/compiler/crystal/codegen/primitives.cr b/src/compiler/crystal/codegen/primitives.cr index 8cf04da4cb99..39025479c857 100644 --- a/src/compiler/crystal/codegen/primitives.cr +++ b/src/compiler/crystal/codegen/primitives.cr @@ -22,6 +22,8 @@ class Crystal::CodeGenVisitor codegen_primitive_cast node, target_def, call_args when "convert" codegen_primitive_cast node, target_def, call_args + when "unchecked_convert" + codegen_primitive_cast node, target_def, call_args when "allocate" codegen_primitive_allocate node, target_def, call_args when "pointer_malloc" diff --git a/src/primitives.cr b/src/primitives.cr index 413f0faa903d..982e26412332 100644 --- a/src/primitives.cr +++ b/src/primitives.cr @@ -286,6 +286,13 @@ end @[Primitive(:cast)] def {{name.id}} : {{type}} end + + # TODO 0.28.0 replace with @[Primitive(:unchecked_convert)] + + # Returns `self` converted to `{{type}}`. + @[Primitive(:cast)] + def {{name.id}}! : {{type}} + end {% end %} {% for num2 in nums %} From 051a6d321a27482f504ce5ce247b1b878240d523 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Wed, 19 Dec 2018 15:40:24 -0300 Subject: [PATCH 3/7] Add Int.new! Float.new! variants new! initializers use #to_*! to avoid overflow if the value is out of range of the target type --- spec/std/number_spec.cr | 42 ++++++++++++++++++++++++++++++++++ src/float.cr | 10 +++++++++ src/int.cr | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/spec/std/number_spec.cr b/spec/std/number_spec.cr index 6cdeac80e086..d11701c8c26d 100644 --- a/spec/std/number_spec.cr +++ b/spec/std/number_spec.cr @@ -1,6 +1,48 @@ require "spec" +private macro it_initializes_from_value_to(number_type) + it "initialize from value to {{number_type}}" do + {{number_type}}.new(1).should be_a({{number_type}}) + {{number_type}}.new(1).should eq(1) + + {{number_type}}.new(1u32).should be_a({{number_type}}) + {{number_type}}.new(1u32).should eq(1) + + {{number_type}}.new(1.0).should be_a({{number_type}}) + {{number_type}}.new(1.0).should eq(1) + end + + it "unchecked initialize from value to {{number_type}}" do + {{number_type}}.new!(1).should be_a({{number_type}}) + {{number_type}}.new!(1).should eq(1) + + {{number_type}}.new!(1u32).should be_a({{number_type}}) + {{number_type}}.new!(1u32).should eq(1) + + {{number_type}}.new!(1.0).should be_a({{number_type}}) + {{number_type}}.new!(1.0).should eq(1) + end +end + describe "Number" do + it_initializes_from_value_to Int8 + it_initializes_from_value_to Int16 + it_initializes_from_value_to Int32 + it_initializes_from_value_to Int64 + + it_initializes_from_value_to UInt8 + it_initializes_from_value_to UInt16 + it_initializes_from_value_to UInt32 + it_initializes_from_value_to UInt64 + + {% if flag?(:bits64) %} + it_initializes_from_value_to Int128 + it_initializes_from_value_to UInt128 + {% end %} + + it_initializes_from_value_to Float32 + it_initializes_from_value_to Float64 + describe "significant" do it "10 base" do 1234.567.significant(1).should eq(1000) diff --git a/src/float.cr b/src/float.cr index fed35eb35987..0ff554bc2b57 100644 --- a/src/float.cr +++ b/src/float.cr @@ -139,6 +139,11 @@ struct Float32 value.to_f32 end + # Returns a `Float32` by invoking `to_f32!` on *value*. + def self.new!(value) + value.to_f32! + end + def ceil LibM.ceil_f32(self) end @@ -223,6 +228,11 @@ struct Float64 value.to_f64 end + # Returns a `Float64` by invoking `to_f64!` on *value*. + def Float64.new!(value) + value.to_f64! + end + def ceil LibM.ceil_f64(self) end diff --git a/src/int.cr b/src/int.cr index 297c97ffccc4..a4b0b708468d 100644 --- a/src/int.cr +++ b/src/int.cr @@ -615,6 +615,11 @@ struct Int8 value.to_i8 end + # Returns an `Int8` by invoking `to_i8!` on *value*. + def self.new!(value) + value.to_i8! + end + def - 0_i8 - self end @@ -637,6 +642,11 @@ struct Int16 value.to_i16 end + # Returns an `Int16` by invoking `to_i16!` on *value*. + def self.new!(value) + value.to_i16! + end + def - 0_i16 - self end @@ -659,6 +669,11 @@ struct Int32 value.to_i32 end + # Returns an `Int32` by invoking `to_i32!` on *value*. + def self.new!(value) + value.to_i32! + end + def - 0 - self end @@ -681,6 +696,11 @@ struct Int64 value.to_i64 end + # Returns an `Int64` by invoking `to_i64!` on *value*. + def self.new!(value) + value.to_i64! + end + def - 0_i64 - self end @@ -704,6 +724,11 @@ struct Int128 value.to_i128 end + # Returns an `Int128` by invoking `to_i128!` on *value*. + def self.new!(value) + value.to_i128! + end + def - # TODO: use 0_i128 - self Int128.new(0) - self @@ -727,6 +752,11 @@ struct UInt8 value.to_u8 end + # Returns an `UInt8` by invoking `to_u8!` on *value*. + def self.new!(value) + value.to_u8! + end + def abs self end @@ -749,6 +779,11 @@ struct UInt16 value.to_u16 end + # Returns an `UInt16` by invoking `to_u16!` on *value*. + def self.new!(value) + value.to_u16! + end + def abs self end @@ -771,6 +806,11 @@ struct UInt32 value.to_u32 end + # Returns an `UInt32` by invoking `to_u32!` on *value*. + def self.new!(value) + value.to_u32! + end + def abs self end @@ -793,6 +833,11 @@ struct UInt64 value.to_u64 end + # Returns an `UInt64` by invoking `to_u64!` on *value*. + def self.new!(value) + value.to_u64! + end + def abs self end @@ -816,6 +861,11 @@ struct UInt128 value.to_u128 end + # Returns an `UInt128` by invoking `to_u128!` on *value*. + def self.new!(value) + value.to_u128! + end + def abs self end From 7136750f398442b80c8388a1eb184bcd6e920de0 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Thu, 22 Nov 2018 12:15:39 -0300 Subject: [PATCH 4/7] Add Int#&**. Refactor Int#** due to possible unwanted overflow. Adding noted for future raising of OverflowError --- spec/std/int_spec.cr | 36 ++++++++++++++++++++++++++++++++++++ src/int.cr | 27 ++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/spec/std/int_spec.cr b/spec/std/int_spec.cr index f96fe6aed3de..22bce4ee1297 100644 --- a/spec/std/int_spec.cr +++ b/spec/std/int_spec.cr @@ -46,6 +46,42 @@ describe "Int" do end end + describe "&**" do + it "with positive Int32" do + x = 2 &** 2 + x.should eq(4) + x.should be_a(Int32) + + x = 2 &** 0 + x.should eq(1) + x.should be_a(Int32) + end + + it "with UInt8" do + x = 2_u8 &** 2 + x.should eq(4) + x.should be_a(UInt8) + end + + it "raises with negative exponent" do + expect_raises(ArgumentError, "Cannot raise an integer to a negative integer power, use floats for that") do + 2 &** -1 + end + end + + it "works with large integers" do + x = 51_i64 &** 11 + x.should eq(6071163615208263051_i64) + x.should be_a(Int64) + end + + it "wraps with larger integers" do + x = 51_i64 &** 12 + x.should eq(-3965304877440961871_i64) + x.should be_a(Int64) + end + end + describe "#===(:Char)" do it { (99 === 'c').should be_true } it { (99_u8 === 'c').should be_true } diff --git a/src/int.cr b/src/int.cr index a4b0b708468d..f09ca4bdffd2 100644 --- a/src/int.cr +++ b/src/int.cr @@ -274,8 +274,33 @@ struct Int k = self while exponent > 0 result *= k if exponent & 0b1 != 0 - k *= k exponent = exponent.unsafe_shr(1) + k *= k if exponent > 0 + end + result + end + + # Returns the value of raising `self` to the power of *exponent*. + # + # Raises `ArgumentError` if *exponent* is negative: if this is needed, + # either use a float base or a float exponent. + # + # ``` + # 2 &** 3 # => 8 + # 2 &** 0 # => 1 + # 2 &** -1 # ArgumentError + # ``` + def &**(exponent : Int) : self + if exponent < 0 + raise ArgumentError.new "Cannot raise an integer to a negative integer power, use floats for that" + end + + result = self.class.new(1) + k = self + while exponent > 0 + result &*= k if exponent & 0b1 != 0 + exponent = exponent.unsafe_shr(1) + k &*= k if exponent > 0 end result end From 7f87fa292be48bb3b97542bd849134e3f55369c0 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Tue, 18 Dec 2018 17:38:34 -0300 Subject: [PATCH 5/7] Add Enum#to_*! methods --- src/enum.cr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/enum.cr b/src/enum.cr index ee953b53f15d..8abd09a8196a 100644 --- a/src/enum.cr +++ b/src/enum.cr @@ -164,6 +164,11 @@ struct Enum def to_{{name.id}} : {{type}} value.to_{{name.id}} end + + # Returns the value of this enum member as a `{{type}}` + def to_{{name.id}}! : {{type}} + value.to_{{name.id}}! + end {% end %} # Returns the enum member that results from adding *other* From aedbdaf8f868a221f6ec1cc6df4062fad80d170a Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Tue, 18 Dec 2018 17:41:13 -0300 Subject: [PATCH 6/7] Add BigInt#to_*! methods Add BigDecimal#to_big_i, BigDecimal#to_big_u Note: BigRational does not have to_i / to_u methods --- spec/std/big/big_decimal_spec.cr | 15 +++++ spec/std/big/big_float_spec.cr | 18 ++++++ spec/std/big/big_int_spec.cr | 8 +-- spec/std/big/big_rational_spec.cr | 18 ++++++ src/big/big_decimal.cr | 101 ++++++++++++++++++++++++++---- src/big/big_float.cr | 52 +++++++++++++++ src/big/big_int.cr | 60 ++++++++++++++++++ src/big/big_rational.cr | 12 ++++ 8 files changed, 269 insertions(+), 15 deletions(-) diff --git a/spec/std/big/big_decimal_spec.cr b/spec/std/big/big_decimal_spec.cr index ff6cf71b3117..25f215a90171 100644 --- a/spec/std/big/big_decimal_spec.cr +++ b/spec/std/big/big_decimal_spec.cr @@ -323,6 +323,21 @@ describe BigDecimal do bd2.to_f.should eq -0.00123 bd3.to_f.should eq 123.0 bd4.to_f.should eq -123.0 + + bd1.to_i!.should eq 0 + bd2.to_i!.should eq 0 + bd3.to_i!.should eq 123 + bd4.to_i!.should eq -123 + + bd1.to_u!.should eq 0 + bd2.to_u!.should eq 0 + bd3.to_u!.should eq 123 + bd4.to_u!.should eq 123 + + bd1.to_f!.should eq 0.00123 + bd2.to_f!.should eq -0.00123 + bd3.to_f!.should eq 123.0 + bd4.to_f!.should eq -123.0 end it "hashes" do diff --git a/spec/std/big/big_float_spec.cr b/spec/std/big/big_float_spec.cr index 7a7f00a54682..18bcc04ae8e1 100644 --- a/spec/std/big/big_float_spec.cr +++ b/spec/std/big/big_float_spec.cr @@ -147,18 +147,36 @@ describe "BigFloat" do 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_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_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_s" do it { "0".to_big_f.to_s.should eq("0") } it { "0.000001".to_big_f.to_s.should eq("0.000001") } diff --git a/spec/std/big/big_int_spec.cr b/spec/std/big/big_int_spec.cr index 6fb89c919d25..b254eda9f381 100644 --- a/spec/std/big/big_int_spec.cr +++ b/spec/std/big/big_int_spec.cr @@ -296,13 +296,13 @@ describe "BigInt" do it "can be casted into other Number types" do big = BigInt.new(1234567890) big.to_i.should eq(1234567890) - big.to_i8.should eq(-46) - big.to_i16.should eq(722) + big.to_i8!.should eq(-46) + big.to_i16!.should eq(722) big.to_i32.should eq(1234567890) big.to_i64.should eq(1234567890) big.to_u.should eq(1234567890) - big.to_u8.should eq(210) - big.to_u16.should eq(722) + big.to_u8!.should eq(210) + big.to_u16!.should eq(722) big.to_u32.should eq(1234567890) u64 = big.to_u64 diff --git a/spec/std/big/big_rational_spec.cr b/spec/std/big/big_rational_spec.cr index 702904be1255..a70d192dc334 100644 --- a/spec/std/big/big_rational_spec.cr +++ b/spec/std/big/big_rational_spec.cr @@ -60,18 +60,36 @@ describe BigRational do r.to_f64.should be_close(f, 0.001) end + it "#to_f64!" do + r = br(10, 3) + f = 10.to_f64 / 3.to_f64 + r.to_f64!.should be_close(f, 0.001) + end + it "#to_f" do r = br(10, 3) f = 10.to_f64 / 3.to_f64 r.to_f.should be_close(f, 0.001) end + it "#to_f!" do + r = br(10, 3) + f = 10.to_f64 / 3.to_f64 + r.to_f!.should be_close(f, 0.001) + end + it "#to_f32" do r = br(10, 3) f = 10.to_f32 / 3.to_f32 r.to_f32.should be_close(f, 0.001) end + it "#to_f32!" do + r = br(10, 3) + f = 10.to_f32 / 3.to_f32 + r.to_f32!.should be_close(f, 0.001) + end + it "#to_big_f" do r = br(10, 3) f = 10.to_big_f / 3.to_big_f diff --git a/src/big/big_decimal.cr b/src/big/big_decimal.cr index 8171e9122908..5efe0e9aefad 100644 --- a/src/big/big_decimal.cr +++ b/src/big/big_decimal.cr @@ -307,28 +307,33 @@ struct BigDecimal < Number self end - # Converts to `Int64`. Truncates anything on the right side of the decimal point. - def to_i64 + # Converts to `BigInt`. Truncates anything on the right side of the decimal point. + def to_big_i if @value >= 0 - (@value / TEN ** @scale).to_i64 + (@value / TEN ** @scale) else - -(@value.abs / TEN ** @scale).to_i64 + -(@value.abs / TEN ** @scale) end end + # Converts to `Int64`. Truncates anything on the right side of the decimal point. + def to_i64 + to_big_i.to_i64 + end + # Converts to `Int32`. Truncates anything on the right side of the decimal point. def to_i32 - to_i64.to_i32 + to_big_i.to_i32 end # Converts to `Int16`. Truncates anything on the right side of the decimal point. def to_i16 - to_i64.to_i16 + to_big_i.to_i16 end # Converts to `Int8`. Truncates anything on the right side of the decimal point. def to_i8 - to_i64.to_i8 + to_big_i.to_i8 end # Converts to `Int32`. Truncates anything on the right side of the decimal point. @@ -336,28 +341,57 @@ struct BigDecimal < Number to_i32 end + # Converts to `Int8`. Truncates anything on the right side of the decimal point. + def to_i8! + to_big_i.to_i8! + end + + # Converts to `Int16`. Truncates anything on the right side of the decimal point. + def to_i16! + to_big_i.to_i16! + end + + # Converts to `Int32`. Truncates anything on the right side of the decimal point. + def to_i32! + to_big_i.to_i32! + end + + # Converts to `Int64`. Truncates anything on the right side of the decimal point. + def to_i64! + to_big_i.to_i64! + end + + # Converts to `Int32`. Truncates anything on the right side of the decimal point. + def to_i! + to_i32! + end + + private def to_big_u + (@value.abs / TEN ** @scale) + end + # Converts to `UInt64`. Truncates anything on the right side of the decimal point, # converting negative to positive. def to_u64 - (@value.abs / TEN ** @scale).to_u64 + to_big_u.to_u64 end # Converts to `UInt32`. Truncates anything on the right side of the decimal point, # converting negative to positive. def to_u32 - to_u64.to_u32 + to_big_u.to_u32 end # Converts to `UInt16`. Truncates anything on the right side of the decimal point, # converting negative to positive. def to_u16 - to_u64.to_u16 + to_big_u.to_u16 end # Converts to `UInt8`. Truncates anything on the right side of the decimal point, # converting negative to positive. def to_u8 - to_u64.to_u8 + to_big_u.to_u8 end # Converts to `UInt32`. Truncates anything on the right side of the decimal point, @@ -366,6 +400,36 @@ struct BigDecimal < Number to_u32 end + # Converts to `UInt8`. Truncates anything on the right side of the decimal point, + # converting negative to positive. + def to_u8! + to_big_u.to_u8! + end + + # Converts to `UInt16`. Truncates anything on the right side of the decimal point, + # converting negative to positive. + def to_u16! + to_big_u.to_u16! + end + + # Converts to `UInt32`. Truncates anything on the right side of the decimal point, + # converting negative to positive. + def to_u32! + to_big_u.to_u32! + end + + # Converts to `UInt64`. Truncates anything on the right side of the decimal point, + # converting negative to positive. + def to_u64! + to_big_u.to_u64! + end + + # Converts to `UInt32`. Truncates anything on the right side of the decimal point, + # converting negative to positive. + def to_u! + to_u32! + end + # Converts to `Float64`. def to_f64 to_s.to_f64 @@ -381,6 +445,21 @@ struct BigDecimal < Number to_f64 end + # Converts to `Float32`. + def to_f32! + to_f64.to_f32! + end + + # Converts to `Float64`. + def to_f64! + to_f64 + end + + # Converts to `Float64`. + def to_f! + to_f64! + end + # Converts to `BigFloat`. def to_big_f BigFloat.new(to_s) diff --git a/src/big/big_float.cr b/src/big/big_float.cr index e582f99bbdac..e3132132f54a 100644 --- a/src/big/big_float.cr +++ b/src/big/big_float.cr @@ -172,6 +172,18 @@ struct BigFloat < Float to_f64 end + def to_f32! + to_f64.to_f32! + end + + def to_f64! + to_f64 + end + + def to_f! + to_f64! + end + def to_big_f self end @@ -196,6 +208,26 @@ struct BigFloat < Float to_i32 end + def to_i! + to_i32! + end + + def to_i8! + LibGMP.mpf_get_si(self).to_i8! + end + + def to_i16! + LibGMP.mpf_get_si(self).to_i16! + end + + def to_i32! + LibGMP.mpf_get_si(self).to_i32! + end + + def to_i64! + LibGMP.mpf_get_si(self) + end + def to_u64 LibGMP.mpf_get_ui(self) end @@ -216,6 +248,26 @@ struct BigFloat < Float to_u32 end + def to_u! + to_u32! + end + + def to_u8! + LibGMP.mpf_get_ui(self).to_u8! + end + + def to_u16! + LibGMP.mpf_get_ui(self).to_u16! + end + + def to_u32! + LibGMP.mpf_get_ui(self).to_u32! + end + + def to_u64! + LibGMP.mpf_get_ui(self) + end + def to_unsafe mpf end diff --git a/src/big/big_int.cr b/src/big/big_int.cr index 880ad36f254c..635ec4eee0b7 100644 --- a/src/big/big_int.cr +++ b/src/big/big_int.cr @@ -414,6 +414,30 @@ struct BigInt < Int end end + def to_i! + to_i32! + end + + def to_i8! + LibGMP.get_si(self).to_i8! + end + + def to_i16! + LibGMP.get_si(self).to_i16! + end + + def to_i32! + LibGMP.get_si(self).to_i32! + end + + def to_i64! + if LibGMP::Long == Int64 || (self <= Int32::MAX && self >= Int32::MIN) + LibGMP.get_si(self).to_i64! + else + to_s.to_i64 + end + end + def to_u to_u32 end @@ -438,6 +462,30 @@ struct BigInt < Int end end + def to_u! + to_u32! + end + + def to_u8! + LibGMP.get_ui(self).to_u8! + end + + def to_u16! + LibGMP.get_ui(self).to_u16! + end + + def to_u32! + LibGMP.get_ui(self).to_u32! + end + + def to_u64! + if LibGMP::Long == Int64 || (self <= Int32::MAX && self >= Int32::MIN) + LibGMP.get_ui(self).to_u64! + else + to_s.to_u64 + end + end + def to_f to_f64 end @@ -450,6 +498,18 @@ struct BigInt < Int LibGMP.get_d(self) end + def to_f! + to_f64! + end + + def to_f32! + LibGMP.get_d(self).to_f32! + end + + def to_f64! + LibGMP.get_d(self) + end + def to_big_i self end diff --git a/src/big/big_rational.cr b/src/big/big_rational.cr index f2ff5e961ecb..508b390f224a 100644 --- a/src/big/big_rational.cr +++ b/src/big/big_rational.cr @@ -177,6 +177,18 @@ struct BigRational < Number LibGMP.mpq_get_d(mpq) end + def to_f32! + to_f64.to_f32! + end + + def to_f64! + to_f64 + end + + def to_f! + to_f64! + end + def to_big_f BigFloat.new { |mpf| LibGMP.mpf_set_q(mpf, mpq) } end From 1edf4a8b143ba1f0c87037bce8dde3a985951672 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Wed, 2 Jan 2019 17:01:35 -0300 Subject: [PATCH 7/7] Refactor: BigInt range check --- src/big/big_int.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/big/big_int.cr b/src/big/big_int.cr index 635ec4eee0b7..321841976207 100644 --- a/src/big/big_int.cr +++ b/src/big/big_int.cr @@ -407,7 +407,7 @@ struct BigInt < Int end def to_i64 - if LibGMP::Long == Int64 || (self <= Int32::MAX && self >= Int32::MIN) + if LibGMP::Long == Int64 || (Int32::MIN <= self <= Int32::MAX) LibGMP.get_si(self).to_i64 else to_s.to_i64 @@ -431,7 +431,7 @@ struct BigInt < Int end def to_i64! - if LibGMP::Long == Int64 || (self <= Int32::MAX && self >= Int32::MIN) + if LibGMP::Long == Int64 || (Int32::MIN <= self <= Int32::MAX) LibGMP.get_si(self).to_i64! else to_s.to_i64 @@ -455,7 +455,7 @@ struct BigInt < Int end def to_u64 - if LibGMP::ULong == UInt64 || (self <= UInt32::MAX && self >= UInt32::MIN) + if LibGMP::ULong == UInt64 || (UInt32::MIN <= self <= UInt32::MAX) LibGMP.get_ui(self).to_u64 else to_s.to_u64 @@ -479,7 +479,7 @@ struct BigInt < Int end def to_u64! - if LibGMP::Long == Int64 || (self <= Int32::MAX && self >= Int32::MIN) + if LibGMP::Long == Int64 || (Int32::MIN <= self <= Int32::MAX) LibGMP.get_ui(self).to_u64! else to_s.to_u64