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