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 }