Skip to content

Commit 63b72e8

Browse files
committed
Fix creating a negative zero BigDecimal in some cases
1 parent ec56277 commit 63b72e8

File tree

5 files changed

+31
-15
lines changed

5 files changed

+31
-15
lines changed

spec/ruby/library/bigdecimal/BigDecimal_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,9 @@
154154
lambda { BigDecimal(1.0) }.should raise_error(ArgumentError)
155155
end
156156

157+
it "returns appropriate BigDecimal zero for signed zero" do
158+
BigDecimal(-0.0, Float::DIG).sign.should == -1
159+
BigDecimal(0.0, Float::DIG).sign.should == 1
160+
end
161+
157162
end

spec/tags/library/bigdecimal/to_d_tags.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/main/java/org/truffleruby/language/RubyGuards.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ public static boolean isPositive(double value) {
322322
return value >= 0;
323323
}
324324

325+
public static boolean isNegativeZero(double value) {
326+
return Double.valueOf(value).equals(-0.0);
327+
}
328+
325329
// Composite
326330

327331
public static boolean isSingletonClass(DynamicObject value) {

src/main/java/org/truffleruby/stdlib/bigdecimal/BigDecimalCastNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public BigDecimal doInt(long value, RoundingMode roundingMode) {
6868
@TruffleBoundary
6969
@Specialization
7070
public BigDecimal doDouble(double value, RoundingMode roundingMode) {
71+
assert !RubyGuards.isNegativeZero(value);
7172
return BigDecimal.valueOf(value);
7273
}
7374

src/main/java/org/truffleruby/stdlib/bigdecimal/CreateBigDecimalNode.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,28 @@ public DynamicObject create(double value, NotProvided digits, boolean strict,
8383
}
8484
}
8585

86-
@Specialization
87-
public DynamicObject create(double value, int digits, boolean strict,
88-
@Cached("create()") BigDecimalCastNode bigDecimalCastNode,
89-
@Cached("createBinaryProfile()") ConditionProfile finiteValueProfile,
90-
@Cached("create()") BranchProfile nanProfile,
91-
@Cached("create()") BranchProfile positiveInfinityProfile,
92-
@Cached("create()") BranchProfile negativeInfinityProfile) {
93-
if (finiteValueProfile.profile(Double.isFinite(value))) {
94-
final RoundingMode roundMode = getRoundMode();
95-
final BigDecimal bigDecimal = (BigDecimal) bigDecimalCastNode.execute(value, roundMode);
86+
@Specialization(guards = "isNegativeZero(value)")
87+
public DynamicObject createNegativeZero(double value, int digits, boolean strict) {
88+
return createSpecialBigDecimal(BigDecimalType.NEGATIVE_ZERO);
89+
}
9690

97-
return createNormalBigDecimal(round(bigDecimal, new MathContext(digits, roundMode)));
98-
} else {
99-
return createNonFiniteBigDecimal(value, nanProfile, positiveInfinityProfile, negativeInfinityProfile);
100-
}
91+
@Specialization(guards = {
92+
"isFinite(value)",
93+
"!isNegativeZero(value)"
94+
})
95+
public DynamicObject createFinite(double value, int digits, boolean strict,
96+
@Cached("create()") BigDecimalCastNode bigDecimalCastNode) {
97+
final RoundingMode roundMode = getRoundMode();
98+
final BigDecimal bigDecimal = (BigDecimal) bigDecimalCastNode.execute(value, roundMode);
99+
return createNormalBigDecimal(round(bigDecimal, new MathContext(digits, roundMode)));
100+
}
101+
102+
@Specialization(guards = "!isFinite(value)")
103+
public DynamicObject createInfinite(double value, int digits, boolean strict,
104+
@Cached("create()") BranchProfile nanProfile,
105+
@Cached("create()") BranchProfile positiveInfinityProfile,
106+
@Cached("create()") BranchProfile negativeInfinityProfile) {
107+
return createNonFiniteBigDecimal(value, nanProfile, positiveInfinityProfile, negativeInfinityProfile);
101108
}
102109

103110
@Specialization(guards = "type == NEGATIVE_INFINITY || type == POSITIVE_INFINITY")

0 commit comments

Comments
 (0)