1 28 package org.jruby; 29 30 import java.math.BigDecimal ; 31 32 import org.jruby.runtime.Block; 33 import org.jruby.runtime.CallbackFactory; 34 import org.jruby.runtime.ObjectAllocator; 35 import org.jruby.runtime.builtin.IRubyObject; 36 37 40 public class RubyBigDecimal extends RubyNumeric { 41 private static final ObjectAllocator BIGDECIMAL_ALLOCATOR = new ObjectAllocator() { 42 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 43 return new RubyBigDecimal(runtime, klass); 44 } 45 }; 46 47 public static RubyClass createBigDecimal(Ruby runtime) { 48 RubyClass result = runtime.defineClass("BigDecimal",runtime.getClass("Numeric"), BIGDECIMAL_ALLOCATOR); 49 50 result.setConstant("ROUND_DOWN",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_DOWN)); 51 result.setConstant("SIGN_POSITIVE_INFINITE",RubyNumeric.int2fix(runtime,3)); 52 result.setConstant("EXCEPTION_OVERFLOW",RubyNumeric.int2fix(runtime,1)); 53 result.setConstant("SIGN_POSITIVE_ZERO",RubyNumeric.int2fix(runtime,1)); 54 result.setConstant("EXCEPTION_ALL",RubyNumeric.int2fix(runtime,255)); 55 result.setConstant("ROUND_CEILING",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_CEILING)); 56 result.setConstant("ROUND_UP",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_UP)); 57 result.setConstant("SIGN_NEGATIVE_FINITE",RubyNumeric.int2fix(runtime,-2)); 58 result.setConstant("EXCEPTION_UNDERFLOW",RubyNumeric.int2fix(runtime, 4)); 59 result.setConstant("SIGN_NaN",RubyNumeric.int2fix(runtime, 0)); 60 result.setConstant("BASE",RubyNumeric.int2fix(runtime,10000)); 61 result.setConstant("ROUND_HALF_DOWN",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_HALF_DOWN)); 62 result.setConstant("ROUND_MODE",RubyNumeric.int2fix(runtime,256)); 63 result.setConstant("SIGN_POSITIVE_FINITE",RubyNumeric.int2fix(runtime,2)); 64 result.setConstant("EXCEPTION_INFINITY",RubyNumeric.int2fix(runtime,1)); 65 result.setConstant("ROUND_HALF_EVEN",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_HALF_EVEN)); 66 result.setConstant("ROUND_HALF_UP",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_HALF_UP)); 67 result.setConstant("SIGN_NEGATIVE_INFINITE",RubyNumeric.int2fix(runtime,-3)); 68 result.setConstant("EXCEPTION_ZERODIVIDE",RubyNumeric.int2fix(runtime,1)); 69 result.setConstant("SIGN_NEGATIVE_ZERO",RubyNumeric.int2fix(runtime,-1)); 70 result.setConstant("EXCEPTION_NaN",RubyNumeric.int2fix(runtime,2)); 71 result.setConstant("ROUND_FLOOR",RubyNumeric.int2fix(runtime,BigDecimal.ROUND_FLOOR)); 72 73 CallbackFactory callbackFactory = runtime.callbackFactory(RubyBigDecimal.class); 74 75 runtime.getModule("Kernel").defineModuleFunction("BigDecimal",callbackFactory.getOptSingletonMethod("newBigDecimal")); 76 result.getMetaClass().defineMethod("new", callbackFactory.getOptSingletonMethod("newInstance")); 77 result.getMetaClass().defineFastMethod("ver", callbackFactory.getFastSingletonMethod("ver")); 78 result.getMetaClass().defineMethod("_load", callbackFactory.getSingletonMethod("_load",RubyKernel.IRUBY_OBJECT)); 79 result.getMetaClass().defineFastMethod("double_fig", callbackFactory.getFastSingletonMethod("double_fig")); 80 result.getMetaClass().defineFastMethod("limit", callbackFactory.getFastSingletonMethod("limit", RubyKernel.IRUBY_OBJECT)); 81 result.getMetaClass().defineFastMethod("mode", callbackFactory.getFastSingletonMethod("mode", RubyKernel.IRUBY_OBJECT, RubyKernel.IRUBY_OBJECT)); 82 83 result.defineMethod("initialize", callbackFactory.getOptMethod("initialize")); 84 result.defineFastMethod("%", callbackFactory.getFastMethod("mod",RubyKernel.IRUBY_OBJECT)); 85 result.defineFastMethod("modulo", callbackFactory.getFastMethod("mod",RubyKernel.IRUBY_OBJECT)); 86 result.defineFastMethod("*", callbackFactory.getFastOptMethod("mult")); 87 result.defineFastMethod("mult", callbackFactory.getFastOptMethod("mult")); 88 result.defineFastMethod("**", callbackFactory.getFastMethod("power",RubyKernel.IRUBY_OBJECT)); 89 result.defineFastMethod("power", callbackFactory.getFastMethod("power",RubyKernel.IRUBY_OBJECT)); 90 result.defineFastMethod("+", callbackFactory.getFastOptMethod("add")); 91 result.defineFastMethod("add", callbackFactory.getFastOptMethod("add")); 92 result.defineFastMethod("-", callbackFactory.getFastOptMethod("sub")); 93 result.defineFastMethod("sub", callbackFactory.getFastOptMethod("sub")); 94 result.defineFastMethod("/", callbackFactory.getFastOptMethod("div")); 95 result.defineFastMethod("div", callbackFactory.getFastOptMethod("div")); 96 result.defineFastMethod("quo", callbackFactory.getFastOptMethod("div")); 97 result.defineFastMethod("<=>", callbackFactory.getFastMethod("spaceship",RubyKernel.IRUBY_OBJECT)); 98 result.defineFastMethod("==", callbackFactory.getFastMethod("eql_p",RubyKernel.IRUBY_OBJECT)); 99 result.defineFastMethod("===", callbackFactory.getFastMethod("eql_p",RubyKernel.IRUBY_OBJECT)); 100 result.defineFastMethod("eql?", callbackFactory.getFastMethod("eql_p",RubyKernel.IRUBY_OBJECT)); 101 result.defineFastMethod("!=", callbackFactory.getFastMethod("ne",RubyKernel.IRUBY_OBJECT)); 102 result.defineFastMethod("<", callbackFactory.getFastMethod("lt",RubyKernel.IRUBY_OBJECT)); 103 result.defineFastMethod("<=", callbackFactory.getFastMethod("le",RubyKernel.IRUBY_OBJECT)); 104 result.defineFastMethod(">", callbackFactory.getFastMethod("gt",RubyKernel.IRUBY_OBJECT)); 105 result.defineFastMethod(">=", callbackFactory.getFastMethod("ge",RubyKernel.IRUBY_OBJECT)); 106 result.defineFastMethod("abs", callbackFactory.getFastMethod("abs")); 107 result.defineFastMethod("ceil", callbackFactory.getFastMethod("ceil",RubyKernel.IRUBY_OBJECT)); 108 result.defineFastMethod("coerce", callbackFactory.getFastMethod("coerce",RubyKernel.IRUBY_OBJECT)); 109 result.defineFastMethod("divmod", callbackFactory.getFastMethod("divmod",RubyKernel.IRUBY_OBJECT)); 110 result.defineFastMethod("exponent", callbackFactory.getFastMethod("exponent")); 111 result.defineFastMethod("finite?", callbackFactory.getFastMethod("finite_p")); 112 result.defineFastMethod("fix", callbackFactory.getFastMethod("fix")); 113 result.defineFastMethod("floor", callbackFactory.getFastMethod("floor",RubyKernel.IRUBY_OBJECT)); 114 result.defineFastMethod("frac", callbackFactory.getFastMethod("frac")); 115 result.defineFastMethod("infinite?", callbackFactory.getFastMethod("infinite_p")); 116 result.defineFastMethod("inspect", callbackFactory.getFastMethod("inspect")); 117 result.defineFastMethod("nan?", callbackFactory.getFastMethod("nan_p")); 118 result.defineFastMethod("nonzero?", callbackFactory.getFastMethod("nonzero_p")); 119 result.defineFastMethod("precs", callbackFactory.getFastMethod("precs")); 120 result.defineFastMethod("remainder", callbackFactory.getFastMethod("remainder",RubyKernel.IRUBY_OBJECT)); 121 result.defineFastMethod("round", callbackFactory.getFastOptMethod("round")); 122 result.defineFastMethod("sign", callbackFactory.getFastMethod("sign")); 123 result.defineFastMethod("split", callbackFactory.getFastMethod("split")); 124 result.defineFastMethod("sqrt", callbackFactory.getFastOptMethod("sqrt")); 125 result.defineFastMethod("to_f", callbackFactory.getFastMethod("to_f")); 126 result.defineFastMethod("to_i", callbackFactory.getFastMethod("to_i")); 127 result.defineFastMethod("to_int", callbackFactory.getFastMethod("to_int")); 128 result.defineFastMethod("to_s", callbackFactory.getFastOptMethod("to_s")); 129 result.defineFastMethod("truncate", callbackFactory.getFastOptMethod("truncate")); 130 result.defineFastMethod("zero?", callbackFactory.getFastMethod("zero_p")); 131 132 result.setClassVar("VpPrecLimit", RubyFixnum.zero(runtime)); 133 134 return result; 135 } 136 137 private BigDecimal value; 138 139 public RubyBigDecimal(Ruby runtime, RubyClass klass) { 140 super(runtime, klass); 141 } 142 143 public RubyBigDecimal(Ruby runtime, BigDecimal value) { 144 super(runtime, runtime.getClass("BigDecimal")); 145 this.value = value; 146 } 147 148 public static RubyBigDecimal newInstance(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 149 RubyClass klass = (RubyClass)recv; 150 151 RubyBigDecimal result = (RubyBigDecimal) klass.allocate(); 152 153 result.callInit(args, Block.NULL_BLOCK); 154 155 return result; 156 } 157 158 public static RubyBigDecimal newBigDecimal(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 159 return newInstance(recv.getRuntime().getClass("BigDecimal"), args, Block.NULL_BLOCK); 160 } 161 162 public static IRubyObject ver(IRubyObject recv) { 163 return recv.getRuntime().newString("1.0.1"); 164 } 165 166 public static IRubyObject _load(IRubyObject recv, IRubyObject p1, Block block) { 167 return recv.getRuntime().getNil(); 169 } 170 171 public static IRubyObject double_fig(IRubyObject recv) { 172 return recv.getRuntime().newFixnum(20); 173 } 174 175 public static IRubyObject limit(IRubyObject recv, IRubyObject arg1) { 176 RubyModule c = (RubyModule)recv; 177 IRubyObject nCur = c.getClassVar("VpPrecLimit"); 178 179 if (arg1.isNil()) { 180 return nCur; 181 } 182 183 c.setClassVar("VpPrecLimit",arg1); 184 185 return nCur; 186 } 187 188 public static IRubyObject mode(IRubyObject recv, IRubyObject mode, IRubyObject value) { 189 System.err.println("unimplemented: mode"); 190 return recv.getRuntime().getNil(); 192 } 193 194 private RubyBigDecimal getVpValue(IRubyObject v, boolean must) { 195 if(v instanceof RubyBigDecimal) { 196 return (RubyBigDecimal)v; 197 } else if(v instanceof RubyFixnum || v instanceof RubyBignum) { 198 String s = v.toString(); 199 return newInstance(getRuntime().getClass("BigDecimal"),new IRubyObject[]{getRuntime().newString(s)}, Block.NULL_BLOCK); 200 } 201 if(must) { 202 throw getRuntime().newTypeError(trueFalseNil(v.getMetaClass().getName() + " can't be coerced into BigDecimal")); 203 } 204 return null; 205 } 206 207 public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { 208 String ss = args[0].convertToString().toString(); 209 210 try { 211 this.value = new BigDecimal (ss); 212 } catch(NumberFormatException e) { 213 this.value = new BigDecimal ("0"); 214 } 215 216 return this; 217 } 218 219 private RubyBigDecimal setResult() { 220 return setResult(0); 221 } 222 223 private RubyBigDecimal setResult(int scale) { 224 int prec = RubyFixnum.fix2int(getRuntime().getClass("BigDecimal").getClassVar("VpPrecLimit")); 225 int prec2 = Math.max(scale,prec); 226 if(prec2 > 0 && this.value.scale() > (prec2-exp())) { 227 this.value = this.value.setScale(prec2-exp(),BigDecimal.ROUND_HALF_UP); 228 } 229 return this; 230 } 231 232 public IRubyObject mod(IRubyObject arg) { 233 System.err.println("unimplemented: mod"); 234 return this; 236 } 237 238 public IRubyObject mult(IRubyObject[] args) { 239 RubyBigDecimal val = getVpValue(args[0],false); 240 if(val == null) { 241 return callCoerced("*",args[0]); 242 } 243 244 return new RubyBigDecimal(getRuntime(),value.multiply(val.value)).setResult(); 245 } 246 247 public IRubyObject power(IRubyObject arg) { 248 BigDecimal val = value; 250 int times = RubyNumeric.fix2int(arg.convertToInteger()); 251 for(int i=0;i<times;i++) { 252 val = val.multiply(val); 253 } 254 return new RubyBigDecimal(getRuntime(),val).setResult(); 255 } 256 257 public IRubyObject add(IRubyObject[] args) { 258 RubyBigDecimal val = getVpValue(args[0],false); 259 if(val == null) { 260 return callCoerced("+",args[0]); 261 } 262 return new RubyBigDecimal(getRuntime(),value.add(val.value)).setResult(); 263 } 264 265 public IRubyObject sub(IRubyObject[] args) { 266 RubyBigDecimal val = getVpValue(args[0],false); 267 if(val == null) { 268 return callCoerced("-",args[0]); 269 } 270 return new RubyBigDecimal(getRuntime(),value.subtract(val.value)).setResult(); 271 } 272 273 public IRubyObject div(IRubyObject[] args) { 274 int scale = 0; 275 if(checkArgumentCount(args,1,2) == 2) { 276 scale = RubyNumeric.fix2int(args[1]); 277 } 278 279 RubyBigDecimal val = getVpValue(args[0],false); 280 if(val == null) { 281 return callCoerced("/",args[0]); 282 } 283 284 if(scale == 0) { 285 return new RubyBigDecimal(getRuntime(),value.divide(val.value,200,BigDecimal.ROUND_HALF_UP)).setResult(); 286 } else { 287 return new RubyBigDecimal(getRuntime(),value.divide(val.value,200,BigDecimal.ROUND_HALF_UP)).setResult(scale); 288 } 289 } 290 291 private IRubyObject cmp(IRubyObject r, char op) { 292 int e = 0; 293 RubyBigDecimal rb = getVpValue(r,false); 294 if(rb == null) { 295 e = RubyNumeric.fix2int(callCoerced("<=>",rb)); 296 } else { 297 e = value.compareTo(rb.value); 298 } 299 switch(op) { 300 case '*': return getRuntime().newFixnum(e); 301 case '=': return (e==0)?getRuntime().getTrue():getRuntime().getFalse(); 302 case '!': return (e!=0)?getRuntime().getTrue():getRuntime().getFalse(); 303 case 'G': return (e>=0)?getRuntime().getTrue():getRuntime().getFalse(); 304 case '>': return (e> 0)?getRuntime().getTrue():getRuntime().getFalse(); 305 case 'L': return (e<=0)?getRuntime().getTrue():getRuntime().getFalse(); 306 case '<': return (e< 0)?getRuntime().getTrue():getRuntime().getFalse(); 307 } 308 return getRuntime().getNil(); 309 } 310 311 public IRubyObject spaceship(IRubyObject arg) { 312 return cmp(arg,'*'); 313 } 314 315 public IRubyObject eql_p(IRubyObject arg) { 316 return cmp(arg,'='); 317 } 318 319 public IRubyObject ne(IRubyObject arg) { 320 return cmp(arg,'!'); 321 } 322 323 public IRubyObject lt(IRubyObject arg) { 324 return cmp(arg,'<'); 325 } 326 327 public IRubyObject le(IRubyObject arg) { 328 return cmp(arg,'L'); 329 } 330 331 public IRubyObject gt(IRubyObject arg) { 332 return cmp(arg,'>'); 333 } 334 335 public IRubyObject ge(IRubyObject arg) { 336 return cmp(arg,'G'); 337 } 338 339 public IRubyObject abs() { 340 return new RubyBigDecimal(getRuntime(),value.abs()).setResult(); 341 } 342 343 public IRubyObject ceil(IRubyObject arg) { 344 System.err.println("unimplemented: ceil"); 345 return this; 347 } 348 349 public IRubyObject coerce(IRubyObject other) { 350 IRubyObject obj; 351 if(other instanceof RubyFloat) { 352 obj = getRuntime().newArray(other,to_f()); 353 } else { 354 obj = getRuntime().newArray(getVpValue(other, true),this); 355 } 356 return obj; 357 } 358 359 public double getDoubleValue() { return value.doubleValue(); } 360 public long getLongValue() { return value.longValue(); } 361 362 public RubyNumeric multiplyWith(RubyInteger value) { 363 return (RubyNumeric)mult(new IRubyObject[]{value}); 364 } 365 366 public RubyNumeric multiplyWith(RubyFloat value) { 367 return (RubyNumeric)mult(new IRubyObject[]{value}); 368 } 369 370 public RubyNumeric multiplyWith(RubyBignum value) { 371 return (RubyNumeric)mult(new IRubyObject[]{value}); 372 } 373 374 public IRubyObject divmod(IRubyObject arg) { 375 System.err.println("unimplemented: divmod"); 376 return getRuntime().getNil(); 378 } 379 380 public IRubyObject exponent() { 381 return getRuntime().newFixnum(exp()); 382 } 383 384 private int exp() { 385 return value.abs().unscaledValue().toString().length() - value.abs().scale(); 386 } 387 388 public IRubyObject finite_p() { 389 System.err.println("unimplemented: finite?"); 390 return getRuntime().getTrue(); 392 } 393 394 public IRubyObject fix() { 395 System.err.println("unimplemented: fix"); 396 return this; 398 } 399 400 public IRubyObject floor(IRubyObject arg) { 401 System.err.println("unimplemented: floor"); 402 return this; 404 } 405 406 public IRubyObject frac() { 407 System.err.println("unimplemented: frac"); 408 return this; 410 } 411 412 public IRubyObject infinite_p() { 413 System.err.println("unimplemented: infinite?"); 414 return getRuntime().getFalse(); 416 } 417 418 public IRubyObject inspect() { 419 StringBuffer val = new StringBuffer ("#<BigDecimal:").append(Integer.toHexString(System.identityHashCode(this))).append(","); 420 val.append("'").append(this.callMethod(getRuntime().getCurrentContext(), "to_s")).append("'").append(","); 421 int len = value.abs().unscaledValue().toString().length(); 422 int pow = len/4; 423 val.append(len).append("(").append((pow+1)*4).append(")").append(">"); 424 return getRuntime().newString(val.toString()); 425 } 426 427 public IRubyObject nan_p() { 428 System.err.println("unimplemented: nan?"); 429 return getRuntime().getFalse(); 431 } 432 433 public IRubyObject nonzero_p() { 434 return value.signum() != 0 ? getRuntime().getTrue() : getRuntime().getFalse(); 435 } 436 437 public IRubyObject precs() { 438 System.err.println("unimplemented: precs"); 439 return getRuntime().getNil(); 441 } 442 443 public IRubyObject remainder(IRubyObject arg) { 444 System.err.println("unimplemented: remainder"); 445 return this; 447 } 448 449 public IRubyObject round(IRubyObject[] args) { 450 System.err.println("unimplemented: round"); 451 return this; 453 } 454 455 public IRubyObject sign() { 456 System.err.println("unimplemented: sign"); 457 return getRuntime().newFixnum(value.signum()); 459 } 460 461 public IRubyObject split() { 462 System.err.println("unimplemented: split"); 463 return getRuntime().getNil(); 465 } 466 467 public IRubyObject sqrt(IRubyObject[] args) { 468 System.err.println("unimplemented: sqrt"); 469 return new RubyBigDecimal(getRuntime(),new BigDecimal (Math.sqrt(value.doubleValue()))).setResult(); 471 } 472 473 public IRubyObject to_f() { 474 return RubyFloat.newFloat(getRuntime(),value.doubleValue()); 475 } 476 477 public IRubyObject to_i() { 478 return RubyNumeric.int2fix(getRuntime(),value.longValue()); 479 } 480 481 public IRubyObject to_int() { 482 return RubyNumeric.int2fix(getRuntime(),value.longValue()); 484 } 485 486 private String removeTrailingZeroes(String in) { 487 while(in.length() > 0 && in.charAt(in.length()-1)=='0') { 488 in = in.substring(0,in.length()-1); 489 } 490 return in; 491 } 492 493 public IRubyObject to_s(IRubyObject[] args) { 494 boolean engineering = true; 495 boolean pos_sign = false; 496 boolean pos_space = false; 497 int groups = 0; 498 499 if(args.length != 0 && !args[0].isNil()) { 500 String format = args[0].toString(); 501 int start = 0; 502 int end = format.length(); 503 if(format.length() > 0 && format.charAt(0) == '+') { 504 pos_sign = true; 505 start++; 506 } else if(format.length() > 0 && format.charAt(0) == ' ') { 507 pos_sign = true; 508 pos_space = true; 509 start++; 510 } 511 if(format.length() > 0 && format.charAt(format.length()-1) == 'F') { 512 engineering = false; 513 end--; 514 } else if(format.length() > 0 && format.charAt(format.length()-1) == 'E') { 515 engineering = true; 516 end--; 517 } 518 String nums = format.substring(start,end); 519 if(nums.length()>0) { 520 groups = Integer.parseInt(nums); 521 } 522 } 523 524 String out = null; 525 if(engineering) { 526 BigDecimal abs = value.abs(); 527 String unscaled = abs.unscaledValue().toString(); 528 int exponent = exp(); 529 int signum = value.signum(); 530 StringBuffer build = new StringBuffer (); 531 build.append(signum == -1 ? "-" : (signum == 1 ? (pos_sign ? (pos_space ? " " : "+" ) : "") : "")); 532 build.append("0."); 533 if(0 == groups) { 534 String s = removeTrailingZeroes(unscaled); 535 if("".equals(s)) { 536 build.append("0"); 537 } else { 538 build.append(s); 539 } 540 } else { 541 int index = 0; 542 String sep = ""; 543 while(index < unscaled.length()) { 544 int next = index+groups; 545 if(next > unscaled.length()) { 546 next = unscaled.length(); 547 } 548 build.append(sep).append(unscaled.substring(index,next)); 549 sep = " "; 550 index += groups; 551 } 552 } 553 build.append("E").append(exponent); 554 out = build.toString(); 555 } else { 556 BigDecimal abs = value.abs(); 557 String unscaled = abs.unscaledValue().toString(); 558 int ix = abs.toString().indexOf('.'); 559 String whole = unscaled; 560 String after = null; 561 if(ix != -1) { 562 whole = unscaled.substring(0,ix); 563 after = unscaled.substring(ix); 564 } 565 int signum = value.signum(); 566 StringBuffer build = new StringBuffer (); 567 build.append(signum == -1 ? "-" : (signum == 1 ? (pos_sign ? (pos_space ? " " : "+" ) : "") : "")); 568 if(0 == groups) { 569 build.append(whole); 570 if(null != after) { 571 build.append(".").append(after); 572 } 573 } else { 574 int index = 0; 575 String sep = ""; 576 while(index < whole.length()) { 577 int next = index+groups; 578 if(next > whole.length()) { 579 next = whole.length(); 580 } 581 build.append(sep).append(whole.substring(index,next)); 582 sep = " "; 583 index += groups; 584 } 585 if(null != after) { 586 System.out.println("AFTER: " + after); 587 build.append("."); 588 index = 0; 589 sep = ""; 590 while(index < after.length()) { 591 int next = index+groups; 592 if(next > after.length()) { 593 next = after.length(); 594 } 595 build.append(sep).append(after.substring(index,next)); 596 sep = " "; 597 index += groups; 598 } 599 } 600 } 601 out = build.toString(); 602 } 603 604 return getRuntime().newString(out); 605 } 606 607 public IRubyObject truncate(IRubyObject[] args) { 608 System.err.println("unimplemented: truncate"); 609 return this; 611 } 612 613 public IRubyObject zero_p() { 614 return value.signum() == 0 ? getRuntime().getTrue() : getRuntime().getFalse(); 615 } 616 } | Popular Tags |