Skip to content

Commit 71b46c9

Browse files
committed
[Truffle] Implemement more Bignum#% specs.
1 parent 77a5ca9 commit 71b46c9

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

spec/truffle/tags/core/bignum/modulo_tags.txt

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

truffle/src/main/java/org/jruby/truffle/nodes/core/BignumNodes.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public Object div(RubyBignum a, RubyBignum b) {
206206

207207
}
208208

209-
@CoreMethod(names = "%", required = 1)
209+
@CoreMethod(names = {"%", "modulo"}, required = 1)
210210
public abstract static class ModNode extends BignumCoreMethodNode {
211211

212212
public ModNode(RubyContext context, SourceSection sourceSection) {
@@ -219,19 +219,46 @@ public ModNode(ModNode prev) {
219219

220220
@Specialization
221221
public Object mod(RubyBignum a, int b) {
222+
if (b == 0) {
223+
throw new ArithmeticException("divide by zero");
224+
} else if (b < 0) {
225+
final BigInteger bigint = BigInteger.valueOf(b);
226+
final BigInteger mod = a.bigIntegerValue().mod(bigint.negate());
227+
return fixnumOrBignum(mod.add(bigint));
228+
}
222229
return fixnumOrBignum(a.bigIntegerValue().mod(BigInteger.valueOf(b)));
223230
}
224231

225232
@Specialization
226233
public Object mod(RubyBignum a, long b) {
234+
if (b == 0) {
235+
throw new ArithmeticException("divide by zero");
236+
} else if (b < 0) {
237+
final BigInteger bigint = BigInteger.valueOf(b);
238+
final BigInteger mod = a.bigIntegerValue().mod(bigint.negate());
239+
return fixnumOrBignum(mod.add(bigint));
240+
}
227241
return fixnumOrBignum(a.bigIntegerValue().mod(BigInteger.valueOf(b)));
228242
}
229243

230244
@Specialization
231245
public Object mod(RubyBignum a, RubyBignum b) {
246+
final BigInteger bigint = b.bigIntegerValue();
247+
final int compare = bigint.compareTo(BigInteger.ZERO);
248+
if (compare == 0) {
249+
throw new ArithmeticException("divide by zero");
250+
} else if (compare < 0) {
251+
final BigInteger mod = a.bigIntegerValue().mod(bigint.negate());
252+
return fixnumOrBignum(mod.add(bigint));
253+
}
232254
return fixnumOrBignum(a.bigIntegerValue().mod(b.bigIntegerValue()));
233255
}
234256

257+
@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])", "!isRubyBignum(arguments[1])"})
258+
public Object mod(VirtualFrame frame, RubyBignum a, Object b) {
259+
return ruby(frame, "redo_coerced :%, other", "other", b);
260+
}
261+
235262
}
236263

237264
@CoreMethod(names = "<", required = 1)

0 commit comments

Comments
 (0)