Skip to content

Commit

Permalink
Optimize arithmetic between BigFloat and integers (#14944)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored Aug 26, 2024
1 parent 8878c8b commit bd49e2e
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 22 deletions.
65 changes: 65 additions & 0 deletions src/big/big_float.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/big/lib_gmp.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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*)
Expand Down
22 changes: 0 additions & 22 deletions src/big/number.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bd49e2e

Please sign in to comment.