Skip to content

Commit

Permalink
Implement pow operator for BigDecimal and BigRational (#7860)
Browse files Browse the repository at this point in the history
Co-Authored-By: Sijawusz Pur Rahnama <sija@sija.pl>
Co-Authored-By: r00ster <r00ster91@protonmail.com>
  • Loading branch information
3 people authored and straight-shoota committed Aug 1, 2019
1 parent cbf651a commit 8b5a9bf
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
6 changes: 6 additions & 0 deletions spec/std/big/big_decimal_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,12 @@ describe BigDecimal do
(3 / 2.to_big_d).should eq(BigDecimal.new("1.5"))
end

it "exponentiates" do
result = "12.34".to_big_d ** 5
result.should be_a(BigDecimal)
result.to_s.should eq("286138.1721051424")
end

it "can be converted from other types" do
1.to_big_d.should eq (BigDecimal.new(1))
"1.5".to_big_d.should eq (BigDecimal.new(15, 1))
Expand Down
17 changes: 17 additions & 0 deletions spec/std/big/big_rational_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ describe BigRational do
(br(10, 3) >> 2).should eq(br(5, 6))
end

describe "#**" do
it "exponentiates with positive powers" do
result = br(17, 11) ** 5
result.should be_a(BigRational)
result.should eq(br(1419857, 161051))
end

it "exponentiates with negative powers" do
result = br(17, 11) ** -5
result.should eq(br(161051, 1419857))
end

it "cannot raise 0 to a negative power" do
expect_raises(DivisionByZeroError) { br(0, 1) ** -1 }
end
end

it "#ceil" do
br(2, 1).ceil.should eq(2)
br(21, 10).ceil.should eq(3)
Expand Down
14 changes: 14 additions & 0 deletions src/big/big_decimal.cr
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,20 @@ struct BigDecimal < Number
end
end

# Raises the decimal to the *other*th power
#
# ```
# require "big"
#
# BigDecimal.new(1234, 2) ** 2 # => 152.2756
# ```
def **(other : Int) : BigDecimal
if other < 0
raise ArgumentError.new("Negative exponent isn't supported")
end
BigDecimal.new(@value ** other, @scale * other)
end

def ceil : BigDecimal
mask = power_ten_to(@scale)
diff = (mask - @value % mask) % mask
Expand Down
17 changes: 17 additions & 0 deletions src/big/big_rational.cr
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,23 @@ struct BigRational < Number
BigRational.new { |mpq| LibGMP.mpq_neg(mpq, self) }
end

# Raises the rational to the *other*th power
#
# This will raise `DivisionByZeroError` if rational is 0 and *other* is negative.
#
# ```
# require "big"
#
# BigRational.new(2, 3) ** 2 # => 4/9
# BigRational.new(2, 3) ** -1 # => 3/2
# ```
def **(other : Int) : BigRational
if other < 0
return (self ** -other).inv
end
BigRational.new(numerator ** other, denominator ** other)
end

# Returns a new `BigRational` as 1/r.
#
# This will raise an exception if rational is 0.
Expand Down

0 comments on commit 8b5a9bf

Please sign in to comment.