Skip to content
This repository
Browse code

should not raise an exception, so implement vm_fast_mod(). fix #1471

The modulo between the Fixnum/Float is improved the performance by this patch.

* before
      user     system      total        real
  1.000000   0.000000   1.000000 (  1.000743)
  1.030000   0.000000   1.030000 (  1.030479)
  1.090000   0.000000   1.090000 (  1.097021)

* after
      user     system      total        real
  0.570000   0.000000   0.570000 (  0.577238)
  1.040000   0.000000   1.040000 (  1.031634)
  0.540000   0.000000   0.540000 (  0.539968)

Test Script:
----
require 'benchmark'

Benchmark.bm do |x|
  x.report do
    10_000_000.times do
      42 % 1
    end
  end

  x.report do
    10_000_000.times do
      42 % 1.0
    end
  end

  x.report do
    10_000_000.times do
      42.0 % 1.0
    end
  end
end
  • Loading branch information...
commit a3b91c64b6fa2635f3ce51610f3f4ca9c120a8ec 1 parent 9dec8ce
Watson authored May 15, 2012
6  compiler.cpp
@@ -172,6 +172,7 @@ RoxorCompiler::RoxorCompiler(bool _debug_mode)
172 172
     fastMinusFunc = get_function("vm_fast_minus");
173 173
     fastMultFunc = get_function("vm_fast_mult");
174 174
     fastDivFunc = get_function("vm_fast_div");
  175
+    fastModFunc = get_function("vm_fast_mod");
175 176
     fastLtFunc = get_function("vm_fast_lt");
176 177
     fastLeFunc = get_function("vm_fast_le");
177 178
     fastGtFunc = get_function("vm_fast_gt");
@@ -2298,7 +2299,7 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
2298 2299
 	return pn;
2299 2300
     }
2300 2301
     // Pure arithmetic operations.
2301  
-    else if (sel == selPLUS || sel == selMINUS || sel == selDIV 
  2302
+    else if (sel == selPLUS || sel == selMINUS || sel == selDIV || sel == selMOD
2302 2303
 	     || sel == selMULT || sel == selLT || sel == selLE 
2303 2304
 	     || sel == selGT || sel == selGE || sel == selEq
2304 2305
 	     || sel == selNeq || sel == selEqq) {
@@ -2320,6 +2321,9 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
2320 2321
 	else if (sel == selDIV) {
2321 2322
 	    func = fastDivFunc;
2322 2323
 	}
  2324
+	else if (sel == selMOD) {
  2325
+	    func = fastModFunc;
  2326
+	}
2323 2327
 	else if (sel == selMULT) {
2324 2328
 	    func = fastMultFunc;
2325 2329
 	}
1  compiler.h
@@ -159,6 +159,7 @@ class RoxorCompiler {
159 159
 	Function *fastMinusFunc;
160 160
 	Function *fastMultFunc;
161 161
 	Function *fastDivFunc;
  162
+	Function *fastModFunc;
162 163
 	Function *fastLtFunc;
163 164
 	Function *fastLeFunc;
164 165
 	Function *fastGtFunc;
1  exported_symbols_list
@@ -14,6 +14,7 @@ _rstr_concat
14 14
 _selPLUS
15 15
 _selMINUS
16 16
 _selDIV
  17
+_selMOD
17 18
 _selMULT
18 19
 _selLT
19 20
 _selLE
58  kernel.c
@@ -439,6 +439,64 @@ vm_fast_div(VALUE left, VALUE right, unsigned char overriden)
439 439
 }
440 440
 
441 441
 PRIMITIVE VALUE
  442
+vm_fast_mod(VALUE left, VALUE right, unsigned char overriden)
  443
+{
  444
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
  445
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
  446
+	    const long x = FIX2LONG(left);
  447
+	    const long y = FIX2LONG(right);
  448
+	    long div, mod;
  449
+
  450
+	    if (y == 0) {
  451
+		rb_num_zerodiv();
  452
+	    }
  453
+	    if (y < 0) {
  454
+		if (x < 0) {
  455
+		    div = -x / -y;
  456
+		}
  457
+		else {
  458
+		    div = - (x / -y);
  459
+		}
  460
+	    }
  461
+	    else {
  462
+		if (x < 0) {
  463
+		    div = - (-x / y);
  464
+		}
  465
+		else {
  466
+		    div = x / y;
  467
+		}
  468
+	    }
  469
+	    mod = x - div*y;
  470
+	    if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
  471
+		mod += y;
  472
+		div -= 1;
  473
+	    }
  474
+	    return LONG2FIX(mod);
  475
+	}
  476
+	else if (FIXFLOAT_P(left) && FIXFLOAT_P(right)) {
  477
+	    const double x = IMM2DBL(left);
  478
+	    const double y = IMM2DBL(right);
  479
+	    double div, mod;
  480
+
  481
+#ifdef HAVE_FMOD
  482
+	    mod = fmod(x, y);
  483
+#else
  484
+	    double z;
  485
+	    modf(x/y, &z);
  486
+	    mod = x - z * y;
  487
+#endif
  488
+	    div = (x - mod) / y;
  489
+	    if (y * mod < 0) {
  490
+		mod += y;
  491
+		div -= 1.0;
  492
+	    }
  493
+	    return DBL2FIXFLOAT(mod);
  494
+	}
  495
+    }
  496
+    return vm_dispatch(0, left, selMOD, NULL, 0, 1, &right);
  497
+}
  498
+
  499
+PRIMITIVE VALUE
442 500
 vm_fast_lt(VALUE left, VALUE right, unsigned char overriden)
443 501
 {
444 502
     if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {

0 notes on commit a3b91c6

Please sign in to comment.
Something went wrong with that request. Please try again.