KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > RubyBigDecimal


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2006 Ola Bini <ola@ologix.com>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28 package org.jruby;
29
30 import java.math.BigDecimal JavaDoc;
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 /**
38  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
39  */

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 JavaDoc value;
138
139     public RubyBigDecimal(Ruby runtime, RubyClass klass) {
140         super(runtime, klass);
141     }
142
143     public RubyBigDecimal(Ruby runtime, BigDecimal JavaDoc 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         // TODO: implement
168
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         // TODO: implement
191
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 JavaDoc 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 JavaDoc ss = args[0].convertToString().toString();
209         
210         try {
211         this.value = new BigDecimal JavaDoc(ss);
212         } catch(NumberFormatException JavaDoc e) {
213             this.value = new BigDecimal JavaDoc("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         // TODO: implement
235
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         // TODO: better implementation
249
BigDecimal JavaDoc 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         // TODO: implement correctly
346
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         // TODO: implement
377
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         // TODO: implement correctly
391
return getRuntime().getTrue();
392     }
393
394     public IRubyObject fix() {
395         System.err.println("unimplemented: fix");
396         // TODO: implement correctly
397
return this;
398     }
399
400     public IRubyObject floor(IRubyObject arg) {
401         System.err.println("unimplemented: floor");
402         // TODO: implement correctly
403
return this;
404     }
405  
406     public IRubyObject frac() {
407         System.err.println("unimplemented: frac");
408         // TODO: implement correctly
409
return this;
410     }
411
412     public IRubyObject infinite_p() {
413         System.err.println("unimplemented: infinite?");
414         // TODO: implement correctly
415
return getRuntime().getFalse();
416     }
417
418     public IRubyObject inspect() {
419         StringBuffer JavaDoc val = new StringBuffer JavaDoc("#<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         // TODO: implement correctly
430
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         // TODO: implement
440
return getRuntime().getNil();
441     }
442
443     public IRubyObject remainder(IRubyObject arg) {
444         System.err.println("unimplemented: remainder");
445         // TODO: implement
446
return this;
447     }
448
449     public IRubyObject round(IRubyObject[] args) {
450         System.err.println("unimplemented: round");
451         // TODO: implement
452
return this;
453     }
454
455     public IRubyObject sign() {
456         System.err.println("unimplemented: sign");
457         // TODO: implement correctly
458
return getRuntime().newFixnum(value.signum());
459     }
460
461     public IRubyObject split() {
462         System.err.println("unimplemented: split");
463         // TODO: implement
464
return getRuntime().getNil();
465     }
466
467     public IRubyObject sqrt(IRubyObject[] args) {
468         System.err.println("unimplemented: sqrt");
469         // TODO: implement correctly
470
return new RubyBigDecimal(getRuntime(),new BigDecimal JavaDoc(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         // TODO: implement to handle infinity and stuff
483
return RubyNumeric.int2fix(getRuntime(),value.longValue());
484     }
485
486     private String JavaDoc removeTrailingZeroes(String JavaDoc 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 JavaDoc 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 JavaDoc nums = format.substring(start,end);
519             if(nums.length()>0) {
520                 groups = Integer.parseInt(nums);
521             }
522         }
523
524         String JavaDoc out = null;
525         if(engineering) {
526             BigDecimal JavaDoc abs = value.abs();
527             String JavaDoc unscaled = abs.unscaledValue().toString();
528             int exponent = exp();
529             int signum = value.signum();
530             StringBuffer JavaDoc build = new StringBuffer JavaDoc();
531             build.append(signum == -1 ? "-" : (signum == 1 ? (pos_sign ? (pos_space ? " " : "+" ) : "") : ""));
532             build.append("0.");
533             if(0 == groups) {
534                 String JavaDoc 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 JavaDoc 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 JavaDoc abs = value.abs();
557             String JavaDoc unscaled = abs.unscaledValue().toString();
558             int ix = abs.toString().indexOf('.');
559             String JavaDoc whole = unscaled;
560             String JavaDoc 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 JavaDoc build = new StringBuffer JavaDoc();
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 JavaDoc 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         // TODO: implement
610
return this;
611     }
612
613     public IRubyObject zero_p() {
614         return value.signum() == 0 ? getRuntime().getTrue() : getRuntime().getFalse();
615     }
616 }// RubyBigdecimal
617
Popular Tags