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 &le; val(r) &le; (2<sup>n</sup>-1).
548         * 0 &le; exp(r) &le; (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 &le; val(r) &le; (2<sup>n</sup>-1).
558         * 0 &le; exp(r) &le; (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 &le; val(r) &le; (2<sup>n</sup>-1).
569         * @param e such that 0 &le; exp(r) &le; (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 &le; val(r) &le; (2<sup>n</sup>-1).
579         * @param e such that 0 &le; exp(r) &le; (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    }