Skip to content

Commit e3a61d5

Browse files
committed
Implement BigDecimal#to_r.
PullRequest: truffleruby/554
2 parents e6886d6 + b59c925 commit e3a61d5

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Compatibility:
1414

1515
* Change to a new system for handling Ruby objects in C extensions which
1616
greatly increases compatibility with MRI.
17+
* Implemented `BigDecimal#to_r` (#1521).
1718

1819
# 1.0 RC 11, 15 January 2019
1920

spec/tags/library/bigdecimal/to_r_tags.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,67 @@ public double toFSpecial(
14151415

14161416
}
14171417

1418+
@CoreMethod(names = "to_r")
1419+
public abstract static class ToRNode extends BigDecimalCoreMethodArrayArgumentsNode {
1420+
1421+
@Child private CallDispatchHeadNode createRationalNode = CallDispatchHeadNode.createPrivate();
1422+
1423+
@Specialization(guards = "isNormal(value)")
1424+
public Object toR(DynamicObject value,
1425+
@Cached("new()") FixnumOrBignumNode numeratorConversionNode,
1426+
@Cached("new()") FixnumOrBignumNode denominatorConversionNode) {
1427+
final BigDecimal bigDecimalValue = Layouts.BIG_DECIMAL.getValue(value);
1428+
1429+
final BigInteger numerator = getNumerator(bigDecimalValue);
1430+
final BigInteger denominator = getDenominator(bigDecimalValue);
1431+
1432+
final Object numeratorAsRubyValue = numeratorConversionNode.fixnumOrBignum(numerator);
1433+
final Object denominatorAsRubyValue = denominatorConversionNode.fixnumOrBignum(denominator);
1434+
1435+
return createRationalNode.call(getContext().getCoreLibrary().getRationalClass(), "convert",
1436+
numeratorAsRubyValue, denominatorAsRubyValue);
1437+
}
1438+
1439+
@Specialization(guards = "!isNormal(value)")
1440+
public Object toRSpecial(
1441+
DynamicObject value,
1442+
@Cached("create()") BranchProfile negInfinityProfile,
1443+
@Cached("create()") BranchProfile posInfinityProfile,
1444+
@Cached("create()") BranchProfile negZeroProfile,
1445+
@Cached("create()") BranchProfile nanProfile) {
1446+
final BigDecimalType type = Layouts.BIG_DECIMAL.getType(value);
1447+
1448+
switch (type) {
1449+
case NEGATIVE_INFINITY:
1450+
negInfinityProfile.enter();
1451+
throw new RaiseException(getContext(), coreExceptions().floatDomainErrorResultsToNegInfinity(this));
1452+
case POSITIVE_INFINITY:
1453+
posInfinityProfile.enter();
1454+
throw new RaiseException(getContext(), coreExceptions().floatDomainErrorResultsToInfinity(this));
1455+
case NAN:
1456+
nanProfile.enter();
1457+
throw new RaiseException(getContext(), coreExceptions().floatDomainErrorResultsToNaN(this));
1458+
case NEGATIVE_ZERO:
1459+
negZeroProfile.enter();
1460+
return createRationalNode.call(getContext().getCoreLibrary().getRationalClass(), "convert", 0, 1);
1461+
default:
1462+
CompilerDirectives.transferToInterpreterAndInvalidate();
1463+
throw new UnsupportedOperationException("unreachable code branch for value: " + Layouts.BIG_DECIMAL.getType(value));
1464+
}
1465+
}
1466+
1467+
@TruffleBoundary
1468+
private BigInteger getNumerator(BigDecimal value) {
1469+
return value.scaleByPowerOfTen(value.scale()).toBigInteger();
1470+
}
1471+
1472+
@TruffleBoundary
1473+
private BigInteger getDenominator(BigDecimal value) {
1474+
return BigInteger.TEN.pow(value.scale());
1475+
}
1476+
1477+
}
1478+
14181479
@NonStandard
14191480
@CoreMethod(names = "unscaled", visibility = Visibility.PRIVATE)
14201481
public abstract static class UnscaledNode extends BigDecimalCoreMethodArrayArgumentsNode {

0 commit comments

Comments
 (0)