Skip to content

Commit

Permalink
Merge branch 'master' into feat/tool-unreachable-test
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Sep 20, 2023
2 parents 97e2cdd + fb92a1e commit c64fa17
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 33 deletions.
105 changes: 105 additions & 0 deletions spec/std/big/big_decimal_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,23 @@ describe BigDecimal do
"-12.345".to_big_d.round(0, mode: :to_zero).should eq "-12".to_big_d
"-12.345".to_big_d.round(1, mode: :to_zero).should eq "-12.3".to_big_d
"-12.345".to_big_d.round(2, mode: :to_zero).should eq "-12.34".to_big_d

# 1 + 3.0000e-200 -> 1 + 3.0e-200 (ditto for others)
(1.to_big_d + BigDecimal.new(30000, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(30001, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(39999, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(40000, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40001, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(49999, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(50000, 204)).round(200, mode: :to_zero).should eq(1.to_big_d + BigDecimal.new(5, 200))

(-1.to_big_d - BigDecimal.new(30000, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(30001, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(39999, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(40000, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40001, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(49999, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(50000, 204)).round(200, mode: :to_zero).should eq(-1.to_big_d - BigDecimal.new(5, 200))
end

it "to_positive" do
Expand All @@ -829,6 +846,23 @@ describe BigDecimal do
"-12.345".to_big_d.round(0, mode: :to_positive).should eq "-12".to_big_d
"-12.345".to_big_d.round(1, mode: :to_positive).should eq "-12.3".to_big_d
"-12.345".to_big_d.round(2, mode: :to_positive).should eq "-12.34".to_big_d

# 1 + 3.0000e-200 -> 1 + 3.0e-200 (ditto for others)
(1.to_big_d + BigDecimal.new(30000, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(30001, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(39999, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40000, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40001, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(5, 200))
(1.to_big_d + BigDecimal.new(49999, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(5, 200))
(1.to_big_d + BigDecimal.new(50000, 204)).round(200, mode: :to_positive).should eq(1.to_big_d + BigDecimal.new(5, 200))

(-1.to_big_d - BigDecimal.new(30000, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(30001, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(39999, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(40000, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40001, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(49999, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(50000, 204)).round(200, mode: :to_positive).should eq(-1.to_big_d - BigDecimal.new(5, 200))
end

it "to_negative" do
Expand All @@ -840,6 +874,23 @@ describe BigDecimal do
"-12.345".to_big_d.round(0, mode: :to_negative).should eq "-13".to_big_d
"-12.345".to_big_d.round(1, mode: :to_negative).should eq "-12.4".to_big_d
"-12.345".to_big_d.round(2, mode: :to_negative).should eq "-12.35".to_big_d

# 1 + 3.0000e-200 -> 1 + 3.0e-200 (ditto for others)
(1.to_big_d + BigDecimal.new(30000, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(30001, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(39999, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(40000, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40001, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(49999, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(50000, 204)).round(200, mode: :to_negative).should eq(1.to_big_d + BigDecimal.new(5, 200))

(-1.to_big_d - BigDecimal.new(30000, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(30001, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(39999, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40000, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40001, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(5, 200))
(-1.to_big_d - BigDecimal.new(49999, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(5, 200))
(-1.to_big_d - BigDecimal.new(50000, 204)).round(200, mode: :to_negative).should eq(-1.to_big_d - BigDecimal.new(5, 200))
end

it "ties_away" do
Expand All @@ -851,6 +902,33 @@ describe BigDecimal do
"-13.825".to_big_d.round(0, mode: :ties_away).should eq "-14".to_big_d
"-13.825".to_big_d.round(1, mode: :ties_away).should eq "-13.8".to_big_d
"-13.825".to_big_d.round(2, mode: :ties_away).should eq "-13.83".to_big_d

# 1 + 3.0000e-200 -> 1 + 3.0e-200 (ditto for others)
(1.to_big_d + BigDecimal.new(30000, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(30001, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(34999, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(35000, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(35001, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(39999, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40000, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40001, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(44999, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(45000, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(5, 200))
(1.to_big_d + BigDecimal.new(45001, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(5, 200))
(1.to_big_d + BigDecimal.new(50000, 204)).round(200, mode: :ties_away).should eq(1.to_big_d + BigDecimal.new(5, 200))

(-1.to_big_d - BigDecimal.new(30000, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(30001, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(34999, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(35000, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(35001, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(39999, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40000, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40001, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(44999, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(45000, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(5, 200))
(-1.to_big_d - BigDecimal.new(45001, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(5, 200))
(-1.to_big_d - BigDecimal.new(50000, 204)).round(200, mode: :ties_away).should eq(-1.to_big_d - BigDecimal.new(5, 200))
end

it "ties_even" do
Expand All @@ -862,6 +940,33 @@ describe BigDecimal do
"-15.255".to_big_d.round(0, mode: :ties_even).should eq "-15".to_big_d
"-15.255".to_big_d.round(1, mode: :ties_even).should eq "-15.3".to_big_d
"-15.255".to_big_d.round(2, mode: :ties_even).should eq "-15.26".to_big_d

# 1 + 3.0000e-200 -> 1 + 3.0e-200 (ditto for others)
(1.to_big_d + BigDecimal.new(30000, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(30001, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(34999, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(3, 200))
(1.to_big_d + BigDecimal.new(35000, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(35001, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(39999, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40000, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(40001, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(44999, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(45000, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(4, 200))
(1.to_big_d + BigDecimal.new(45001, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(5, 200))
(1.to_big_d + BigDecimal.new(50000, 204)).round(200, mode: :ties_even).should eq(1.to_big_d + BigDecimal.new(5, 200))

(-1.to_big_d - BigDecimal.new(30000, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(30001, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(34999, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(3, 200))
(-1.to_big_d - BigDecimal.new(35000, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(35001, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(39999, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40000, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(40001, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(44999, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(45000, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(4, 200))
(-1.to_big_d - BigDecimal.new(45001, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(5, 200))
(-1.to_big_d - BigDecimal.new(50000, 204)).round(200, mode: :ties_even).should eq(-1.to_big_d - BigDecimal.new(5, 200))
end
end
end
Expand Down
17 changes: 17 additions & 0 deletions spec/std/time/span_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ describe Time::Span do
t1.to_s.should eq("1.01:00:00")
end

it "initializes with type restrictions" do
t = Time::Span.new seconds: 1_u8, nanoseconds: 1_u8
t.should eq(Time::Span.new seconds: 1, nanoseconds: 1)

t = Time::Span.new seconds: 127_i8, nanoseconds: 1_000_000_000
t.should eq(Time::Span.new seconds: 128)

t = Time::Span.new seconds: -128_i8, nanoseconds: -1_000_000_000
t.should eq(Time::Span.new seconds: -129)

t = Time::Span.new seconds: 255_u8, nanoseconds: 1_000_000_000
t.should eq(Time::Span.new seconds: 256)

t = Time::Span.new seconds: 0_u8, nanoseconds: -1_000_000_000
t.should eq(Time::Span.new seconds: -1)
end

it "initializes with big seconds value" do
t = Time::Span.new hours: 0, minutes: 0, seconds: 1231231231231
t.total_seconds.should eq(1231231231231)
Expand Down
20 changes: 20 additions & 0 deletions spec/std/uri/params_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ class URI

encoded.should eq("foo%20bar=hello%20world")
end

it "builds with IO" do
io = IO::Memory.new
Params.build(io) do |form|
form.add("custom", "key")
end
io.to_s.should eq("custom=key")
end
end

describe ".encode" do
Expand All @@ -69,10 +77,22 @@ class URI
encoded.should eq("foo=bar&baz=quux&baz=quuz")
end

it "builds from hash with IO" do
io = IO::Memory.new
Params.encode(io, {"foo" => "bar", "baz" => ["quux", "quuz"]})
io.to_s.should eq("foo=bar&baz=quux&baz=quuz")
end

it "builds from named tuple" do
encoded = Params.encode({foo: "bar", baz: ["quux", "quuz"]})
encoded.should eq("foo=bar&baz=quux&baz=quuz")
end

it "builds from named tuple with IO" do
io = IO::Memory.new
encoded = Params.encode(io, {foo: "bar", baz: ["quux", "quuz"]})
io.to_s.should eq("foo=bar&baz=quux&baz=quuz")
end
end

describe "#to_s" do
Expand Down
51 changes: 35 additions & 16 deletions src/big/big_decimal.cr
Original file line number Diff line number Diff line change
Expand Up @@ -460,27 +460,37 @@ struct BigDecimal < Number
end

def round(digits : Number, base = 10, *, mode : RoundingMode = :ties_even) : BigDecimal
return self if (base == 10 && @scale <= digits) || zero?
return self if zero?

# the following is same as the overload in `Number` except `base.to_f`
# becomes `.to_big_d`
if digits < 0
multiplier = base.to_big_d ** digits.abs
shifted = self / multiplier
if base == 10
return self if @scale <= digits

# optimized version that skips `#div` completely, always exact
shifted = mul_power_of_ten(digits)
rounded = shifted.round(mode)
rounded.mul_power_of_ten(-digits)
else
multiplier = base.to_big_d ** digits
shifted = self * multiplier
end
# the following is same as the overload in `Number` except `base.to_f`
# becomes `base.to_big_d`; note that the `#/` calls always use
# `DEFAULT_PRECISION`
if digits < 0
multiplier = base.to_big_d ** digits.abs
shifted = self / multiplier
else
multiplier = base.to_big_d ** digits
shifted = self * multiplier
end

rounded = shifted.round(mode)
rounded = shifted.round(mode)

if digits < 0
result = rounded * multiplier
else
result = rounded / multiplier
end
if digits < 0
result = rounded * multiplier
else
result = rounded / multiplier
end

BigDecimal.new result
BigDecimal.new result
end
end

def to_s(io : IO) : Nil
Expand Down Expand Up @@ -759,6 +769,15 @@ struct BigDecimal < Number
TEN_I ** x
end

# returns `self * 10 ** exponent`
protected def mul_power_of_ten(exponent : Int)
if exponent <= scale
BigDecimal.new(@value, @scale - exponent)
else
BigDecimal.new(@value * power_ten_to(exponent - scale), 0_u64)
end
end

# Factors out any extra powers of ten in the internal representation.
# For instance, value=100 scale=2 => value=1 scale=0
protected def factor_powers_of_ten
Expand Down
26 changes: 10 additions & 16 deletions src/time/span.cr
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,19 @@ struct Time::Span
# ```
def initialize(*, seconds : Int, nanoseconds : Int)
# Normalize nanoseconds in the range 0...1_000_000_000
seconds += nanoseconds.tdiv(NANOSECONDS_PER_SECOND)
nanoseconds = nanoseconds.remainder(NANOSECONDS_PER_SECOND)
@seconds = seconds.to_i64 + nanoseconds.tdiv(NANOSECONDS_PER_SECOND).to_i64
@nanoseconds = nanoseconds.remainder(NANOSECONDS_PER_SECOND).to_i32

# Make sure that if seconds is positive, nanoseconds is
# positive too. Likewise, if seconds is negative, make
# sure that nanoseconds is negative too.
if seconds > 0 && nanoseconds < 0
seconds -= 1
nanoseconds += NANOSECONDS_PER_SECOND
elsif seconds < 0 && nanoseconds > 0
seconds += 1
nanoseconds -= NANOSECONDS_PER_SECOND
if @seconds > 0 && @nanoseconds < 0
@seconds -= 1
@nanoseconds += NANOSECONDS_PER_SECOND
elsif @seconds < 0 && @nanoseconds > 0
@seconds += 1
@nanoseconds -= NANOSECONDS_PER_SECOND
end

@seconds = seconds.to_i64
@nanoseconds = nanoseconds.to_i32
end

# Creates a new `Time::Span` from the *nanoseconds* given
Expand All @@ -93,10 +90,7 @@ struct Time::Span
# Time::Span.new(nanoseconds: 5_500_000_000) # => 00:00:05.500000000
# ```
def self.new(*, nanoseconds : Int)
new(
seconds: nanoseconds.to_i64.tdiv(NANOSECONDS_PER_SECOND),
nanoseconds: nanoseconds.to_i64.remainder(NANOSECONDS_PER_SECOND),
)
new(seconds: 0, nanoseconds: nanoseconds)
end

# Creates a new `Time::Span` from the *days*, *hours*, *minutes*, *seconds* and *nanoseconds* given
Expand All @@ -111,7 +105,7 @@ struct Time::Span
def self.new(*, days : Int = 0, hours : Int = 0, minutes : Int = 0, seconds : Int = 0, nanoseconds : Int = 0)
new(
seconds: compute_seconds(days, hours, minutes, seconds),
nanoseconds: nanoseconds.to_i64,
nanoseconds: nanoseconds,
)
end

Expand Down
Loading

0 comments on commit c64fa17

Please sign in to comment.