001 /*
002 * $Id: BigDecimal.java 3354 2010-10-23 15:51:37Z kredel $
003 */
004
005 package edu.jas.arith;
006
007 import java.util.Random;
008 import java.math.MathContext;
009 import java.io.Reader;
010 import java.util.List;
011 import java.util.ArrayList;
012
013 //import edu.jas.structure.RingElem;
014 import edu.jas.kern.StringUtil;
015 import edu.jas.structure.GcdRingElem;
016 import edu.jas.structure.RingFactory;
017
018
019
020 /**
021 * BigDecimal class to make java.math.BigDecimal available with RingElem
022 * interface.
023 * Objects of this class are immutable.
024 * Experimental, use with care, compareTo is hacked.
025 * @author Heinz Kredel
026 * @see java.math.BigDecimal
027 */
028
029 public final class BigDecimal implements GcdRingElem<BigDecimal>,
030 RingFactory<BigDecimal> {
031
032 /** The data structure.
033 */
034 public final java.math.BigDecimal val;
035
036
037 private final static Random random = new Random();
038
039
040 // should go to factory:
041 public static final int DEFAULT_PRECISION = 50;
042 public static final MathContext DEFAULT_CONTEXT = new MathContext(DEFAULT_PRECISION);
043 public final MathContext context;
044
045
046 /** The constant 0.
047 */
048 public final static BigDecimal ZERO
049 = new BigDecimal( java.math.BigDecimal.ZERO );
050
051
052 /** The constant 1.
053 */
054 public final static BigDecimal ONE
055 = new BigDecimal( java.math.BigDecimal.ONE );
056
057
058 /**
059 * Constructor for BigDecimal from math.BigDecimal.
060 * @param a java.math.BigDecimal.
061 */
062 public BigDecimal(java.math.BigDecimal a) {
063 this(a,DEFAULT_CONTEXT);
064 }
065
066
067 /**
068 * Constructor for BigDecimal from math.BigDecimal.
069 * @param a java.math.BigDecimal.
070 * @param mc MathContext.
071 */
072 public BigDecimal(java.math.BigDecimal a, MathContext mc) {
073 val = a;
074 context = mc;
075 }
076
077
078 /**
079 * Constructor for BigDecimal from long.
080 * @param a long.
081 */
082 public BigDecimal(long a) {
083 this(a,DEFAULT_CONTEXT);
084 }
085
086
087 /**
088 * Constructor for BigDecimal from long and a context.
089 * @param a long.
090 * @param mc MathContext.
091 */
092 public BigDecimal(long a, MathContext mc) {
093 this( new java.math.BigDecimal( String.valueOf(a) ), mc );
094 }
095
096
097 /**
098 * Constructor for BigDecimal from double.
099 * @param a double.
100 */
101 public BigDecimal(double a) {
102 this(a,DEFAULT_CONTEXT);
103 }
104
105
106 /**
107 * Constructor for BigDecimal from double and a context.
108 * @param a double.
109 * @param mc MathContext.
110 */
111 public BigDecimal(double a, MathContext mc) {
112 this( new java.math.BigDecimal(a), mc );
113 }
114
115
116 /**
117 * Constructor for BigDecimal from java.math.BigInteger.
118 * @param a java.math.BigInteger.
119 */
120 public BigDecimal(java.math.BigInteger a) {
121 this(a,DEFAULT_CONTEXT);
122 }
123
124
125 /**
126 * Constructor for BigDecimal from java.math.BigInteger.
127 * @param a java.math.BigInteger.
128 * @param mc MathContext.
129 */
130 public BigDecimal(java.math.BigInteger a, MathContext mc) {
131 this(new java.math.BigDecimal(a),mc);
132 }
133
134
135 /**
136 * Constructor for BigDecimal from BigRational.
137 * @param a edu.jas.arith.BigRational.
138 */
139 public BigDecimal(BigRational a) {
140 this(a,DEFAULT_CONTEXT);
141 }
142
143
144 /**
145 * Constructor for BigDecimal from BigRational.
146 * @param a edu.jas.arith.BigRational.
147 * @param mc MathContext.
148 */
149 public BigDecimal(BigRational a, MathContext mc) {
150 this( (new java.math.BigDecimal(a.num)).divide(new java.math.BigDecimal(a.den),mc),mc);
151 }
152
153
154 /**
155 * Constructor for BigDecimal from String.
156 * @param s String.
157 */
158 public BigDecimal(String s) {
159 this(s,DEFAULT_CONTEXT);
160 }
161
162
163 /**
164 * Constructor for BigDecimal from String.
165 * @param s String.
166 * @param mc MathContext.
167 */
168 public BigDecimal(String s, MathContext mc) {
169 this( new java.math.BigDecimal( s.trim() ), mc );
170 }
171
172
173 /**
174 * Constructor for BigDecimal without parameters.
175 */
176 public BigDecimal() {
177 this( java.math.BigDecimal.ZERO, DEFAULT_CONTEXT);
178 }
179
180
181 /** Get the value.
182 * @return val java.math.BigDecimal.
183 public java.math.BigDecimal getVal() {
184 return val;
185 }
186 */
187
188
189 /**
190 * Get the corresponding element factory.
191 * @return factory for this Element.
192 * @see edu.jas.structure.Element#factory()
193 */
194 public BigDecimal factory() {
195 return this;
196 }
197
198
199 /**
200 * Get a list of the generating elements.
201 * @return list of generators for the algebraic structure.
202 * @see edu.jas.structure.ElemFactory#generators()
203 */
204 public List<BigDecimal> generators() {
205 List<BigDecimal> g = new ArrayList<BigDecimal>(1);
206 g.add( getONE() );
207 return g;
208 }
209
210
211 /**
212 * Is this structure finite or infinite.
213 * @return true if this structure is finite, else false.
214 * @see edu.jas.structure.ElemFactory#isFinite()
215 * <b>Note: </b> is actually finite but returns false.
216 */
217 public boolean isFinite() {
218 return false;
219 }
220
221
222 /** Clone this.
223 * @see java.lang.Object#clone()
224 */
225 @Override
226 public BigDecimal clone() {
227 return new BigDecimal( val, context );
228 }
229
230
231 /** Copy BigDecimal element c.
232 * @param c BigDecimal.
233 * @return a copy of c.
234 */
235 public BigDecimal copy(BigDecimal c) {
236 return new BigDecimal( c.val, c.context );
237 }
238
239
240 /** Get the zero element.
241 * @return 0.
242 */
243 public BigDecimal getZERO() {
244 return ZERO;
245 }
246
247
248 /** Get the one element.
249 * @return 1.
250 */
251 public BigDecimal getONE() {
252 return ONE;
253 }
254
255
256 /**
257 * Query if this ring is commutative.
258 * @return true.
259 */
260 public boolean isCommutative() {
261 return true;
262 }
263
264
265 /**
266 * Query if this ring is associative.
267 * Floating point number addition is not associative,
268 * but multiplication is.
269 * @return true.
270 */
271 public boolean isAssociative() {
272 return true;
273 }
274
275
276 /**
277 * Query if this ring is a field.
278 * @return true.
279 */
280 public boolean isField() {
281 return true;
282 }
283
284
285 /**
286 * Characteristic of this ring.
287 * @return characteristic of this ring.
288 */
289 public java.math.BigInteger characteristic() {
290 return java.math.BigInteger.ZERO;
291 }
292
293
294 /** Get a BigDecimal element from a math.BigDecimal.
295 * @param a math.BigDecimal.
296 * @return a as BigDecimal.
297 */
298 public BigDecimal fromInteger(java.math.BigInteger a) {
299 return new BigDecimal( new java.math.BigDecimal(a), context );
300 }
301
302
303 /** Get a BigDecimal element from a math.BigDecimal.
304 * @param a math.BigDecimal.
305 * @return a as BigDecimal.
306 */
307 public static BigDecimal valueOf(java.math.BigDecimal a) {
308 return new BigDecimal(a, DEFAULT_CONTEXT);
309 }
310
311
312 /** Get a BigDecimal element from long.
313 * @param a long.
314 * @return a as BigDecimal.
315 */
316 public BigDecimal fromInteger(long a) {
317 return new BigDecimal(a, context);
318 }
319
320
321 /** Get a BigDecimal element from long.
322 * @param a long.
323 * @return a as BigDecimal.
324 */
325 public static BigDecimal valueOf(long a) {
326 return new BigDecimal(a, DEFAULT_CONTEXT);
327 }
328
329
330 /** Is BigDecimal number zero.
331 * @return If this is 0 then true is returned, else false.
332 * @see edu.jas.structure.RingElem#isZERO()
333 */
334 public boolean isZERO() {
335 return val.compareTo( java.math.BigDecimal.ZERO ) == 0;
336 }
337
338
339 /** Is BigDecimal number one.
340 * @see edu.jas.structure.RingElem#isONE()
341 */
342 public boolean isONE() {
343 return val.compareTo( java.math.BigDecimal.ONE ) == 0;
344 }
345
346
347 /** Is BigDecimal number unit.
348 * @see edu.jas.structure.RingElem#isUnit()
349 */
350 public boolean isUnit() {
351 return ( ! isZERO() );
352 }
353
354 /** Get the String representation.
355 * @see java.lang.Object#toString()
356 */
357 @Override
358 public String toString() {
359 //return val.toString() + "(ulp=" + val.ulp() + ")";
360 return val.toString();
361 }
362
363
364 /** Get a scripting compatible string representation.
365 * @return script compatible representation for this Element.
366 * @see edu.jas.structure.Element#toScript()
367 */
368 //JAVA6only: @Override
369 public String toScript() {
370 // Python case
371 return toString();
372 }
373
374
375 /** Get a scripting compatible string representation of the factory.
376 * @return script compatible representation for this ElemFactory.
377 * @see edu.jas.structure.Element#toScriptFactory()
378 */
379 //JAVA6only: @Override
380 public String toScriptFactory() {
381 // Python case
382 return "DD()";
383 }
384
385
386 /** Compare to BigDecimal b.
387 * Experimental, is hacked.
388 * @param b BigDecimal.
389 * @return 0 if abs(this-b) < epsilon,
390 1 if this > b,
391 -1 if this < b.
392 */
393 //JAVA6only: @Override
394 public int compareTo(BigDecimal b) {
395 if ( false ) {
396 return val.compareTo( b.val );
397 }
398 java.math.BigDecimal s = val.subtract( b.val, context );
399 java.math.BigDecimal u1 = val.ulp();
400 java.math.BigDecimal u2 = b.val.ulp();
401 int u = Math.min( u1.scale(), u2.scale() );
402 //System.out.println("u = " + u + ", s = " + s);
403 java.math.BigDecimal eps;
404 if ( u <= 0 ) {
405 eps = u1.max( u2 );
406 } else {
407 eps = u1.min( u2 );
408 }
409 //eps = eps.movePointRight(1);
410 //System.out.println("ctx = " + context);
411 //System.out.println("eps = " + eps);
412 int t = s.abs().compareTo( eps );
413 if ( t < 1 ) {
414 return 0;
415 }
416 return s.signum();
417 }
418
419
420 /** Comparison with any other object.
421 * @see java.lang.Object#equals(java.lang.Object)
422 */
423 @Override
424 public boolean equals(Object b) {
425 if ( ! ( b instanceof BigDecimal ) ) {
426 return false;
427 }
428 BigDecimal bi = (BigDecimal)b;
429 return val.equals( bi.val );
430 }
431
432
433 /** Hash code for this BigDecimal.
434 * @see java.lang.Object#hashCode()
435 */
436 @Override
437 public int hashCode() {
438 return val.hashCode();
439 }
440
441
442 /** Absolute value of this.
443 * @see edu.jas.structure.RingElem#abs()
444 */
445 public BigDecimal abs() {
446 return new BigDecimal( val.abs(), context );
447 }
448
449
450 /* Negative value of this.
451 * @see edu.jas.structure.RingElem#negate()
452 */
453 public BigDecimal negate() {
454 return new BigDecimal( val.negate(), context );
455 }
456
457
458 /** signum.
459 * @see edu.jas.structure.RingElem#signum()
460 */
461 public int signum() {
462 return val.signum();
463 }
464
465
466 /** BigDecimal subtract.
467 * @param S BigDecimal.
468 * @return this-S.
469 */
470 public BigDecimal subtract(BigDecimal S) {
471 return new BigDecimal( val.subtract( S.val, context ) );
472 }
473
474
475 /** BigDecimal divide.
476 * @param S BigDecimal.
477 * @return this/S.
478 */
479 public BigDecimal divide(BigDecimal S) {
480 return new BigDecimal( val.divide( S.val, context ) );
481 }
482
483
484 /** Integer inverse. R is a non-zero integer.
485 S=1/R if defined else 0.
486 * @see edu.jas.structure.RingElem#inverse()
487 */
488 public BigDecimal inverse() {
489 return ONE.divide( this );
490 }
491
492
493 /** BigDecimal remainder.
494 * @param S BigDecimal.
495 * @return this - (this/S)*S.
496 */
497 public BigDecimal remainder(BigDecimal S) {
498 return new BigDecimal( val.remainder( S.val, context ) );
499 }
500
501
502 /** BigDecimal compute quotient and remainder.
503 * @param S BigDecimal.
504 * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S).
505 */
506 public BigDecimal[] quotientRemainder(BigDecimal S) {
507 BigDecimal[] qr = new BigDecimal[2];
508 java.math.BigDecimal[] C = val.divideAndRemainder( S.val, context );
509 qr[0] = new BigDecimal( C[0] );
510 qr[1] = new BigDecimal( C[1] );
511 return qr;
512 }
513
514
515 /** BigDecimal compute quotient and remainder.
516 * @param S BigDecimal.
517 * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S).
518 * @deprecated use quotientRemainder()
519 */
520 @Deprecated
521 public BigDecimal[] divideAndRemainder(BigDecimal S) {
522 return quotientRemainder(S);
523 }
524
525
526 /** BigDecimal greatest common divisor.
527 * @param S BigDecimal.
528 * @return gcd(this,S).
529 */
530 public BigDecimal gcd(BigDecimal S) {
531 throw new UnsupportedOperationException("BigDecimal.gcd() not implemented");
532 //return new BigDecimal( val.gcd( S.val ) );
533 }
534
535
536 /**
537 * BigDecimal extended greatest common divisor.
538 * @param S BigDecimal.
539 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
540 */
541 public BigDecimal[] egcd(BigDecimal S) {
542 throw new UnsupportedOperationException("BigDecimal.egcd() not implemented");
543 }
544
545
546 /** BigDecimal random.
547 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1).
548 * 0 ≤ exp(r) ≤ (100-1).
549 * @return r, a random BigDecimal.
550 */
551 public BigDecimal random(int n) {
552 return random(n,random);
553 }
554
555
556 /** BigDecimal random.
557 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1).
558 * 0 ≤ exp(r) ≤ (100-1).
559 * @param rnd is a source for random bits.
560 * @return r, a random BigDecimal.
561 */
562 public BigDecimal random(int n, Random rnd) {
563 return random(n,100,rnd);
564 }
565
566
567 /** BigDecimal random.
568 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1).
569 * @param e such that 0 ≤ exp(r) ≤ (e-1).
570 * @return r, a random BigDecimal.
571 */
572 public BigDecimal random(int n, int e) {
573 return random(n,e,random);
574 }
575
576
577 /** BigDecimal random.
578 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1).
579 * @param e such that 0 ≤ exp(r) ≤ (e-1).
580 * @param rnd is a source for random bits.
581 * @return r, a random BigDecimal.
582 */
583 public BigDecimal random(int n, int e, Random rnd) {
584 java.math.BigInteger r = new java.math.BigInteger( n, rnd );
585 if ( rnd.nextBoolean() ) {
586 r = r.negate();
587 }
588 int scale = rnd.nextInt(e);
589 if ( rnd.nextBoolean() ) {
590 scale = -scale;
591 }
592 java.math.BigDecimal d = new java.math.BigDecimal(r,scale,context);
593 return new BigDecimal( d, context );
594 }
595
596
597 /** BigDecimal multiply.
598 * @param S BigDecimal.
599 * @return this*S.
600 */
601 public BigDecimal multiply(BigDecimal S) {
602 return new BigDecimal( val.multiply( S.val, context ) );
603 }
604
605
606 /** BigDecimal summation.
607 * @param S BigDecimal.
608 * @return this+S.
609 */
610 public BigDecimal sum(BigDecimal S) {
611 return new BigDecimal( val.add( S.val, context ) );
612 }
613
614
615 /** BigDecimal parse from String.
616 * @param s String.
617 * @return Biginteger from s.
618 */
619 public BigDecimal parse(String s) {
620 return new BigDecimal(s, context);
621 }
622
623
624 /** BigDecimal parse from Reader.
625 * @param r Reader.
626 * @return next Biginteger from r.
627 */
628 public BigDecimal parse(Reader r) {
629 return parse( StringUtil.nextString(r) );
630 }
631
632 }