From 647dcf9cf512629e1f7f3e63a65a7f3572c50bd9 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sun, 25 Aug 2024 17:19:57 +0800 Subject: [PATCH] Optimize arithmetic between `BigFloat` and integers --- src/big/big_float.cr | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/big/lib_gmp.cr | 3 ++ src/big/number.cr | 22 --------------- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/big/big_float.cr b/src/big/big_float.cr index cadc91282fc1..2c567f21eec9 100644 --- a/src/big/big_float.cr +++ b/src/big/big_float.cr @@ -115,18 +115,60 @@ struct BigFloat < Float BigFloat.new { |mpf| LibGMP.mpf_neg(mpf, self) } end + def +(other : Int::Primitive) : BigFloat + Int.primitive_ui_check(other) do |ui, neg_ui, big_i| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_add_ui(mpf, self, {{ ui }}) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_sub_ui(mpf, self, {{ neg_ui }}) }, + big_i: self + {{ big_i }}, + } + end + end + def +(other : Number) : BigFloat BigFloat.new { |mpf| LibGMP.mpf_add(mpf, self, other.to_big_f) } end + def -(other : Int::Primitive) : BigFloat + Int.primitive_ui_check(other) do |ui, neg_ui, big_i| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_sub_ui(mpf, self, {{ ui }}) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_add_ui(mpf, self, {{ neg_ui }}) }, + big_i: self - {{ big_i }}, + } + end + end + def -(other : Number) : BigFloat BigFloat.new { |mpf| LibGMP.mpf_sub(mpf, self, other.to_big_f) } end + def *(other : Int::Primitive) : BigFloat + Int.primitive_ui_check(other) do |ui, neg_ui, big_i| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_mul_ui(mpf, self, {{ ui }}) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_mul_ui(mpf, self, {{ neg_ui }}); LibGMP.mpf_neg(mpf, mpf) }, + big_i: self + {{ big_i }}, + } + end + end + def *(other : Number) : BigFloat BigFloat.new { |mpf| LibGMP.mpf_mul(mpf, self, other.to_big_f) } end + def /(other : Int::Primitive) : BigFloat + # Division by 0 in BigFloat is not allowed, there is no BigFloat::Infinity + raise DivisionByZeroError.new if other == 0 + Int.primitive_ui_check(other) do |ui, neg_ui, _| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_div_ui(mpf, self, {{ ui }}) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_div_ui(mpf, self, {{ neg_ui }}); LibGMP.mpf_neg(mpf, mpf) }, + big_i: BigFloat.new { |mpf| LibGMP.mpf_div(mpf, self, BigFloat.new(other)) }, + } + end + end + def /(other : BigFloat) : BigFloat # Division by 0 in BigFloat is not allowed, there is no BigFloat::Infinity raise DivisionByZeroError.new if other == 0 @@ -448,6 +490,29 @@ struct Int def <=>(other : BigFloat) -(other <=> self) end + + def -(other : BigFloat) : BigFloat + Int.primitive_ui_check(self) do |ui, neg_ui, _| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_neg(mpf, other); LibGMP.mpf_add_ui(mpf, mpf, {{ ui }}) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_neg(mpf, other); LibGMP.mpf_sub_ui(mpf, mpf, {{ neg_ui }}) }, + big_i: BigFloat.new { |mpf| LibGMP.mpf_sub(mpf, BigFloat.new(self), other) }, + } + end + end + + def /(other : BigFloat) : BigFloat + # Division by 0 in BigFloat is not allowed, there is no BigFloat::Infinity + raise DivisionByZeroError.new if other == 0 + + Int.primitive_ui_check(self) do |ui, neg_ui, _| + { + ui: BigFloat.new { |mpf| LibGMP.mpf_ui_div(mpf, {{ ui }}, other) }, + neg_ui: BigFloat.new { |mpf| LibGMP.mpf_ui_div(mpf, {{ neg_ui }}, other); LibGMP.mpf_neg(mpf, mpf) }, + big_i: BigFloat.new { |mpf| LibGMP.mpf_div(mpf, BigFloat.new(self), other) }, + } + end + end end struct Float diff --git a/src/big/lib_gmp.cr b/src/big/lib_gmp.cr index 00834598d9d2..5ae18b5a4606 100644 --- a/src/big/lib_gmp.cr +++ b/src/big/lib_gmp.cr @@ -233,8 +233,11 @@ lib LibGMP # # Arithmetic fun mpf_add = __gmpf_add(rop : MPF*, op1 : MPF*, op2 : MPF*) + fun mpf_add_ui = __gmpf_add_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_sub = __gmpf_sub(rop : MPF*, op1 : MPF*, op2 : MPF*) + fun mpf_sub_ui = __gmpf_sub_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_mul = __gmpf_mul(rop : MPF*, op1 : MPF*, op2 : MPF*) + fun mpf_mul_ui = __gmpf_mul_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_div = __gmpf_div(rop : MPF*, op1 : MPF*, op2 : MPF*) fun mpf_div_ui = __gmpf_div_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_ui_div = __gmpf_ui_div(rop : MPF*, op1 : UI, op2 : MPF*) diff --git a/src/big/number.cr b/src/big/number.cr index 1251e8113db3..8761a2aa8b6c 100644 --- a/src/big/number.cr +++ b/src/big/number.cr @@ -8,18 +8,6 @@ struct BigFloat self.class.new(self / other) end - def /(other : Int::Primitive) : BigFloat - # Division by 0 in BigFloat is not allowed, there is no BigFloat::Infinity - raise DivisionByZeroError.new if other == 0 - Int.primitive_ui_check(other) do |ui, neg_ui, _| - { - ui: BigFloat.new { |mpf| LibGMP.mpf_div_ui(mpf, self, {{ ui }}) }, - neg_ui: BigFloat.new { |mpf| LibGMP.mpf_div_ui(mpf, self, {{ neg_ui }}); LibGMP.mpf_neg(mpf, mpf) }, - big_i: BigFloat.new { |mpf| LibGMP.mpf_div(mpf, self, BigFloat.new(other)) }, - } - end - end - Number.expand_div [Float32, Float64], BigFloat end @@ -91,70 +79,60 @@ end struct Int8 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct Int16 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct Int32 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct Int64 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct Int128 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct UInt8 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct UInt16 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct UInt32 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct UInt64 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end struct UInt128 Number.expand_div [BigInt], BigFloat - Number.expand_div [BigFloat], BigFloat Number.expand_div [BigDecimal], BigDecimal Number.expand_div [BigRational], BigRational end