Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8b8d3972e415
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 446f05861e25
Choose a head ref
  • 2 commits
  • 3 files changed
  • 2 contributors

Commits on Feb 23, 2015

  1. Fix power of 0 and 1 issues in Rational

    The patch adds special case handling for 0**n and 1**n to match the
    MRI behavior. For example, the following cases are affected:
    
    0**Rational(1, 2) # => 0/1 instead of 0.0
    0**Rational(-1, 2) # => ZeroDivisionError instead of Infinity
    1**Rational(1, 2) # => 1/1 instead of 1.0
    lumeet committed Feb 23, 2015
    Copy the full SHA
    fe98a27 View commit details

Commits on May 1, 2015

  1. Merge pull request #2616 from lumeet/rational_zero_division

    Fix power of 0 and 1 issues in Rational
    enebo committed May 1, 2015
    Copy the full SHA
    446f058 View commit details
Showing with 50 additions and 3 deletions.
  1. +23 −0 core/src/main/java/org/jruby/RubyRational.java
  2. +26 −1 core/src/main/java/org/jruby/util/Numeric.java
  3. +1 −2 test/mri/excludes/TestFixnum.rb
23 changes: 23 additions & 0 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -38,9 +38,11 @@
import static org.jruby.util.Numeric.f_inspect;
import static org.jruby.util.Numeric.f_integer_p;
import static org.jruby.util.Numeric.f_lt_p;
import static org.jruby.util.Numeric.f_minus_one_p;
import static org.jruby.util.Numeric.f_mul;
import static org.jruby.util.Numeric.f_negate;
import static org.jruby.util.Numeric.f_negative_p;
import static org.jruby.util.Numeric.f_odd_p;
import static org.jruby.util.Numeric.f_one_p;
import static org.jruby.util.Numeric.f_rshift;
import static org.jruby.util.Numeric.f_sub;
@@ -54,6 +56,8 @@
import static org.jruby.util.Numeric.i_gcd;
import static org.jruby.util.Numeric.i_ilog2;
import static org.jruby.util.Numeric.k_exact_p;
import static org.jruby.util.Numeric.k_integer_p;
import static org.jruby.util.Numeric.k_numeric_p;
import static org.jruby.util.Numeric.ldexp;
import static org.jruby.util.Numeric.nurat_rationalize_internal;

@@ -581,6 +585,25 @@ public IRubyObject op_expt(ThreadContext context, IRubyObject other) {
if (f_one_p(context, otherRational.den)) other = otherRational.num;
}

// Deal with special cases of 0**n and 1**n
if (k_numeric_p(other) && k_exact_p(other)) {
if (f_one_p(context, den)) {
if (f_one_p(context, num)) {
return RubyRational.newRationalBang(context, getMetaClass(), RubyFixnum.one(runtime));
} else if (f_minus_one_p(context, num) && k_integer_p(other)) {
return RubyRational.newRationalBang(context, getMetaClass(),
f_odd_p(context, other) ? RubyFixnum.minus_one(runtime) : RubyFixnum.one(runtime));
} else if (f_zero_p(context, num)) {
if (f_cmp(context, other, RubyFixnum.zero(runtime)) == RubyFixnum.minus_one(runtime)) {
throw context.runtime.newZeroDivisionError();
} else {
return RubyRational.newRationalBang(context, getMetaClass(), RubyFixnum.zero(runtime));
}
}
}
}

// General case
if (other instanceof RubyFixnum || other instanceof RubyBignum) {
final IRubyObject tnum, tden;
IRubyObject res = f_cmp(context, other, RubyFixnum.zero(runtime));
27 changes: 26 additions & 1 deletion core/src/main/java/org/jruby/util/Numeric.java
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyInteger;
import org.jruby.RubyNumeric;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

@@ -347,7 +348,23 @@ public static boolean f_one_p(ThreadContext context, IRubyObject x) {
if (x instanceof RubyFixnum) return ((RubyFixnum)x).getLongValue() == 1;
return x.callMethod(context, "==", RubyFixnum.one(context.runtime)).isTrue();
}


/** f_minus_one_p
*
*/
public static boolean f_minus_one_p(ThreadContext context, IRubyObject x) {
if (x instanceof RubyFixnum) return ((RubyFixnum)x).getLongValue() == -1;
return x.callMethod(context, "==", RubyFixnum.minus_one(context.runtime)).isTrue();
}

/** f_odd_p
*
*/
public static boolean f_odd_p(ThreadContext context, IRubyObject integer) {
Ruby runtime = context.runtime;
return (((RubyFixnum) integer.callMethod(context, "%", RubyFixnum.two(runtime))).getLongValue() != 0);
}

/** i_gcd
*
*/
@@ -498,6 +515,14 @@ public static boolean k_inexact_p(IRubyObject x) {
return x instanceof RubyFloat;
}

public static boolean k_integer_p(IRubyObject x) {
return x instanceof RubyInteger;
}

public static boolean k_numeric_p(IRubyObject x) {
return x instanceof RubyNumeric;
}

public static final class ComplexPatterns {
public static final Regex comp_pat0, comp_pat1, comp_pat2, underscores_pat;
static {
3 changes: 1 addition & 2 deletions test/mri/excludes/TestFixnum.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
exclude :test_power_of_0, "needs investigation"
exclude :test_power_of_1_and_minus_1, "needs investigation"
exclude :test_power_of_1_and_minus_1, "needs investigation"