Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
  
  package org.jruby;
  
  import static org.jruby.util.Numeric.checkInteger;
  import static org.jruby.util.Numeric.f_abs;
  import static org.jruby.util.Numeric.f_add;
  import static org.jruby.util.Numeric.f_cmp;
  import static org.jruby.util.Numeric.f_div;
  import static org.jruby.util.Numeric.f_equal;
  import static org.jruby.util.Numeric.f_expt;
  import static org.jruby.util.Numeric.f_floor;
  import static org.jruby.util.Numeric.f_gcd;
  import static org.jruby.util.Numeric.f_idiv;
  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_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_one_p;
  import static org.jruby.util.Numeric.f_rshift;
  import static org.jruby.util.Numeric.f_sub;
  import static org.jruby.util.Numeric.f_to_f;
  import static org.jruby.util.Numeric.f_to_i;
  import static org.jruby.util.Numeric.f_to_r;
  import static org.jruby.util.Numeric.f_to_s;
  import static org.jruby.util.Numeric.f_truncate;
  import static org.jruby.util.Numeric.f_xor;
  import static org.jruby.util.Numeric.f_zero_p;
  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.ldexp;
  import static org.jruby.util.Numeric.nurat_rationalize_internal;
  
  
  import static org.jruby.javasupport.util.RuntimeHelpers.invokedynamic;
  import static org.jruby.runtime.invokedynamic.MethodNames.HASH;

1.9 rational.c as of revision: 20011
  
  
  @JRubyClass(name = "Rational", parent = "Numeric", include = "Precision")
  public class RubyRational extends RubyNumeric {
      
      public static RubyClass createRationalClass(Ruby runtime) {
          RubyClass rationalc = runtime.defineClass("Rational"runtime.getNumeric(), );
          runtime.setRational(rationalc);
  
          rationalc.index = .;
          rationalc.setReifiedClass(RubyRational.class);
          
          rationalc.kindOf = new RubyModule.KindOf() {
              @Override
              public boolean isKindOf(IRubyObject objRubyModule type) {
                  return obj instanceof RubyRational;
              }
          };
  
          rationalc.defineAnnotatedMethods(RubyRational.class);
  
         rationalc.getSingletonClass().undefineMethod("allocate");
         rationalc.getSingletonClass().undefineMethod("new");
 
         return rationalc;
     }
 
     private static ObjectAllocator RATIONAL_ALLOCATOR = new ObjectAllocator() {
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             RubyFixnum zero = RubyFixnum.zero(runtime);
             return new RubyRational(runtimeklasszerozero);
         }
     };

    
internal
 
     private RubyRational(Ruby runtimeIRubyObject clazzIRubyObject numIRubyObject den) {
         super(runtime, (RubyClass)clazz);
         this. = num;
         this. = den;
     }

    
rb_rational_raw
 
     static RubyRational newRationalRaw(Ruby runtimeIRubyObject xIRubyObject y) {
         return new RubyRational(runtimeruntime.getRational(), xy);
     }

    
rb_rational_raw1
 
     static RubyRational newRationalRaw(Ruby runtimeIRubyObject x) {
         return new RubyRational(runtimeruntime.getRational(), x, RubyFixnum.one(runtime));
     }

    
rb_rational_new1
 
         return newRationalCanonicalize(contextx, RubyFixnum.one(context.runtime));
     }

    
rb_rational_new
 
     private static IRubyObject newRationalCanonicalize(ThreadContext contextIRubyObject xIRubyObject y) {
         return canonicalizeInternal(contextcontext.runtime.getRational(), xy);
     }
    
    
f_rational_new2
 
     private static IRubyObject newRational(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) {
         assert !(x instanceof RubyRational) && !(y instanceof RubyRational);
         return canonicalizeInternal(contextclazzxy);
     }

    
f_rational_new_no_reduce2
 
     private static IRubyObject newRationalNoReduce(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) {
         assert !(x instanceof RubyRational) && !(y instanceof RubyRational);
         return canonicalizeInternalNoReduce(contextclazzxy);
     }

    
f_rational_new_bang2
 
     private static RubyRational newRationalBang(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) { 
         assert !f_negative_p(contexty) && !(f_zero_p(contexty));
         return new RubyRational(context.runtimeclazzxy);
     }

    
f_rational_new_bang1
 
     private static RubyRational newRationalBang(ThreadContext contextIRubyObject clazzIRubyObject x) {
         return newRationalBang(contextclazzx, RubyFixnum.one(context.runtime));
     }
     
     private IRubyObject num;
     private IRubyObject den;

    
nurat_s_new_bang
 
     @Deprecated
     public static IRubyObject newInstanceBang(ThreadContext contextIRubyObject recvIRubyObject[]args) {
         switch (args.length) {
         case 1: return newInstanceBang(contextrecvargs[0]);
         case 2: return newInstanceBang(contextrecvargs[0], args[1]);
         }
         Arity.raiseArgumentError(context.runtimeargs.length, 1, 1);
         return null;
     }
 
     @JRubyMethod(name = "new!", meta = true, visibility = ., compat = .)
     public static IRubyObject newInstanceBang(ThreadContext contextIRubyObject recvIRubyObject num) {
         return newInstanceBang(contextrecvnum, RubyFixnum.one(context.runtime));
     }
 
     @JRubyMethod(name = "new!", meta = true, visibility = ., compat = .)
     public static IRubyObject newInstanceBang(ThreadContext contextIRubyObject recvIRubyObject numIRubyObject den) {
         if (!(num instanceof RubyInteger)) num = f_to_i(contextnum);
         if (!(den instanceof RubyInteger)) den = f_to_i(contextden);
 
         Ruby runtime = context.runtime;
         IRubyObject res = f_cmp(contextden, RubyFixnum.zero(runtime));
         if (res == RubyFixnum.minus_one(runtime)) {
             num = f_negate(contextnum);
             den = f_negate(contextden);
         } else if (res == RubyFixnum.zero(runtime)) {
             throw runtime.newZeroDivisionError();
         }
 
         return new RubyRational(runtimerecvnumden);
     }

    
nurat_canonicalization
 
     private static boolean canonicalization = false;
     public static void setCanonicalization(boolean canonical) {
          = canonical;
     }

    
nurat_int_check
 
     static void intCheck(ThreadContext contextIRubyObject num) {
         if (num instanceof RubyFixnum || num instanceof RubyBignumreturn;
         if (!(num instanceof RubyNumeric) || !num.callMethod(context"integer?").isTrue()) {
             Ruby runtime = num.getRuntime();
             if (runtime.is1_9()) {
                 throw runtime.newTypeError("can't convert "
                         + num.getMetaClass().getName() + " into Rational");
             } else {
                 throw runtime.newArgumentError("not an integer");
             }
         }
     }

    
nurat_int_value
 
     static IRubyObject intValue(ThreadContext contextIRubyObject num) {
         intCheck(contextnum);
         if (!(num instanceof RubyInteger)) num = num.callMethod(context"to_f");
         return num;
     }
    
    
nurat_s_canonicalize_internal
 
     private static IRubyObject canonicalizeInternal(ThreadContext contextIRubyObject clazzIRubyObject numIRubyObject den) {
         Ruby runtime = context.runtime;
         IRubyObject res = f_cmp(contextden, RubyFixnum.zero(runtime));
         if (res == RubyFixnum.minus_one(runtime)) {
             num = f_negate(contextnum);
             den = f_negate(contextden);
         } else if (res == RubyFixnum.zero(runtime)) {
             throw runtime.newZeroDivisionError();            
         }
 
         IRubyObject gcd = f_gcd(contextnumden);
         num = f_idiv(contextnumgcd);
         den = f_idiv(contextdengcd);
 
         if (.) {
             if (f_one_p(contextden) && return num;
         }
 
         return new RubyRational(context.runtimeclazznumden);
     }
    
    
nurat_s_canonicalize_internal_no_reduce
 
     private static IRubyObject canonicalizeInternalNoReduce(ThreadContext contextIRubyObject clazzIRubyObject numIRubyObject den) {
         Ruby runtime = context.runtime;
         IRubyObject res = f_cmp(contextden, RubyFixnum.zero(runtime));
         if (res == RubyFixnum.minus_one(runtime)) {
             num = f_negate(contextnum);
             den = f_negate(contextden);
         } else if (res == RubyFixnum.zero(runtime)) {
             throw runtime.newZeroDivisionError();            
         }        
 
         if (.) {
             if (f_one_p(contextden) && return num;
         }
 
         return new RubyRational(context.runtimeclazznumden);
     }
    
    
nurat_s_new
 
     @Deprecated
     public static IRubyObject newInstance(ThreadContext contextIRubyObject clazzIRubyObject[]args) {
         switch (args.length) {
         case 1: return newInstance(contextclazzargs[0]);
         case 2: return newInstance(contextclazzargs[0], args[1]);
         }
         Arity.raiseArgumentError(context.runtimeargs.length, 1, 1);
         return null;
     }
 
     // @JRubyMethod(name = "new", meta = true, visibility = Visibility.PRIVATE)
     public static IRubyObject newInstance(ThreadContext contextIRubyObject clazzIRubyObject num) {
         num = intValue(contextnum);
         return canonicalizeInternal(contextclazznum, RubyFixnum.one(context.runtime));
     }
 
     // @JRubyMethod(name = "new", meta = true, visibility = Visibility.PRIVATE)
     public static IRubyObject newInstance(ThreadContext contextIRubyObject clazzIRubyObject numIRubyObject den) {
         num = intValue(contextnum);
         den = intValue(contextden);
         return canonicalizeInternal(contextclazznumden);
     }
    
    
rb_Rational1
 
     public static IRubyObject newRationalConvert(ThreadContext contextIRubyObject x) {
         return newRationalConvert(contextx, RubyFixnum.one(context.runtime));
     }

    
rb_Rational/rb_Rational2
 
     public static IRubyObject newRationalConvert(ThreadContext contextIRubyObject xIRubyObject y) {
         return convert(contextcontext.runtime.getRational(), xy);
     }
     
     public static RubyRational newRational(Ruby runtimelong xlong y) {
         return new RubyRational(runtimeruntime.getRational(), runtime.newFixnum(x), runtime.newFixnum(y));
     }
     
     @Deprecated
     public static IRubyObject convert(ThreadContext contextIRubyObject clazzIRubyObject[]args) {
         switch (args.length) {
         case 1: return convert(contextclazzargs[0]);        
         case 2: return convert(contextclazzargs[0], args[1]);
         }
         Arity.raiseArgumentError(context.runtimeargs.length, 1, 1);
         return null;
     }

    
nurat_s_convert
 
     @JRubyMethod(name = "convert", meta = true, visibility = .)
     public static IRubyObject convert(ThreadContext contextIRubyObject recvIRubyObject a1) {
         if (a1.isNil()) {
             throw context.runtime.newTypeError("can't convert nil into Rational");
         }
 
         return convertCommon(contextrecva1context.runtime.getNil());
     }

    
nurat_s_convert
 
     @JRubyMethod(name = "convert", meta = true, visibility = .)
     public static IRubyObject convert(ThreadContext contextIRubyObject recvIRubyObject a1IRubyObject a2) {
         if (a1.isNil() || a2.isNil()) {
             throw context.runtime.newTypeError("can't convert nil into Rational");
         }
         
         return convertCommon(contextrecva1a2);
     }
     
     private static IRubyObject convertCommon(ThreadContext contextIRubyObject recvIRubyObject a1IRubyObject a2) {
         if (a1 instanceof RubyComplex) {
             RubyComplex a1Complex = (RubyComplex)a1;
             if (k_exact_p(a1Complex.getImage()) && f_zero_p(contexta1Complex.getImage())) a1 = a1Complex.getReal();            
         }
 
         if (a2 instanceof RubyComplex) {
             RubyComplex a2Complex = (RubyComplex)a2;
             if (k_exact_p(a2Complex.getImage()) && f_zero_p(contexta2Complex.getImage())) a2 = a2Complex.getReal();
         }
         
         DynamicScope scope = context.getCurrentScope();
         IRubyObject backref = scope.getBackRef(context.runtime);
         if (backref instanceof RubyMatchData) ((RubyMatchData)backref).use();
         
         if (a1 instanceof RubyFloat) {
             a1 = f_to_r(contexta1);
         } else if (a1 instanceof RubyString) {
             a1 = str_to_r_strict(contexta1);
         } else {
             if (a1.respondsTo("to_r")) {
                 a1 = f_to_r(contexta1);
             }
         }
         
         if (a2 instanceof RubyFloat) {
             a2 = f_to_r(contexta2);
         } else if (a2 instanceof RubyString) {
             a2 = str_to_r_strict(contexta2);
         }
         
         scope.setBackRef(backref);
 
         if (a1 instanceof RubyRational) {
             if (a2.isNil() || (k_exact_p(a2) && f_one_p(contexta2))) return a1;
         }
 
         if (a2.isNil()) {
             if (a1 instanceof RubyNumeric && !f_integer_p(contexta1).isTrue()) return a1;
             return newInstance(contextrecva1);
         } else {
             if (a1 instanceof RubyNumeric && a2 instanceof RubyNumeric &&
                 (!f_integer_p(contexta1).isTrue() || !f_integer_p(contexta2).isTrue())) {
                 return f_div(contexta1a2);
             }
             return newInstance(contextrecva1a2);
         }
     }

    
nurat_numerator
 
     @JRubyMethod(name = "numerator")
     @Override
     public IRubyObject numerator(ThreadContext context) {
         return ;
     }

    
nurat_denominator
 
     @JRubyMethod(name = "denominator")
     @Override
     public IRubyObject denominator(ThreadContext context) {
         return ;
     }

    
f_imul
 
     private static IRubyObject f_imul(ThreadContext contextlong along b) {
         Ruby runtime = context.runtime;
         if (a == 0 || b == 0) {
             return RubyFixnum.zero(runtime);
         } else if (a == 1) {
             return RubyFixnum.newFixnum(runtimeb);
         } else if (b == 1) {
             return RubyFixnum.newFixnum(runtimea);
         }
 
         long c = a * b;
         if(c / a != b) {
             return RubyBignum.newBignum(runtimea).op_mul(context, RubyBignum.newBignum(runtimeb));
         }
         return RubyFixnum.newFixnum(runtimec);
     }
    
    
f_addsub
 
     private IRubyObject f_addsub(ThreadContext contextIRubyObject anumIRubyObject adenIRubyObject bnumIRubyObject bdenboolean plus) {
         Ruby runtime = context.runtime;
         IRubyObject newNumnewDengab;
         if (anum instanceof RubyFixnum && aden instanceof RubyFixnum &&
             bnum instanceof RubyFixnum && bden instanceof RubyFixnum) {
             long an = ((RubyFixnum)anum).getLongValue();
             long ad = ((RubyFixnum)aden).getLongValue();
             long bn = ((RubyFixnum)bnum).getLongValue();
             long bd = ((RubyFixnum)bden).getLongValue();
             long ig = i_gcd(adbd);
 
             g = RubyFixnum.newFixnum(runtimeig);
             a = f_imul(contextanbd / ig);
             b = f_imul(contextbnad / ig);
         } else {
             g = f_gcd(contextadenbden);
             a = f_mul(contextanumf_idiv(contextbdeng));
             b = f_mul(contextbnumf_idiv(contextadeng));
         }
 
         IRubyObject c = plus ? f_add(contextab) : f_sub(contextab);
 
         b = f_idiv(contextadeng);
         g = f_gcd(contextcg);
         newNum = f_idiv(contextcg);
         a = f_idiv(contextbdeng);
         newDen = f_mul(contextab);
         
         return RubyRational.newRationalNoReduce(contextgetMetaClass(), newNumnewDen);
     }
    
    
nurat_add
 
     @JRubyMethod(name = "+")
     public IRubyObject op_add(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             return f_addsub(contextother, RubyFixnum.one(context.runtime), true);
         } else if (other instanceof RubyFloat) {
             return f_add(contextf_to_f(contextthis), other);
         } else if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             return f_addsub(contextotherRational.numotherRational.dentrue);
         }            
         return coerceBin(context"+"other);
     }
    
    
nurat_sub
 
     @JRubyMethod(name = "-")
     public IRubyObject op_sub(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             return f_addsub(contextother, RubyFixnum.one(context.runtime), false);
         } else if (other instanceof RubyFloat) {
             return f_sub(contextf_to_f(contextthis), other);
         } else if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             return f_addsub(contextotherRational.numotherRational.denfalse);
         }
         return coerceBin(context"-"other);
     }
    
    
f_muldiv
 
     private IRubyObject f_muldiv(ThreadContext contextIRubyObject anumIRubyObject adenIRubyObject bnumIRubyObject bdenboolean mult) {
         if (!mult) {
             if (f_negative_p(contextbnum)) {
                 anum = f_negate(contextanum);
                 bnum = f_negate(contextbnum);
             }
             IRubyObject tmp =  bnum;
             bnum = bden;
             bden = tmp;
         }
         
         final IRubyObject newNumnewDen;
         if (anum instanceof RubyFixnum && aden instanceof RubyFixnum &&
             bnum instanceof RubyFixnum && bden instanceof RubyFixnum) {
             long an = ((RubyFixnum)anum).getLongValue();
             long ad = ((RubyFixnum)aden).getLongValue();
             long bn = ((RubyFixnum)bnum).getLongValue();
             long bd = ((RubyFixnum)bden).getLongValue();
             long g1 = i_gcd(anbd);
             long g2 = i_gcd(adbn);
             
             newNum = f_imul(contextan / g1bn / g2);
             newDen = f_imul(contextad / g2bd / g1);
         } else {
             IRubyObject g1 = f_gcd(contextanumbden); 
             IRubyObject g2 = f_gcd(contextadenbnum);
             
             newNum = f_mul(contextf_idiv(contextanumg1), f_idiv(contextbnumg2));
             newDen = f_mul(contextf_idiv(contextadeng2), f_idiv(contextbdeng1));
         }
 
         return RubyRational.newRationalNoReduce(contextgetMetaClass(), newNumnewDen);
     }

    
nurat_mul
 
     @JRubyMethod(name = "*")
     public IRubyObject op_mul(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             return f_muldiv(contextother, RubyFixnum.one(context.runtime), true);
         } else if (other instanceof RubyFloat) {
             return f_mul(contextf_to_f(contextthis), other);
         } else if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             return f_muldiv(contextotherRational.numotherRational.dentrue);
         }
         return coerceBin(context"*"other);
     }
    
    
nurat_div
 
     @JRubyMethod(name = {"/""quo"})
     public IRubyObject op_div(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             if (f_zero_p(contextother)) {
                 throw context.runtime.newZeroDivisionError();
             }
             return f_muldiv(contextother, RubyFixnum.one(context.runtime), false);
         } else if (other instanceof RubyFloat) {
             return f_to_f(contextthis).callMethod(context"/"other);
         } else if (other instanceof RubyRational) {
             if (f_zero_p(contextother)) {
                 throw context.runtime.newZeroDivisionError();
             }
             RubyRational otherRational = (RubyRational)other;
             return f_muldiv(contextotherRational.numotherRational.denfalse);
         }
         return coerceBin(context"/"other);
     }

    
nurat_fdiv
 
     @JRubyMethod(name = "fdiv")
     public IRubyObject op_fdiv(ThreadContext contextIRubyObject other) {
         return f_div(contextf_to_f(contextthis), other);
     }

    
nurat_expt
 
     @JRubyMethod(name = "**")
     public IRubyObject op_expt(ThreadContext contextIRubyObject other) {
         Ruby runtime = context.runtime;
 
         if (k_exact_p(other) && f_zero_p(contextother)) {
             return RubyRational.newRationalBang(contextgetMetaClass(), RubyFixnum.one(runtime));
         }
 
         if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             if (f_one_p(contextotherRational.den)) other = otherRational.num;
         }
 
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {        
             final IRubyObject tnumtden;
             IRubyObject res = f_cmp(contextother, RubyFixnum.zero(runtime));
             if (res == RubyFixnum.one(runtime)) {
                 tnum = f_expt(contextother);
                 tden = f_expt(contextother);
             } else if (res == RubyFixnum.minus_one(runtime)){
                 tnum = f_expt(contextf_negate(contextother));
                 tden = f_expt(contextf_negate(contextother));
             } else {
                 tnum = tden = RubyFixnum.one(runtime);
             }
             return RubyRational.newRational(contextgetMetaClass(), tnumtden);
         } else if (other instanceof RubyFloat || other instanceof RubyRational) {
             return f_expt(contextf_to_f(contextthis), other);
         }
         return coerceBin(context"**"other);
     }

    
    
nurat_cmp
 
     @JRubyMethod(name = "<=>")
     public IRubyObject op_cmp(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             if ( instanceof RubyFixnum && ((RubyFixnum)).getLongValue() == 1) return f_cmp(contextother);
             return f_cmp(contextthis, RubyRational.newRationalBang(contextgetMetaClass(), other));
         } else if (other instanceof RubyFloat) {
             return f_cmp(contextf_to_f(contextthis), other);
         } else if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             final IRubyObject num1num2;
             if ( instanceof RubyFixnum &&  instanceof RubyFixnum &&
                 otherRational.num instanceof RubyFixnum && otherRational.den instanceof RubyFixnum) {
                 num1 = f_imul(context, ((RubyFixnum)).getLongValue(), ((RubyFixnum)otherRational.den).getLongValue());
                 num2 = f_imul(context, ((RubyFixnum)otherRational.num).getLongValue(), ((RubyFixnum)).getLongValue());
             } else {
                 num1 = f_mul(contextotherRational.den);
                 num2 = f_mul(contextotherRational.num);
             }
             return f_cmp(contextf_sub(contextnum1num2), RubyFixnum.zero(context.runtime));
         }
         return coerceBin(context"<=>"other);             
     }

    
nurat_equal_p
 
     @JRubyMethod(name = "==")
     @Override
     public IRubyObject op_equal(ThreadContext contextIRubyObject other) {
         Ruby runtime = context.runtime;
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             if (f_zero_p(context) && f_zero_p(contextother)) return runtime.getTrue();
             if (!( instanceof RubyFixnum) || ((RubyFixnum)).getLongValue() != 1) return runtime.getFalse();
             return f_equal(contextother);
         } else if (other instanceof RubyFloat) {
             return f_equal(contextf_to_f(contextthis), other);
         } else if (other instanceof RubyRational) {
             RubyRational otherRational = (RubyRational)other;
             if (f_zero_p(context) && f_zero_p(contextotherRational.num)) return runtime.getTrue();
             return runtime.newBoolean(f_equal(contextotherRational.num).isTrue() &&
                     f_equal(contextotherRational.den).isTrue());
 
         }
         return f_equal(contextotherthis);
     }

    
nurat_coerce
 
     @JRubyMethod(name = "coerce")
     public IRubyObject op_coerce(ThreadContext contextIRubyObject other) {
         Ruby runtime = context.runtime;
         if (other instanceof RubyFixnum || other instanceof RubyBignum) {
             return runtime.newArray(RubyRational.newRationalBang(contextgetMetaClass(), other), this);
         } else if (other instanceof RubyFloat) {
             return runtime.newArray(otherf_to_f(contextthis));
         } else if (other instanceof RubyRational) {
             return runtime.newArray(otherthis);
         }
         throw runtime.newTypeError(other.getMetaClass() + " can't be coerced into " + getMetaClass());
     }

    
nurat_idiv
 
     @JRubyMethod(name = "div", compat = .)
     public IRubyObject op_idiv(ThreadContext contextIRubyObject other) {
         return f_floor(contextf_div(contextthisother));
     }
 
     @JRubyMethod(name = "div", compat = .)
     public IRubyObject op_idiv19(ThreadContext contextIRubyObject other) {
         if (num2dbl(other) == 0.0) {
             throw context.runtime.newZeroDivisionError();
         }
         return op_idiv(contextother);
     }

    
nurat_mod
 
     @JRubyMethod(name = {"modulo""%"}, compat = .)
     public IRubyObject op_mod(ThreadContext contextIRubyObject other) {
         IRubyObject val = f_floor(contextf_div(contextthisother));
         return f_sub(contextthisf_mul(contextotherval));
     }
 
     @JRubyMethod(name = {"modulo""%"}, compat = .)
     public IRubyObject op_mod19(ThreadContext contextIRubyObject other) {
         if (num2dbl(other) == 0.0) {
             throw context.runtime.newZeroDivisionError();
         }
         return op_mod(contextother);
     }

    
nurat_divmod
 
     @JRubyMethod(name = "divmod", compat = .)
     public IRubyObject op_divmod(ThreadContext contextIRubyObject other) {
         IRubyObject val = f_floor(contextf_div(contextthisother));
         return context.runtime.newArray(valf_sub(contextthisf_mul(contextotherval)));
     }
 
     @JRubyMethod(name = "divmod", compat = .)
     public IRubyObject op_divmod19(ThreadContext contextIRubyObject other) {
         if (num2dbl(other) == 0.0) {
             throw context.runtime.newZeroDivisionError();
         }
         return op_divmod(contextother);
     }

    
nurat_rem
 
     @JRubyMethod(name = "remainder")
     public IRubyObject op_rem(ThreadContext contextIRubyObject other) {
         IRubyObject val = f_truncate(contextf_div(contextthisother));
         return f_sub(contextthisf_mul(contextotherval));
     }

    
nurat_abs
 
     @JRubyMethod(name = "abs")
     public IRubyObject op_abs(ThreadContext context) {
         if (!f_negative_p(contextthis)) return this;
         return f_negate(contextthis);
     }
 
     private IRubyObject op_roundCommonPre(ThreadContext contextIRubyObject n) {
         checkInteger(contextn);
         Ruby runtime = context.runtime;
         return f_expt(context, RubyFixnum.newFixnum(runtime, 10), n);
     }
 
     private IRubyObject op_roundCommonPost(ThreadContext contextIRubyObject sIRubyObject nIRubyObject b) {
         s = f_div(contextnewRationalBang(contextgetMetaClass(), s), b);
         if (f_lt_p(contextn, RubyFixnum.one(context.runtime)).isTrue()) s = f_to_i(contexts);
         return s;
     }

    
nurat_floor
 
     @JRubyMethod(name = "floor")
     public IRubyObject op_floor(ThreadContext context) {
         return f_idiv(context);
     }
 
     @JRubyMethod(name = "floor")
     public IRubyObject op_floor(ThreadContext contextIRubyObject n) {
         IRubyObject b = op_roundCommonPre(contextn);
         return op_roundCommonPost(context, ((RubyRational)f_mul(contextthisb)).op_floor(context), nb);
     }

    
nurat_ceil
 
     @JRubyMethod(name = "ceil")
     public IRubyObject op_ceil(ThreadContext context) {
         return f_negate(contextf_idiv(contextf_negate(context), ));
     }
 
     @JRubyMethod(name = "ceil")
     public IRubyObject op_ceil(ThreadContext contextIRubyObject n) {
         IRubyObject b = op_roundCommonPre(contextn);
         return op_roundCommonPost(context, ((RubyRational)f_mul(contextthisb)).op_ceil(context), nb);
     }
     
     @JRubyMethod(name = "to_i")
     public IRubyObject to_i(ThreadContext context) {
         return op_truncate(context);
     }

    
nurat_truncate
 
     @JRubyMethod(name = "truncate")
     public IRubyObject op_truncate(ThreadContext context) {
         if (f_negative_p(context)) {
             return f_negate(contextf_idiv(contextf_negate(context), ));
         }
         return f_idiv(context);
     }
 
     @JRubyMethod(name = "truncate")
     public IRubyObject op_truncate(ThreadContext contextIRubyObject n) {
         IRubyObject b = op_roundCommonPre(contextn);
         return op_roundCommonPost(context, ((RubyRational)f_mul(contextthisb)).op_truncate(context), nb);
     }

    
nurat_round
 
     @JRubyMethod(name = "round")
     public IRubyObject op_round(ThreadContext context) {
         IRubyObject myNum = this.;
         boolean neg = f_negative_p(contextmyNum);
         if (negmyNum = f_negate(contextmyNum);
 
         IRubyObject myDen = this.;
         IRubyObject two = RubyFixnum.two(context.runtime);
         myNum = f_add(contextf_mul(contextmyNumtwo), myDen);
         myDen = f_mul(contextmyDentwo);
         myNum = f_idiv(contextmyNummyDen);
 
         if (negmyNum = f_negate(contextmyNum);
         return myNum;
     }
 
     @JRubyMethod(name = "round")
     public IRubyObject op_round(ThreadContext contextIRubyObject n) {
         IRubyObject b = op_roundCommonPre(contextn);
         return op_roundCommonPost(context, ((RubyRational)f_mul(contextthisb)).op_round(context), nb);
     }

    
nurat_to_f
 
     private static long ML = (long)(Math.log(.) / Math.log(2.0) - 1);
     @JRubyMethod(name = "to_f")
     public IRubyObject to_f(ThreadContext context) {
         return context.runtime.newFloat(getDoubleValue(context));
     }
     
     @Override
     public double getDoubleValue() {
         return getDoubleValue(getRuntime().getCurrentContext());
     }
     
     public double getDoubleValue(ThreadContext context) {
         Ruby runtime = context.runtime;
         if (f_zero_p(context)) return 0;
 
         IRubyObject myNum = this.;
         IRubyObject myDen = this.;
 
         boolean minus = false;
         if (f_negative_p(contextmyNum)) {
             myNum = f_negate(contextmyNum);
             minus = true;
         }
 
         long nl = i_ilog2(contextmyNum);
         long dl = i_ilog2(contextmyDen);
 
         long ne = 0;
         if (nl > ) {
             ne = nl - ;
             myNum = f_rshift(contextmyNum, RubyFixnum.newFixnum(runtimene));
         }
 
         long de = 0;
         if (dl > ) {
             de = dl - ;
             myDen = f_rshift(contextmyDen, RubyFixnum.newFixnum(runtimede));
         }
 
         long e = ne - de;
 
         if (e > 1023 || e < -1022) {
             runtime.getWarnings().warn(.."out of Float range");
             return e > 0 ? . : 0;
         }
 
         double f = RubyNumeric.num2dbl(myNum) / RubyNumeric.num2dbl(myDen);
 
         if (minusf = -f;
 
         f = ldexp(fe);
 
         if (Double.isInfinite(f) || Double.isNaN(f)) {
             runtime.getWarnings().warn(.."out of Float range");
         }
 
         return f;
     }

    
nurat_to_r
 
     @JRubyMethod(name = "to_r")
     public IRubyObject to_r(ThreadContext context) {
         return this;
     }

    
nurat_rationalize
 
     @JRubyMethod(name = "rationalize", optional = 1, compat = .)
     public IRubyObject rationalize(ThreadContext contextIRubyObject[] args) {
 
         IRubyObject ab;
 
         if (args.length == 0) return to_r(context);
 
         if (f_negative_p(contextthis)) {
             return f_negate(context,
                     ((RubyRationalf_abs(contextthis)).rationalize(contextargs));
         }
 
         IRubyObject eps = f_abs(contextargs[0]);
         a = f_sub(contextthiseps);
         b = f_add(contextthiseps);
 
         if (f_equal(contextab).isTrue()) return this;
         IRubyObject[] ary = new IRubyObject[2];
         ary[0] = a;
         ary[1] = b;
         IRubyObject[] ans = nurat_rationalize_internal(contextary);
 
         return newRational(contextthis.ans[0], ans[1]);
     }

    
nurat_hash
 
     @JRubyMethod(name = "hash")
     public IRubyObject hash(ThreadContext context) {
         return f_xor(contextinvokedynamic(context), invokedynamic(context));
     }

    
nurat_to_s
 
     @JRubyMethod(name = "to_s")
     public IRubyObject to_s(ThreadContext context) {
         RubyString str = context.runtime.newString();
         str.append(f_to_s(context));
         str.cat((byte)'/');
         str.append(f_to_s(context));
         return str;
     }

    
nurat_inspect
 
     @JRubyMethod(name = "inspect")
     public IRubyObject inspect(ThreadContext context) {
         RubyString str = context.runtime.newString();
         str.cat((byte)'(');
         str.append(f_inspect(context));
         str.cat((byte)'/');
         str.append(f_inspect(context));
         str.cat((byte)')');
         return str;
     }

    
nurat_marshal_dump
    @JRubyMethod(name = "marshal_dump")
    public IRubyObject marshal_dump(ThreadContext context) {
        RubyArray dump = context.runtime.newArray();
        if (hasVariables()) dump.syncVariables(this);
        return dump;
    }

    
nurat_marshal_load
    @JRubyMethod(name = "marshal_load")
    public IRubyObject marshal_load(ThreadContext contextIRubyObject arg) {
        RubyArray load = arg.convertToArray();
         = load.size() > 0 ? load.eltInternal(0) : context.runtime.getNil();
         = load.size() > 1 ? load.eltInternal(1) : context.runtime.getNil();
        if (f_zero_p(context)) {
            throw context.runtime.newZeroDivisionError();
        }