Skip to content

Instantly share code, notes, and snippets.

@pulsejet
Created May 5, 2018 02:30
Show Gist options
  • Save pulsejet/29ec1fd9fdc77f12a96798f4b32f1d47 to your computer and use it in GitHub Desktop.
Save pulsejet/29ec1fd9fdc77f12a96798f4b32f1d47 to your computer and use it in GitHub Desktop.
Patch to force 1/2 == 0 in mruby
From e36e2760f2c168c179a35cc8bf7a4103ce523f61 Mon Sep 17 00:00:00 2001
From: Rob Lyman <waveformdelta@gmail.com>
Date: Sat, 20 Jan 2018 13:52:04 -0600
Subject: [PATCH 1/2] Updated support for integer division behavior
This adds an adapted fix to give conditional integer division support,
based on the environment variable MRB_INTEGER_DIVISION. This adapts from
the previous fix to the latest stable mRuby branch, taking into
account their new MRB_WITHOUT_FLOAT environment variable.
Note that MRB_WITHOUT_FLOAT and MRB_INTEGER_DIVISION are not compatible
and should not be used together.
With the former unset and the latter set, we can build an mRuby that
supports native floating point values, but still gives an integer
quotient result for dividing two integers (non-integer dividend or
divisor give float results, as usual).
This fix is adapted from the fix in this open PR on the mRuby project:
https://github.com/mruby/mruby/pull/3123
---
src/vm.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/src/vm.c b/src/vm.c
index 084811499..59646ed6c 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -2416,6 +2416,9 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
CASE(OP_DIV) {
/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
int a = GETARG_A(i);
+#ifdef MRB_INTEGER_DIVISION
+ int integer_div = FALSE;
+#endif
#ifndef MRB_WITHOUT_FLOAT
double x, y, f;
#endif
@@ -2433,6 +2436,9 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
#else
x = (mrb_float)mrb_fixnum(regs[a]);
y = (mrb_float)mrb_fixnum(regs[a+1]);
+#ifdef MRB_INTEGER_DIVISION
+ integer_div = TRUE;
+#endif
break;
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
x = (mrb_float)mrb_fixnum(regs[a]);
@@ -2452,6 +2458,35 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
}
#ifndef MRB_WITHOUT_FLOAT
+#ifdef MRB_INTEGER_DIVISION
+ if (integer_div)
+ {
+ if (y == 0 || (x == MRB_INT_MIN && y == -1)) {
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y);
+ }
+ else {
+ mrb_int div, mod;
+ if (y < 0) {
+ if (x < 0)
+ div = -x / -y;
+ else
+ div = - (x / -y);
+ }
+ else {
+ if (x < 0)
+ div = - (-x / y);
+ else
+ div = x / y;
+ }
+ mod = x - div*y;
+ if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
+ div -= 1;
+ }
+ SET_INT_VALUE(regs[a], div);
+ }
+ }
+ else {
+#endif
if (y == 0) {
if (x > 0) f = INFINITY;
else if (x < 0) f = -INFINITY;
@@ -2461,7 +2496,10 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
f = x / y;
}
SET_FLOAT_VALUE(mrb, regs[a], f);
+#ifdef MRB_INTEGER_DIVISION
+ }
#endif
+#endif /* #ifndef MRB_WITHOUT_FLOAT */
NEXT;
}
From 116c6373e188109e27f00012f8ed3a965c75ad53 Mon Sep 17 00:00:00 2001
From: Rob Lyman <waveformdelta@gmail.com>
Date: Sat, 20 Jan 2018 13:52:38 -0600
Subject: [PATCH 2/2] Add explanation of integer division support to README
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This explains the raison d'être for this fork of mRuby.
---
README.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/README.md b/README.md
index 196cc2ef7..6ba0b4c42 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,13 @@
[![Build Status][build-status-img]][travis-ci]
+## mruby with Integer Division Support
+
+This is a fork of the mruby project that includes support for integer division compatible with that in other Rubys, so that
+
+`(1 / 2) => 0`
+
+This is enabled with the compiler variable `MRB_INTEGER_DIVISION`: when set during compilation, it will enable integer division behavior. This mruby is otherwise compatible with mruby 1.4.0.
+
## What is mruby
mruby is the lightweight implementation of the Ruby language complying to (part
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment