@@ -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