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.f_abs;
  import static org.jruby.util.Numeric.f_abs2;
  import static org.jruby.util.Numeric.f_add;
  import static org.jruby.util.Numeric.f_arg;
  import static org.jruby.util.Numeric.f_conjugate;
  import static org.jruby.util.Numeric.f_denominator;
  import static org.jruby.util.Numeric.f_div;
  import static org.jruby.util.Numeric.f_divmod;
  import static org.jruby.util.Numeric.f_equal;
  import static org.jruby.util.Numeric.f_exact_p;
  import static org.jruby.util.Numeric.f_expt;
  import static org.jruby.util.Numeric.f_gt_p;
  import static org.jruby.util.Numeric.f_inspect;
  import static org.jruby.util.Numeric.f_lcm;
  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_numerator;
  import static org.jruby.util.Numeric.f_one_p;
  import static org.jruby.util.Numeric.f_polar;
  import static org.jruby.util.Numeric.f_quo;
  import static org.jruby.util.Numeric.f_real_p;
  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_xor;
  import static org.jruby.util.Numeric.f_zero_p;
  import static org.jruby.util.Numeric.k_exact_p;
  import static org.jruby.util.Numeric.k_inexact_p;
  
  
  import static org.jruby.javasupport.util.RuntimeHelpers.invokedynamic;
  import static org.jruby.runtime.invokedynamic.MethodNames.HASH;

1.9 complex.c as of revision: 20011
  
  
  @JRubyClass(name = "Complex", parent = "Numeric")
  public class RubyComplex extends RubyNumeric {
  
      public static RubyClass createComplexClass(Ruby runtime) {
          RubyClass complexc = runtime.defineClass("Complex"runtime.getNumeric(), );
          runtime.setComplex(complexc);
  
          complexc.index = .;
          complexc.setReifiedClass(RubyComplex.class);
          
          complexc.kindOf = new RubyModule.KindOf() {
              @Override
              public boolean isKindOf(IRubyObject objRubyModule type) {
                  return obj instanceof RubyComplex;
              }
          };
  
          complexc.defineAnnotatedMethods(RubyComplex.class);
  
          complexc.getSingletonClass().undefineMethod("allocate");
         complexc.getSingletonClass().undefineMethod("new");
 
         String[]undefined = {"<""<=""<=>"">"">=""between?""divmod",
                              "floor""ceil""modulo""round""step""truncate"};
 
         for (String undef : undefined) {
             complexc.undefineMethod(undef);
         }
 
         complexc.defineConstant("I", RubyComplex.newComplexConvert(runtime.getCurrentContext(), RubyFixnum.zero(runtime), RubyFixnum.one(runtime)));
 
         return complexc;
     }
 
     private static ObjectAllocator COMPLEX_ALLOCATOR = new ObjectAllocator() {
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             RubyFixnum zero = RubyFixnum.zero(runtime);
             return new RubyComplex(runtimeklasszerozero);
         }
     };

    
internal
 
     private RubyComplex(Ruby runtimeIRubyObject clazzIRubyObject realIRubyObject image) {
         super(runtime, (RubyClass)clazz);
         this. = real;
         this. = image;
     }

    
rb_complex_raw
 
     static RubyComplex newComplexRaw(Ruby runtimeIRubyObject xRubyObject y) {
         return new RubyComplex(runtimeruntime.getComplex(), xy);
     }

    
rb_complex_raw1
 
     static RubyComplex newComplexRaw(Ruby runtimeIRubyObject x) {
         return new RubyComplex(runtimeruntime.getComplex(), x, RubyFixnum.zero(runtime));
     }

    
rb_complex_new1
 
     public static IRubyObject newComplexCanonicalize(ThreadContext contextIRubyObject x) {
         return newComplexCanonicalize(contextx, RubyFixnum.zero(context.runtime));
     }
    
    
rb_complex_new
 
     public static IRubyObject newComplexCanonicalize(ThreadContext contextIRubyObject xIRubyObject y) {
         return canonicalizeInternal(contextcontext.runtime.getComplex(), xy);
     }

    
rb_complex_polar
 
     static IRubyObject newComplexPolar(ThreadContext contextIRubyObject xIRubyObject y) {
         return polar(contextcontext.runtime.getComplex(), xy);
     }

    
f_complex_new1
 
     static IRubyObject newComplex(ThreadContext contextIRubyObject clazzIRubyObject x) {
         return newComplex(contextclazzx, RubyFixnum.zero(context.runtime));
     }

    
f_complex_new2
 
     static IRubyObject newComplex(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) {
         assert !(x instanceof RubyComplex);
         return canonicalizeInternal(contextclazzxy);
     }
    
    
f_complex_new_bang2
 
     static RubyComplex newComplexBang(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) {
 // FIXME: what should these really be? Numeric?       assert x instanceof RubyComplex && y instanceof RubyComplex;
         return new RubyComplex(context.runtimeclazzxy);
     }

    
f_complex_new_bang1
 
     public static RubyComplex newComplexBang(ThreadContext contextIRubyObject clazzIRubyObject x) {
 // FIXME: what should this really be?       assert x instanceof RubyComplex;
         return newComplexBang(contextclazzx, RubyFixnum.zero(context.runtime));
     }
 
     private IRubyObject real;
     private IRubyObject image;
     
     IRubyObject getImage() {
         return ;
     }
 
     IRubyObject getReal() {
         return ;
     }

    
m_cos
 
     private static IRubyObject m_cos(ThreadContext contextIRubyObject x) {
         if (f_real_p(contextx).isTrue()) return RubyMath.cos(xx);
         RubyComplex complex = (RubyComplex)x;
         return newComplex(contextcontext.runtime.getComplex(),
                           f_mul(context, RubyMath.cos(xcomplex.real), RubyMath.cosh(xcomplex.image)),
                           f_mul(contextf_negate(context, RubyMath.sin(xcomplex.real)), RubyMath.sinh(xcomplex.image)));
     }

    
m_sin
 
     private static IRubyObject m_sin(ThreadContext contextIRubyObject x) {
         if (f_real_p(contextx).isTrue()) return RubyMath.sin(xx);
         RubyComplex complex = (RubyComplex)x;
         return newComplex(contextcontext.runtime.getComplex(),
                           f_mul(context, RubyMath.sin(xcomplex.real), RubyMath.cosh(xcomplex.image)),
                           f_mul(context, RubyMath.cos(xcomplex.real), RubyMath.sinh(xcomplex.image)));
     }    
    
    
m_sqrt
 
     private static IRubyObject m_sqrt(ThreadContext contextIRubyObject x) {
         if (f_real_p(contextx).isTrue()) {
             if (!f_negative_p(contextx)) return RubyMath.sqrt(xx);
             return newComplex(contextcontext.runtime.getComplex(),
                               RubyFixnum.zero(context.runtime),
                               RubyMath.sqrt(xf_negate(contextx)));
         } else {
             RubyComplex complex = (RubyComplex)x;
             if (f_negative_p(contextcomplex.image)) {
                 return f_conjugate(contextm_sqrt(contextf_conjugate(contextx)));
             } else {
                 IRubyObject a = f_abs(contextx);
                 IRubyObject two = RubyFixnum.two(context.runtime);
                 return newComplex(contextcontext.runtime.getComplex(),
                                   RubyMath.sqrt(xf_div(contextf_add(contextacomplex.real), two)),
                                   RubyMath.sqrt(xf_div(contextf_sub(contextacomplex.real), two)));
             }
         }
     }

    
nucomp_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 = .)
     public static IRubyObject newInstanceBang(ThreadContext contextIRubyObject recvIRubyObject real) {
         if (!(real instanceof RubyNumeric)) real = f_to_i(contextreal);
         return new RubyComplex(context.runtimerecvreal, RubyFixnum.zero(context.runtime));
     }
 
     @JRubyMethod(name = "new!", meta = true, visibility = .)
     public static IRubyObject newInstanceBang(ThreadContext contextIRubyObject recvIRubyObject realIRubyObject image) {
         if (!(real instanceof RubyNumeric)) real = f_to_i(contextreal);
         if (!(image instanceof RubyNumeric)) image = f_to_i(contextimage);
         return new RubyComplex(context.runtimerecvrealimage);
     }

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

    
nucomp_real_check (might go to bimorphic)
 
     private static void realCheck(ThreadContext contextIRubyObject num) {
         switch (num.getMetaClass().) {
         case .:
         case .:
         case .:
         case .:
             break;
         default:
              if (!(num instanceof RubyNumeric ) || !f_real_p(contextnum).isTrue()) {
                  throw context.runtime.newTypeError("not a real");
              }
         }
     }

    
nucomp_s_canonicalize_internal
 
     private static final boolean CL_CANON = .;
     private static IRubyObject canonicalizeInternal(ThreadContext contextIRubyObject clazzIRubyObject realIRubyObject image) {
         if (.) {
             if (f_zero_p(contextimage) &&
                     (! || k_exact_p(image)) &&
                     )
                     return real;
         }
         if (f_real_p(contextreal).isTrue() &&
                    f_real_p(contextimage).isTrue()) {
             return new RubyComplex(context.runtimeclazzrealimage);
         } else if (f_real_p(contextreal).isTrue()) {
             RubyComplex complex = (RubyComplex)image;
             return new RubyComplex(context.runtimeclazz,
                                    f_sub(contextrealcomplex.image),
                                    f_add(context, RubyFixnum.zero(context.runtime), complex.real));
         } else if (f_real_p(contextimage).isTrue()) {
             RubyComplex complex = (RubyComplex)real;
             return new RubyComplex(context.runtimeclazz,
                                    complex.real,
                                    f_add(contextcomplex.imageimage));
         } else {
             RubyComplex complex1 = (RubyComplex)real;
             RubyComplex complex2 = (RubyComplex)image;
             return new RubyComplex(context.runtimeclazz,
                                    f_sub(contextcomplex1.realcomplex2.image),
                                    f_add(contextcomplex1.imagecomplex2.real));
         }
     }
    
    
nucomp_s_new
 
     @Deprecated
     public static IRubyObject newInstance(ThreadContext contextIRubyObject recvIRubyObject[]args) {
         switch (args.length) {
         case 1: return newInstance(contextrecvargs[0]);
         case 2: return newInstance(contextrecvargs[0], args[1]);
         }
         Arity.raiseArgumentError(context.runtimeargs.length, 1, 1);
         return null;
     }
 
     // @JRubyMethod(name = "new", meta = true, visibility = Visibility.PRIVATE)
     public static IRubyObject newInstanceNew(ThreadContext contextIRubyObject recvIRubyObject real) {
         return newInstance(contextrecvreal);
     }
 
     @JRubyMethod(name = {"rect""rectangular"}, meta = true)
     public static IRubyObject newInstance(ThreadContext contextIRubyObject recvIRubyObject real) {
         realCheck(contextreal);
         return canonicalizeInternal(contextrecvreal, RubyFixnum.zero(context.runtime));
     }
 
     // @JRubyMethod(name = "new", meta = true, visibility = Visibility.PRIVATE)
     public static IRubyObject newInstanceNew(ThreadContext contextIRubyObject recvIRubyObject realIRubyObject image) {
         return newInstance(contextrecvrealimage);
     }
 
     @JRubyMethod(name = {"rect""rectangular"}, meta = true)
     public static IRubyObject newInstance(ThreadContext contextIRubyObject recvIRubyObject realIRubyObject image) {
         realCheck(contextreal);
         realCheck(contextimage);
         return canonicalizeInternal(contextrecvrealimage);
     }

    
f_complex_polar
 
     private static IRubyObject f_complex_polar(ThreadContext contextIRubyObject clazzIRubyObject xIRubyObject y) {
         assert !(x instanceof RubyComplex) && !(y instanceof RubyComplex);
         return canonicalizeInternal(contextclazz,
                                              f_mul(contextxm_cos(contexty)),
                                              f_mul(contextxm_sin(contexty)));
     }

    
nucomp_s_polar
 
     @JRubyMethod(name = "polar", meta = true)
     public static IRubyObject polar(ThreadContext contextIRubyObject clazzIRubyObject absIRubyObject arg) {
         return f_complex_polar(contextclazzabsarg);
     }

    
nucomp_s_polar
 
     @JRubyMethod(name = "polar", meta = true, required = 1, optional = 1, compat = .)
     public static IRubyObject polar19(ThreadContext contextIRubyObject clazzIRubyObject[] args) {
         IRubyObject abs = args[0];
         IRubyObject arg;
         if (args.length < 2) {
             arg = RubyFixnum.zero(context.runtime);
         } else {
             arg = args[1];
         }
         realCheck(contextabs);
         realCheck(contextarg);
         return f_complex_polar(contextclazzabsarg);
     }

    
rb_Complex1
 
     public static IRubyObject newComplexConvert(ThreadContext contextIRubyObject x) {
         return newComplexConvert(contextx, RubyFixnum.zero(context.runtime));
     }

    
rb_Complex/rb_Complex2
 
     public static IRubyObject newComplexConvert(ThreadContext contextIRubyObject xIRubyObject y) {
         return convert(contextcontext.runtime.getComplex(), xy);
     }
 
     @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;
     }

    
nucomp_s_convert
 
     @JRubyMethod(name = "convert", meta = true, visibility = .)
     public static IRubyObject convert(ThreadContext contextIRubyObject recvIRubyObject a1) {
         return convertCommon(contextrecva1context.runtime.getNil());
     }

    
nucomp_s_convert
 
     @JRubyMethod(name = "convert", meta = true, visibility = .)
     public static IRubyObject convert(ThreadContext contextIRubyObject recvIRubyObject a1IRubyObject a2) {
         return convertCommon(contextrecva1a2);
     }
     
     private static IRubyObject convertCommon(ThreadContext contextIRubyObject recvIRubyObject a1IRubyObject a2) {
         DynamicScope scope = context.getCurrentScope();
         IRubyObject backref = scope.getBackRef(context.runtime);
         if (backref instanceof RubyMatchData) ((RubyMatchData)backref).use();
 
         if (a1 instanceof RubyStringa1 = str_to_c_strict(contexta1);
         if (a2 instanceof RubyStringa2 = str_to_c_strict(contexta2);
 
         scope.setBackRef(backref);
 
         if (a1 instanceof RubyComplex) {
             RubyComplex a1Complex = (RubyComplex)a1;
             if (k_exact_p(a1Complex.image) && f_zero_p(contexta1Complex.image)) {
                 a1 = a1Complex.real;
             }
         }
 
         if (a2 instanceof RubyComplex) {
             RubyComplex a2Complex = (RubyComplex)a2;
             if (k_exact_p(a2Complex.image) && f_zero_p(contexta2Complex.image)) {
                 a2 = a2Complex.real;
             }
         }
 
         if (a1 instanceof RubyComplex) {
             if (a2.isNil() || (k_exact_p(a2) && f_zero_p(contexta2))) return a1;
         }
 
         if (a2.isNil()) {
             if (a1 instanceof RubyNumeric && !f_real_p(contexta1).isTrue()) return a1;
             return newInstance(contextrecva1);
         } else {
             if (a1 instanceof RubyNumeric && a2 instanceof RubyNumeric &&
                 (!f_real_p(contexta1).isTrue() || !f_real_p(contexta2).isTrue())) {
                 Ruby runtime = context.runtime;
                 return f_add(contexta1,
                              f_mul(contexta2newComplexBang(contextruntime.getComplex(),
                                      RubyFixnum.zero(runtime), RubyFixnum.one(runtime))));
             }
             return newInstance(contextrecva1a2);
         }
     }

    
nucomp_real
 
     @JRubyMethod(name = "real")
     public IRubyObject real() {
         return ;
     }
    
    
nucomp_image
 
     @JRubyMethod(name = {"imaginary""imag"})
     public IRubyObject image() {
         return ;
     }

    
nucomp_negate
 
     @JRubyMethod(name = "-@")
     public IRubyObject negate(ThreadContext context) {
         return newComplex(contextgetMetaClass(), f_negate(context), f_negate(context));
     }

    
nucomp_add
 
     @JRubyMethod(name = "+")
     public IRubyObject op_add(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplex)other;
             return newComplex(contextgetMetaClass(), 
                               f_add(contextotherComplex.real),
                               f_add(contextotherComplex.image));
         } else if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             return newComplex(contextgetMetaClass(), f_add(contextother), );
         }
         return coerceBin(context"+"other);
     }

    
nucomp_sub
 
     @JRubyMethod(name = "-")
     public IRubyObject op_sub(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplex)other;
             return newComplex(contextgetMetaClass(), 
                               f_sub(contextotherComplex.real),
                               f_sub(contextotherComplex.image));
         } else if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             return newComplex(contextgetMetaClass(), f_sub(contextother), );
         }
         return coerceBin(context"-"other);
     }

    
nucomp_mul
 
     @JRubyMethod(name = "*")
     public IRubyObject op_mul(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplex)other;
             IRubyObject realp = f_sub(context
                                 f_mul(contextotherComplex.real),
                                 f_mul(contextotherComplex.image));
             IRubyObject imagep = f_add(context,
                                 f_mul(contextotherComplex.image),
                                 f_mul(contextotherComplex.real));
             
             return newComplex(contextgetMetaClass(), realpimagep); 
         } else if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             return newComplex(contextgetMetaClass(),
                     f_mul(contextother),
                     f_mul(contextother));
         }
         return coerceBin(context"*"other);
     }
    
    
nucomp_div / nucomp_quo
 
     @JRubyMethod(name = {"/""quo"})
     public IRubyObject op_div(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplex)other;
             if ( instanceof RubyFloat ||  instanceof RubyFloat ||
                 otherComplex.real instanceof RubyFloat || otherComplex.image instanceof RubyFloat) {
                 IRubyObject magn = RubyMath.hypot(thisotherComplex.realotherComplex.image);
                 IRubyObject tmp = newComplexBang(contextgetMetaClass(),
                                                  f_quo(contextotherComplex.realmagn),
                                                  f_quo(contextotherComplex.imagemagn));
                 return f_quo(contextf_mul(contextthisf_conjugate(contexttmp)), magn);
             }
             return f_quo(contextf_mul(contextthisf_conjugate(contextother)), f_abs2(contextother));
         } else if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             return newComplex(contextgetMetaClass(),
                     f_quo(contextother),
                     f_quo(contextother));
         }
         return coerceBin(context"/"other);
     }

    
nucomp_fdiv
 
     @JRubyMethod(name = "fdiv")
     @Override
     public IRubyObject fdiv(ThreadContext contextIRubyObject other) {
         IRubyObject complex = newComplex(contextgetMetaClass(),
                                          f_to_f(context),   
                                          f_to_f(context));
 
         return f_div(contextcomplexother);
     }

    
nucomp_expt
 
     @JRubyMethod(name = "**")
     public IRubyObject op_expt(ThreadContext contextIRubyObject other) {
         if (k_exact_p(other) && f_zero_p(contextother)) {
             return newComplexBang(contextgetMetaClass(), RubyFixnum.one(context.runtime));
         } else if (other instanceof RubyRational && f_one_p(contextf_denominator(contextother))) {
             other = f_numerator(contextother); 
         } 
 
         if (other instanceof RubyComplex) {
             RubyArray a = f_polar(contextthis).convertToArray();
             IRubyObject r = a.eltInternal(0);
             IRubyObject theta = a.eltInternal(1);
             RubyComplex otherComplex = (RubyComplex)other;
             IRubyObject nr = RubyMath.exp(thisf_sub(context
                                                       f_mul(contextotherComplex.real, RubyMath.log(thisr)),
                                                       f_mul(contextotherComplex.imagetheta)));
             IRubyObject ntheta = f_add(context,
                                         f_mul(contextthetaotherComplex.real),
                                         f_mul(contextotherComplex.image, RubyMath.log(thisr)));
             return polar(contextgetMetaClass(), nrntheta);
         } else if (other instanceof RubyInteger) {
             IRubyObject one = RubyFixnum.one(context.runtime);
             if (f_gt_p(contextother, RubyFixnum.zero(context.runtime)).isTrue()) {
                 IRubyObject x = this;
                 IRubyObject z = x;
                 IRubyObject n = f_sub(contextotherone);
 
                 IRubyObject two = RubyFixnum.two(context.runtime);
                 
                 while (!f_zero_p(contextn)) {
                     
                     RubyArray a = f_divmod(contextntwo).convertToArray();
 
                     while (f_zero_p(contexta.eltInternal(1))) {
                         RubyComplex xComplex = (RubyComplex)x;
                         x = newComplex(contextgetMetaClass(),
                                        f_sub(contextf_mul(contextxComplex.realxComplex.real),
                                                       f_mul(contextxComplex.imagexComplex.image)),
                                        f_mul(contextf_mul(contexttwoxComplex.real), xComplex.image));
                         
                         n = a.eltInternal(0);
                         a = f_divmod(contextntwo).convertToArray();
                     }
                     z = f_mul(contextzx);
                     n = f_sub(contextnone);
                 }
                 return z;
             }
             return f_expt(contextf_div(contextf_to_r(contextone), this), f_negate(contextother));
         } else if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             RubyArray a = f_polar(contextthis).convertToArray();
             IRubyObject r = a.eltInternal(0);
             IRubyObject theta = a.eltInternal(1);
             return f_complex_polar(contextgetMetaClass(), f_expt(contextrother), f_mul(contextthetaother));
         }
         return coerceBin(context"**"other);
     }

    
nucomp_equal_p
 
     @JRubyMethod(name = "==")
     @Override
     public IRubyObject op_equal(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplexother;
             boolean test = f_equal(contextotherComplex.real).isTrue() &&
                     f_equal(contextotherComplex.image).isTrue();
 
             return context.runtime.newBoolean(test);
         }
 
         if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             boolean test = f_equal(contextother).isTrue() && f_zero_p(context);
 
             return context.runtime.newBoolean(test);
         }
         
         return f_equal(contextotherthis);
     }

    
nucomp_coerce
 
     @JRubyMethod(name = "coerce")
     public IRubyObject coerce(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyNumeric && f_real_p(contextother).isTrue()) {
             return context.runtime.newArray(newComplexBang(contextgetMetaClass(), other), this);
         }
         if (other instanceof RubyComplex) {
             return context.runtime.newArray(otherthis);
         }
         throw context.runtime.newTypeError(other.getMetaClass().getName() + " can't be coerced into " + getMetaClass().getName());
     }

    
nucomp_abs
 
     @JRubyMethod(name = {"abs""magnitude"})
     @Override
     public IRubyObject abs(ThreadContext context) {
         return RubyMath.hypot(this);
     }

    
nucomp_abs2
 
     @JRubyMethod(name = "abs2")
     @Override
     public IRubyObject abs2(ThreadContext context) {
         return f_add(context,
                      f_mul(context),
                      f_mul(context));
     }

    
nucomp_arg
 
     @JRubyMethod(name = {"arg""angle""phase"})
     @Override
     public IRubyObject arg(ThreadContext context) {
         return RubyMath.atan2(this);
     }

    
nucomp_rect
 
     @JRubyMethod(name = {"rectangular""rect"})
     @Override
     public IRubyObject rect(ThreadContext context) {
         return context.runtime.newArray();
     }

    
nucomp_polar
 
     @JRubyMethod(name = "polar")
     @Override
     public IRubyObject polar(ThreadContext context) {
         return context.runtime.newArray(f_abs(contextthis), f_arg(contextthis));
     }

    
nucomp_conjugate
 
     @JRubyMethod(name = {"conjugate""conj""~"})
     @Override
     public IRubyObject conjugate(ThreadContext context) {
         return newComplex(contextgetMetaClass(), f_negate(context));
     }

    
nucomp_real_p
 
     @JRubyMethod(name = "real?")
     public IRubyObject real_p(ThreadContext context) {
         return context.runtime.getFalse();
     }

    
nucomp_complex_p
 
     // @JRubyMethod(name = "complex?")
     public IRubyObject complex_p(ThreadContext context) {
         return context.runtime.getTrue();
     }

    
nucomp_exact_p
 
     // @JRubyMethod(name = "exact?")
     public IRubyObject exact_p(ThreadContext context) {
         return (f_exact_p(context).isTrue() && f_exact_p(context).isTrue()) ? context.runtime.getTrue() : context.runtime.getFalse();
     }

    
nucomp_exact_p
 
     // @JRubyMethod(name = "inexact?")
     public IRubyObject inexact_p(ThreadContext context) {
         return exact_p(context).isTrue() ? context.runtime.getFalse() : context.runtime.getTrue();
     }

    
nucomp_denominator
 
     @JRubyMethod(name = "denominator")
     public IRubyObject demoninator(ThreadContext context) {
         return f_lcm(contextf_denominator(context), f_denominator(context));
     }

    
nucomp_numerator
 
     @JRubyMethod(name = "numerator")
     @Override
     public IRubyObject numerator(ThreadContext context) {
         IRubyObject cd = callMethod(context"denominator");
         return newComplex(contextgetMetaClass(),
                           f_mul(context
                                 f_numerator(context),
                                 f_div(contextcdf_denominator(context))),
                           f_mul(context,
                                 f_numerator(context),
                                 f_div(contextcdf_denominator(context))));
     }

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

    
nucomp_eql_p
 
     @JRubyMethod(name = "eql?")
     @Override
     public IRubyObject eql_p(ThreadContext contextIRubyObject other) {
         if (other instanceof RubyComplex) {
             RubyComplex otherComplex = (RubyComplex)other;
             if (.getMetaClass() == otherComplex.real.getMetaClass() &&
                 .getMetaClass() == otherComplex.image.getMetaClass() &&
                 f_equal(contextthisotherComplex).isTrue()) {
                 return context.runtime.getTrue();
             }
         }
         return context.runtime.getFalse();
     }

    
f_signbit
 
     private static boolean signbit(ThreadContext contextIRubyObject x) {
         if (x instanceof RubyFloat) {
             double value = ((RubyFloat)x).getDoubleValue();
             return !Double.isNaN(value) && Double.doubleToLongBits(value) < 0;
         }
         return f_negative_p(contextx);
     }

    
f_tpositive_p
 
     private static boolean tpositive_p(ThreadContext contextIRubyObject x) {
         return !signbit(contextx);
     }

    
nucomp_to_s
 
     @JRubyMethod(name = "to_s")
     public IRubyObject to_s(ThreadContext context) {
         boolean impos = tpositive_p(context);
 
         RubyString str = f_to_s(context).convertToString();
         str.cat(impos ? (byte)'+' : (byte)'-');
         str.cat(f_to_s(contextf_abs(context)).convertToString().getByteList());
         if (!lastCharDigit(str)) str.cat((byte)'*');
         str.cat((byte)'i');
         return str;
     }

    
nucomp_inspect
 
     @JRubyMethod(name = "inspect")
     public IRubyObject inspect(ThreadContext context) {
         boolean impos = tpositive_p(context);
         RubyString str = context.runtime.newString();
         str.cat((byte)'(');
         str.cat(f_inspect(context).convertToString().getByteList());
         str.cat(impos ? (byte)'+' : (byte)'-');
         str.cat(f_inspect(contextf_abs(context)).convertToString().getByteList());
         if (!lastCharDigit(str)) str.cat((byte)'*');
         str.cat((byte)'i');
         str.cat((byte)')');
         return str;
     }
 
     private static boolean lastCharDigit(RubyString str) {
         ByteList bytes = str.getByteList();
         return ..isDigit(bytes.getUnsafeBytes()[bytes.getBegin() + bytes.getRealSize() - 1]);
     }

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

    
nucomp_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 (load.hasVariables()) syncVariables((IRubyObject)load);
         return this;
     }

    
nucomp_to_i
 
     @JRubyMethod(name = "to_i")
     public IRubyObject to_i(ThreadContext context) {
         if (k_inexact_p() || !f_zero_p(context)) {
             throw context.runtime.newRangeError("can't convert " + f_to_s(contextthis).convertToString() + " into Integer");
         }
         return f_to_i(context);
     }

    
nucomp_to_f
 
     @JRubyMethod(name = "to_f")
     public IRubyObject to_f(ThreadContext context) {
         if (k_inexact_p() || !f_zero_p(context)) {
             throw context.runtime.newRangeError("can't convert " + f_to_s(contextthis).convertToString() + " into Float");
         }
         return f_to_f(context);
     }

    
nucomp_to_r
 
     @JRubyMethod(name = "to_r")
     public IRubyObject to_r(ThreadContext context) {
         if (k_inexact_p() || !f_zero_p(context)) {
             throw context.runtime.newRangeError("can't convert " + f_to_s(contextthis).convertToString() + " into Rational");
         }
         return f_to_r(context);
     }

    
nucomp_rationalize
 
     @JRubyMethod(name = "rationalize", optional = 1, compat = .)
     public IRubyObject rationalize(ThreadContext contextIRubyObject[] args) {
         if (k_inexact_p() || !f_zero_p(context)) {
             throw context.runtime.newRangeError("can't convert " + f_to_s(contextthis).convertToString() + " into Rational");
         }
         return .callMethod(context"rationalize"args);
     }
     
     static RubyArray str_to_c_internal(ThreadContext contextIRubyObject recv) {
         RubyString s = recv.convertToString();
         ByteList bytes = s.getByteList();
 
         Ruby runtime = context.runtime;
         if (bytes.getRealSize() == 0) return runtime.newArray(runtime.getNil(), recv);
 
         IRubyObject srsire;
         sr = si = re = runtime.getNil();
         boolean po = false;
         IRubyObject m = RubyRegexp.newDummyRegexp(runtime..).callMethod(context"match"s);
 
         if (!m.isNil()) {
             sr = m.callMethod(context"[]", RubyFixnum.one(runtime));
             si = m.callMethod(context"[]", RubyFixnum.two(runtime));
             re = m.callMethod(context"post_match");
             po = true;
         }
 
         if (m.isNil()) {
             m = RubyRegexp.newDummyRegexp(runtime..).callMethod(context"match"s);
 
             if (!m.isNil()) {
                 sr = runtime.getNil();
                 si = m.callMethod(context"[]", RubyFixnum.one(runtime));
                 if (si.isNil()) si = runtime.newString();
                 IRubyObject t = m.callMethod(context"[]", RubyFixnum.two(runtime));
                 if (t.isNil()) t = runtime.newString(new ByteList(new byte[]{'1'}));
                 si.convertToString().cat(t.convertToString().getByteList());
                 re = m.callMethod(context"post_match");
                 po = false;
             }
         }
 
         if (m.isNil()) {
             m = RubyRegexp.newDummyRegexp(runtime..).callMethod(context"match"s);
             if (m.isNil()) return runtime.newArray(runtime.getNil(), recv);
            sr = m.callMethod(context"[]", RubyFixnum.one(runtime));
            if (m.callMethod(context"[]", RubyFixnum.two(runtime)).isNil()) {
                si = runtime.getNil();
            } else {
                si = m.callMethod(context"[]", RubyFixnum.three(runtime));
                IRubyObject t = m.callMethod(context"[]", RubyFixnum.four(runtime));
                if (t.isNil()) t = runtime.newString(new ByteList(new byte[]{'1'}));
                si.convertToString().cat(t.convertToString().getByteList());
            }
            re = m.callMethod(context"post_match");
            po = false;
        }