OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [math/] [BigDecimal.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* java.math.BigDecimal -- Arbitrary precision decimals.
2
   Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package java.math;
39
 
40
public class BigDecimal extends Number implements Comparable
41
{
42
  private BigInteger intVal;
43
  private int scale;
44
  private static final long serialVersionUID = 6108874887143696463L;
45
 
46
  /**
47
   * The constant zero as a BigDecimal with scale zero.
48
   * @since 1.5
49
   */
50
  public static final BigDecimal ZERO =
51
    new BigDecimal (BigInteger.valueOf (0), 0);
52
 
53
  /**
54
   * The constant one as a BigDecimal with scale zero.
55
   * @since 1.5
56
   */
57
  public static final BigDecimal ONE =
58
    new BigDecimal (BigInteger.valueOf (1), 0);
59
 
60
  /**
61
   * The constant ten as a BigDecimal with scale zero.
62
   * @since 1.5
63
   */
64
  public static final BigDecimal TEN =
65
    new BigDecimal (BigInteger.valueOf (10), 0);
66
 
67
  public static final int ROUND_UP = 0;
68
  public static final int ROUND_DOWN = 1;
69
  public static final int ROUND_CEILING = 2;
70
  public static final int ROUND_FLOOR = 3;
71
  public static final int ROUND_HALF_UP = 4;
72
  public static final int ROUND_HALF_DOWN = 5;
73
  public static final int ROUND_HALF_EVEN = 6;
74
  public static final int ROUND_UNNECESSARY = 7;
75
 
76
  public BigDecimal (BigInteger num)
77
  {
78
    this (num, 0);
79
  }
80
 
81
  public BigDecimal (BigInteger num, int scale) throws NumberFormatException
82
  {
83
    if (scale < 0)
84
      throw new NumberFormatException ("scale of " + scale + " is < 0");
85
    this.intVal = num;
86
    this.scale = scale;
87
  }
88
 
89
  public BigDecimal (double num) throws NumberFormatException
90
  {
91
    if (Double.isInfinite (num) || Double.isNaN (num))
92
      throw new NumberFormatException ("invalid argument: " + num);
93
    // Note we can't convert NUM to a String and then use the
94
    // String-based constructor.  The BigDecimal documentation makes
95
    // it clear that the two constructors work differently.
96
 
97
    final int mantissaBits = 52;
98
    final int exponentBits = 11;
99
    final long mantMask = (1L << mantissaBits) - 1;
100
    final long expMask = (1L << exponentBits) - 1;
101
 
102
    long bits = Double.doubleToLongBits (num);
103
    long mantissa = bits & mantMask;
104
    long exponent = (bits >>> mantissaBits) & expMask;
105
    boolean denormal = exponent == 0;
106
    // Correct the exponent for the bias.
107
    exponent -= denormal ? 1022 : 1023;
108
    // Now correct the exponent to account for the bits to the right
109
    // of the decimal.
110
    exponent -= mantissaBits;
111
    // Ordinary numbers have an implied leading `1' bit.
112
    if (! denormal)
113
      mantissa |= (1L << mantissaBits);
114
 
115
    // Shave off factors of 10.
116
    while (exponent < 0 && (mantissa & 1) == 0)
117
      {
118
        ++exponent;
119
        mantissa >>= 1;
120
      }
121
 
122
    intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa);
123
    if (exponent < 0)
124
      {
125
        // We have MANTISSA * 2 ^ (EXPONENT).
126
        // Since (1/2)^N == 5^N * 10^-N we can easily convert this
127
        // into a power of 10.
128
        scale = (int) (- exponent);
129
        BigInteger mult = BigInteger.valueOf (5).pow (scale);
130
        intVal = intVal.multiply (mult);
131
      }
132
    else
133
      {
134
        intVal = intVal.shiftLeft ((int) exponent);
135
        scale = 0;
136
      }
137
  }
138
 
139
  public BigDecimal (String num) throws NumberFormatException
140
  {
141
    int len = num.length();
142
    int start = 0, point = 0;
143
    int dot = -1;
144
    boolean negative = false;
145
    if (num.charAt(0) == '+')
146
      {
147
        ++start;
148
        ++point;
149
      }
150
    else if (num.charAt(0) == '-')
151
      {
152
        ++start;
153
        ++point;
154
        negative = true;
155
      }
156
 
157
    while (point < len)
158
      {
159
        char c = num.charAt (point);
160
        if (c == '.')
161
          {
162
            if (dot >= 0)
163
              throw new NumberFormatException ("multiple `.'s in number");
164
            dot = point;
165
          }
166
        else if (c == 'e' || c == 'E')
167
          break;
168
        else if (Character.digit (c, 10) < 0)
169
          throw new NumberFormatException ("unrecognized character: " + c);
170
        ++point;
171
      }
172
 
173
    String val;
174
    if (dot >= 0)
175
      {
176
        val = num.substring (start, dot) + num.substring (dot + 1, point);
177
        scale = point - 1 - dot;
178
      }
179
    else
180
      {
181
        val = num.substring (start, point);
182
        scale = 0;
183
      }
184
    if (val.length () == 0)
185
      throw new NumberFormatException ("no digits seen");
186
 
187
    if (negative)
188
      val = "-" + val;
189
    intVal = new BigInteger (val);
190
 
191
    // Now parse exponent.
192
    if (point < len)
193
      {
194
        point++;
195
        if (num.charAt(point) == '+')
196
          point++;
197
 
198
        if (point >= len )
199
          throw new NumberFormatException ("no exponent following e or E");
200
 
201
        try
202
          {
203
            int exp = Integer.parseInt (num.substring (point));
204
            exp -= scale;
205
            if (signum () == 0)
206
              scale = 0;
207
            else if (exp > 0)
208
              {
209
                intVal = intVal.multiply (BigInteger.valueOf (10).pow (exp));
210
                scale = 0;
211
              }
212
            else
213
              scale = - exp;
214
          }
215
        catch (NumberFormatException ex)
216
          {
217
            throw new NumberFormatException ("malformed exponent");
218
          }
219
      }
220
  }
221
 
222
  public static BigDecimal valueOf (long val)
223
  {
224
    return valueOf (val, 0);
225
  }
226
 
227
  public static BigDecimal valueOf (long val, int scale)
228
    throws NumberFormatException
229
  {
230
    if ((scale == 0) && ((int)val == val))
231
      switch ((int) val)
232
        {
233
        case 0:
234
          return ZERO;
235
        case 1:
236
          return ONE;
237
        }
238
 
239
    return new BigDecimal (BigInteger.valueOf (val), scale);
240
  }
241
 
242
  public BigDecimal add (BigDecimal val)
243
  {
244
    // For addition, need to line up decimals.  Note that the movePointRight
245
    // method cannot be used for this as it might return a BigDecimal with
246
    // scale == 0 instead of the scale we need.
247
    BigInteger op1 = intVal;
248
    BigInteger op2 = val.intVal;
249
    if (scale < val.scale)
250
      op1 = op1.multiply (BigInteger.valueOf (10).pow (val.scale - scale));
251
    else if (scale > val.scale)
252
      op2 = op2.multiply (BigInteger.valueOf (10).pow (scale - val.scale));
253
 
254
    return new BigDecimal (op1.add (op2), Math.max (scale, val.scale));
255
  }
256
 
257
  public BigDecimal subtract (BigDecimal val)
258
  {
259
    return this.add(val.negate());
260
  }
261
 
262
  public BigDecimal multiply (BigDecimal val)
263
  {
264
    return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale);
265
  }
266
 
267
  public BigDecimal divide (BigDecimal val, int roundingMode)
268
    throws ArithmeticException, IllegalArgumentException
269
  {
270
    return divide (val, scale, roundingMode);
271
  }
272
 
273
  public BigDecimal divide(BigDecimal val, int newScale, int roundingMode)
274
    throws ArithmeticException, IllegalArgumentException
275
  {
276
    if (roundingMode < 0 || roundingMode > 7)
277
      throw
278
        new IllegalArgumentException("illegal rounding mode: " + roundingMode);
279
 
280
    if (newScale < 0)
281
      throw new ArithmeticException ("scale is negative: " + newScale);
282
 
283
    if (intVal.signum () == 0)   // handle special case of 0.0/0.0
284
      return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale);
285
 
286
    // Ensure that pow gets a non-negative value.
287
    BigInteger valIntVal = val.intVal;
288
    int power = newScale - (scale - val.scale);
289
    if (power < 0)
290
      {
291
        // Effectively increase the scale of val to avoid an
292
        // ArithmeticException for a negative power.
293
        valIntVal = valIntVal.multiply (BigInteger.valueOf (10).pow (-power));
294
        power = 0;
295
      }
296
 
297
    BigInteger dividend = intVal.multiply (BigInteger.valueOf (10).pow (power));
298
 
299
    BigInteger parts[] = dividend.divideAndRemainder (valIntVal);
300
 
301
    BigInteger unrounded = parts[0];
302
    if (parts[1].signum () == 0) // no remainder, no rounding necessary
303
      return new BigDecimal (unrounded, newScale);
304
 
305
    if (roundingMode == ROUND_UNNECESSARY)
306
      throw new ArithmeticException ("newScale is not large enough");
307
 
308
    int sign = intVal.signum () * valIntVal.signum ();
309
 
310
    if (roundingMode == ROUND_CEILING)
311
      roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN;
312
    else if (roundingMode == ROUND_FLOOR)
313
      roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN;
314
    else
315
      {
316
        // half is -1 if remainder*2 < positive intValue (*power), 0 if equal,
317
        // 1 if >. This implies that the remainder to round is less than,
318
        // equal to, or greater than half way to the next digit.
319
        BigInteger posRemainder
320
          = parts[1].signum () < 0 ? parts[1].negate() : parts[1];
321
        valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal;
322
        int half = posRemainder.shiftLeft(1).compareTo(valIntVal);
323
 
324
        switch(roundingMode)
325
          {
326
          case ROUND_HALF_UP:
327
            roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP;
328
            break;
329
          case ROUND_HALF_DOWN:
330
            roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN;
331
            break;
332
          case ROUND_HALF_EVEN:
333
            if (half < 0)
334
              roundingMode = ROUND_DOWN;
335
            else if (half > 0)
336
              roundingMode = ROUND_UP;
337
            else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP
338
              roundingMode = ROUND_UP;
339
            else                           // even, ROUND_HALF_DOWN
340
              roundingMode = ROUND_DOWN;
341
            break;
342
          }
343
      }
344
 
345
    if (roundingMode == ROUND_UP)
346
      unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1));
347
 
348
    // roundingMode == ROUND_DOWN
349
    return new BigDecimal (unrounded, newScale);
350
  }
351
 
352
  public int compareTo (BigDecimal val)
353
  {
354
    if (scale == val.scale)
355
      return intVal.compareTo (val.intVal);
356
 
357
    BigInteger thisParts[] =
358
      intVal.divideAndRemainder (BigInteger.valueOf (10).pow (scale));
359
    BigInteger valParts[] =
360
      val.intVal.divideAndRemainder (BigInteger.valueOf (10).pow (val.scale));
361
 
362
    int compare;
363
    if ((compare = thisParts[0].compareTo (valParts[0])) != 0)
364
      return compare;
365
 
366
    // quotients are the same, so compare remainders
367
 
368
    // Add some trailing zeros to the remainder with the smallest scale
369
    if (scale < val.scale)
370
      thisParts[1] = thisParts[1].multiply
371
                        (BigInteger.valueOf (10).pow (val.scale - scale));
372
    else if (scale > val.scale)
373
      valParts[1] = valParts[1].multiply
374
                        (BigInteger.valueOf (10).pow (scale - val.scale));
375
 
376
    // and compare them
377
    return thisParts[1].compareTo (valParts[1]);
378
  }
379
 
380
  public int compareTo (Object val)
381
  {
382
    return(compareTo((BigDecimal)val));
383
  }
384
 
385
  public boolean equals (Object o)
386
  {
387
    return (o instanceof BigDecimal
388
            && scale == ((BigDecimal) o).scale
389
            && compareTo ((BigDecimal) o) == 0);
390
  }
391
 
392
  public int hashCode()
393
  {
394
    return intValue() ^ scale;
395
  }
396
 
397
  public BigDecimal max (BigDecimal val)
398
  {
399
    switch (compareTo (val))
400
      {
401
      case 1:
402
        return this;
403
      default:
404
        return val;
405
      }
406
  }
407
 
408
  public BigDecimal min (BigDecimal val)
409
  {
410
    switch (compareTo (val))
411
      {
412
      case -1:
413
        return this;
414
      default:
415
        return val;
416
      }
417
  }
418
 
419
  public BigDecimal movePointLeft (int n)
420
  {
421
    return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n);
422
  }
423
 
424
  public BigDecimal movePointRight (int n)
425
  {
426
    if (n < 0)
427
      return movePointLeft (-n);
428
 
429
    if (scale >= n)
430
      return new BigDecimal (intVal, scale - n);
431
 
432
    return new BigDecimal (intVal.multiply
433
                           (BigInteger.valueOf (10).pow (n - scale)), 0);
434
  }
435
 
436
  public int signum ()
437
  {
438
    return intVal.signum ();
439
  }
440
 
441
  public int scale ()
442
  {
443
    return scale;
444
  }
445
 
446
  public BigInteger unscaledValue()
447
  {
448
    return intVal;
449
  }
450
 
451
  public BigDecimal abs ()
452
  {
453
    return new BigDecimal (intVal.abs (), scale);
454
  }
455
 
456
  public BigDecimal negate ()
457
  {
458
    return new BigDecimal (intVal.negate (), scale);
459
  }
460
 
461
  public String toString ()
462
  {
463
    String bigStr = intVal.toString();
464
    if (scale == 0)
465
      return bigStr;
466
 
467
    boolean negative = (bigStr.charAt(0) == '-');
468
 
469
    int point = bigStr.length() - scale - (negative ? 1 : 0);
470
 
471
    StringBuffer sb = new StringBuffer(bigStr.length() + 2 +
472
                                       (point <= 0 ? (-point + 1) : 0));
473
    if (point <= 0)
474
      {
475
        if (negative)
476
          sb.append('-');
477
        sb.append('0').append('.');
478
        while (point < 0)
479
          {
480
            sb.append('0');
481
            point++;
482
          }
483
        sb.append(bigStr.substring(negative ? 1 : 0));
484
      }
485
    else
486
      {
487
        sb.append(bigStr);
488
        sb.insert(point + (negative ? 1 : 0), '.');
489
      }
490
    return sb.toString();
491
  }
492
 
493
  public BigInteger toBigInteger ()
494
  {
495
    return scale == 0 ? intVal :
496
      intVal.divide (BigInteger.valueOf (10).pow (scale));
497
  }
498
 
499
  public int intValue ()
500
  {
501
    return toBigInteger ().intValue ();
502
  }
503
 
504
  public long longValue ()
505
  {
506
    return toBigInteger().longValue();
507
  }
508
 
509
  public float floatValue()
510
  {
511
    return Float.valueOf(toString()).floatValue();
512
  }
513
 
514
  public double doubleValue()
515
  {
516
    return Double.valueOf(toString()).doubleValue();
517
  }
518
 
519
  public BigDecimal setScale (int scale) throws ArithmeticException
520
  {
521
    return setScale (scale, ROUND_UNNECESSARY);
522
  }
523
 
524
  public BigDecimal setScale (int scale, int roundingMode)
525
    throws ArithmeticException, IllegalArgumentException
526
  {
527
    return divide (ONE, scale, roundingMode);
528
  }
529
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.