Source Code Cross Referenced for BigDecimal.java in  » Apache-Harmony-Java-SE » java-package » java » math » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » java package » java.math 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package java.math;
0019:
0020:        import java.io.IOException;
0021:        import java.io.ObjectInputStream;
0022:        import java.io.ObjectOutputStream;
0023:        import java.io.Serializable;
0024:
0025:        import org.apache.harmony.math.internal.nls.Messages;
0026:
0027:        /**
0028:         * @author Intel Middleware Product Division
0029:         * @author Instituto Tecnologico de Cordoba
0030:         */
0031:        public class BigDecimal extends Number implements 
0032:                Comparable<BigDecimal>, Serializable {
0033:            /* Static Fields */
0034:
0035:            /** @ar.org.fitc.spec_ref */
0036:            public static final BigDecimal ZERO = new BigDecimal(0, 0);
0037:
0038:            /** @ar.org.fitc.spec_ref */
0039:            public static final BigDecimal ONE = new BigDecimal(1, 0);
0040:
0041:            /** @ar.org.fitc.spec_ref */
0042:            public static final BigDecimal TEN = new BigDecimal(10, 0);
0043:
0044:            /** @ar.org.fitc.spec_ref */
0045:            public static final int ROUND_UP = 0;
0046:
0047:            /** @ar.org.fitc.spec_ref */
0048:            public static final int ROUND_DOWN = 1;
0049:
0050:            /** @ar.org.fitc.spec_ref */
0051:            public static final int ROUND_CEILING = 2;
0052:
0053:            /** @ar.org.fitc.spec_ref */
0054:            public static final int ROUND_FLOOR = 3;
0055:
0056:            /** @ar.org.fitc.spec_ref */
0057:            public static final int ROUND_HALF_UP = 4;
0058:
0059:            /** @ar.org.fitc.spec_ref */
0060:            public static final int ROUND_HALF_DOWN = 5;
0061:
0062:            /** @ar.org.fitc.spec_ref */
0063:            public static final int ROUND_HALF_EVEN = 6;
0064:
0065:            /** @ar.org.fitc.spec_ref */
0066:            public static final int ROUND_UNNECESSARY = 7;
0067:
0068:            /* Private Fields */
0069:
0070:            /** @ar.org.fitc.spec_ref */
0071:            private static final long serialVersionUID = 6108874887143696463L;
0072:
0073:            /** The double closer to <code>Log10(2)</code>. */
0074:            private static final double LOG10_2 = 0.3010299956639812;
0075:
0076:            /** The <code>String</code> representation is cached. */
0077:            private transient String toStringImage = null;
0078:
0079:            private transient int hashCode = 0;
0080:
0081:            /**
0082:             * An array with powers of five that fit in the type <code>long</code>
0083:             * (<code>5^0,5^1,...,5^27</code>)
0084:             */
0085:            private static final BigInteger FIVE_POW[];
0086:
0087:            /**
0088:             * An array with powers of ten that fit in the type <code>long</code>
0089:             * (<code>10^0,10^1,...,10^18</code>)
0090:             */
0091:            private static final BigInteger TEN_POW[];
0092:
0093:            /**
0094:             * An array with powers of ten that fit in the type <code>long</code>
0095:             * (<code>10^0,10^1,...,10^18</code>)
0096:             */
0097:            private static final long[] LONG_TEN_POW = new long[] { 1L, 10L,
0098:                    100L, 1000L, 10000L, 100000L, 1000000L, 10000000L,
0099:                    100000000L, 1000000000L, 10000000000L, 100000000000L,
0100:                    1000000000000L, 10000000000000L, 100000000000000L,
0101:                    1000000000000000L, 10000000000000000L, 100000000000000000L,
0102:                    1000000000000000000L, };
0103:
0104:            private static final long[] LONG_FIVE_POW = new long[] { 1L, 5L,
0105:                    25L, 125L, 625L, 3125L, 15625L, 78125L, 390625L, 1953125L,
0106:                    9765625L, 48828125L, 244140625L, 1220703125L, 6103515625L,
0107:                    30517578125L, 152587890625L, 762939453125L, 3814697265625L,
0108:                    19073486328125L, 95367431640625L, 476837158203125L,
0109:                    2384185791015625L, 11920928955078125L, 59604644775390625L,
0110:                    298023223876953125L, 1490116119384765625L,
0111:                    7450580596923828125L, };
0112:
0113:            private static final int[] LONG_FIVE_POW_BIT_LENGTH = new int[LONG_FIVE_POW.length];
0114:            private static final int[] LONG_TEN_POW_BIT_LENGTH = new int[LONG_TEN_POW.length];
0115:
0116:            private static final int BI_SCALED_BY_ZERO_LENGTH = 11;
0117:            /**
0118:             * An array with the first <code>BigInteger</code> scaled by zero.
0119:             * (<code>[0,0],[1,0],...,[10,0]</code>)
0120:             */
0121:            private static final BigDecimal BI_SCALED_BY_ZERO[] = new BigDecimal[BI_SCALED_BY_ZERO_LENGTH];
0122:
0123:            /**
0124:             * An array with the zero number scaled by the first positive scales.
0125:             * (<code>0*10^0, 0*10^1, ..., 0*10^10</code>)
0126:             */
0127:            private static final BigDecimal ZERO_SCALED_BY[] = new BigDecimal[11];
0128:
0129:            /** An array filled with characters <code>'0'</code>. */
0130:            private static final char[] CH_ZEROS = new char[100];
0131:
0132:            static {
0133:                // To fill all static arrays.
0134:                int i = 0;
0135:
0136:                for (; i < ZERO_SCALED_BY.length; i++) {
0137:                    BI_SCALED_BY_ZERO[i] = new BigDecimal(i, 0);
0138:                    ZERO_SCALED_BY[i] = new BigDecimal(0, i);
0139:                    CH_ZEROS[i] = '0';
0140:                }
0141:
0142:                for (; i < CH_ZEROS.length; i++) {
0143:                    CH_ZEROS[i] = '0';
0144:                }
0145:                for (int j = 0; j < LONG_FIVE_POW_BIT_LENGTH.length; j++) {
0146:                    LONG_FIVE_POW_BIT_LENGTH[j] = bitLength(LONG_FIVE_POW[j]);
0147:                }
0148:                for (int j = 0; j < LONG_TEN_POW_BIT_LENGTH.length; j++) {
0149:                    LONG_TEN_POW_BIT_LENGTH[j] = bitLength(LONG_TEN_POW[j]);
0150:                }
0151:
0152:                // Taking the references of useful powers.
0153:                TEN_POW = Multiplication.bigTenPows;
0154:                FIVE_POW = Multiplication.bigFivePows;
0155:            }
0156:
0157:            /**
0158:             * The arbitrary precision integer (unscaled value) in the internal
0159:             * representation of <code>BigDecimal</code>.
0160:             */
0161:            private BigInteger intVal;
0162:
0163:            private transient int bitLength;
0164:
0165:            private transient long smallValue;
0166:
0167:            /** 
0168:             * The 32-bit integer scale in the internal representation of <code>BigDecimal</code>. 
0169:             */
0170:            private int scale;
0171:
0172:            /**
0173:             * Represent the number of decimal digits in the unscaled value. This 
0174:             * precision is calculated the first time, and used in the following 
0175:             * calls of method <code>precision()</code>. Note that some call to 
0176:             * the private method <code>inplaceRound()</code> could update this field.
0177:             * @see #precision()
0178:             * @see #inplaceRound(MathContext)
0179:             */
0180:            private transient int precision = 0;
0181:
0182:            /* Constructors */
0183:
0184:            private BigDecimal(long smallValue, int scale) {
0185:                this .smallValue = smallValue;
0186:                this .scale = scale;
0187:                this .bitLength = bitLength(smallValue);
0188:            }
0189:
0190:            private BigDecimal(int smallValue, int scale) {
0191:                this .smallValue = smallValue;
0192:                this .scale = scale;
0193:                this .bitLength = bitLength(smallValue);
0194:            }
0195:
0196:            /** @ar.org.fitc.spec_ref */
0197:            public BigDecimal(char[] in, int offset, int len) {
0198:                int begin = offset; // first index to be copied
0199:                int last = offset + (len - 1); // last index to be copied
0200:                String scaleString = null; // buffer for scale
0201:                StringBuilder unscaledBuffer; // buffer for unscaled value
0202:                long newScale; // the new scale
0203:
0204:                if (in == null) {
0205:                    throw new NullPointerException();
0206:                }
0207:                if ((last >= in.length) || (offset < 0) || (len <= 0)
0208:                        || (last < 0)) {
0209:                    throw new NumberFormatException();
0210:                }
0211:                unscaledBuffer = new StringBuilder(len);
0212:                int bufLength = 0;
0213:                // To skip a possible '+' symbol
0214:                if ((offset <= last) && (in[offset] == '+')) {
0215:                    offset++;
0216:                    begin++;
0217:                }
0218:                int counter = 0;
0219:                boolean wasNonZero = false;
0220:                // Accumulating all digits until a possible decimal point
0221:                for (; (offset <= last) && (in[offset] != '.')
0222:                        && (in[offset] != 'e') && (in[offset] != 'E'); offset++) {
0223:                    if (!wasNonZero) {
0224:                        if (in[offset] == '0') {
0225:                            counter++;
0226:                        } else {
0227:                            wasNonZero = true;
0228:                        }
0229:                    }
0230:                    ;
0231:
0232:                }
0233:                unscaledBuffer.append(in, begin, offset - begin);
0234:                bufLength += offset - begin;
0235:                // A decimal point was found
0236:                if ((offset <= last) && (in[offset] == '.')) {
0237:                    offset++;
0238:                    // Accumulating all digits until a possible exponent
0239:                    begin = offset;
0240:                    for (; (offset <= last) && (in[offset] != 'e')
0241:                            && (in[offset] != 'E'); offset++) {
0242:                        if (!wasNonZero) {
0243:                            if (in[offset] == '0') {
0244:                                counter++;
0245:                            } else {
0246:                                wasNonZero = true;
0247:                            }
0248:                        }
0249:                        ;
0250:                    }
0251:                    scale = offset - begin;
0252:                    bufLength += scale;
0253:                    unscaledBuffer.append(in, begin, scale);
0254:                } else {
0255:                    scale = 0;
0256:                }
0257:                // An exponent was found
0258:                if ((offset <= last)
0259:                        && ((in[offset] == 'e') || (in[offset] == 'E'))) {
0260:                    offset++;
0261:                    // Checking for a possible sign of scale
0262:                    begin = offset;
0263:                    if ((offset <= last) && (in[offset] == '+')) {
0264:                        offset++;
0265:                        if ((offset <= last) && (in[offset] != '-')) {
0266:                            begin++;
0267:                        }
0268:                    }
0269:                    // Accumulating all remaining digits
0270:                    scaleString = String.valueOf(in, begin, last + 1 - begin);
0271:                    // Checking if the scale is defined            
0272:                    newScale = (long) scale - Integer.parseInt(scaleString);
0273:                    scale = (int) newScale;
0274:                    if (newScale != scale) {
0275:                        // math.02=Scale out of range.
0276:                        throw new NumberFormatException(Messages
0277:                                .getString("math.02")); //$NON-NLS-1$
0278:                    }
0279:                }
0280:                // Parsing the unscaled value
0281:                if (bufLength < 19) {
0282:                    smallValue = Long.parseLong(unscaledBuffer.toString());
0283:                    bitLength = bitLength(smallValue);
0284:                } else {
0285:                    setUnscaledValue(new BigInteger(unscaledBuffer.toString()));
0286:                }
0287:                precision = unscaledBuffer.length() - counter;
0288:                if (unscaledBuffer.charAt(0) == '-') {
0289:                    precision--;
0290:                }
0291:            }
0292:
0293:            /** @ar.org.fitc.spec_ref */
0294:            public BigDecimal(char[] in, int offset, int len, MathContext mc) {
0295:                this (in, offset, len);
0296:                inplaceRound(mc);
0297:            }
0298:
0299:            /** @ar.org.fitc.spec_ref */
0300:            public BigDecimal(char[] in) {
0301:                this (in, 0, in.length);
0302:            }
0303:
0304:            /** @ar.org.fitc.spec_ref */
0305:            public BigDecimal(char[] in, MathContext mc) {
0306:                this (in, 0, in.length);
0307:                inplaceRound(mc);
0308:            }
0309:
0310:            /** @ar.org.fitc.spec_ref */
0311:            public BigDecimal(String val) {
0312:                this (val.toCharArray(), 0, val.length());
0313:            }
0314:
0315:            /** @ar.org.fitc.spec_ref */
0316:            public BigDecimal(String val, MathContext mc) {
0317:                this (val.toCharArray(), 0, val.length());
0318:                inplaceRound(mc);
0319:            }
0320:
0321:            /** @ar.org.fitc.spec_ref */
0322:            public BigDecimal(double val) {
0323:                if (Double.isInfinite(val) || Double.isNaN(val)) {
0324:                    // math.03=Infinity or NaN
0325:                    throw new NumberFormatException(Messages
0326:                            .getString("math.03")); //$NON-NLS-1$
0327:                }
0328:                long bits = Double.doubleToLongBits(val); // IEEE-754
0329:                long mantisa;
0330:                int trailingZeros;
0331:                // Extracting the exponent, note that the bias is 1023
0332:                scale = 1075 - (int) ((bits >> 52) & 0x7FFL);
0333:                // Extracting the 52 bits of the mantisa.
0334:                mantisa = (scale == 1075) ? (bits & 0xFFFFFFFFFFFFFL) << 1
0335:                        : (bits & 0xFFFFFFFFFFFFFL) | 0x10000000000000L;
0336:                if (mantisa == 0) {
0337:                    scale = 0;
0338:                    precision = 1;
0339:                }
0340:                // To simplify all factors '2' in the mantisa 
0341:                if (scale > 0) {
0342:                    trailingZeros = Math.min(scale, Long
0343:                            .numberOfTrailingZeros(mantisa));
0344:                    mantisa >>>= trailingZeros;
0345:                    scale -= trailingZeros;
0346:                }
0347:                // Calculating the new unscaled value and the new scale
0348:                if ((bits >> 63) != 0) {
0349:                    mantisa = -mantisa;
0350:                }
0351:                int mantisaBits = bitLength(mantisa);
0352:                if (scale < 0) {
0353:                    bitLength = mantisaBits == 0 ? 0 : mantisaBits - scale;
0354:                    if (bitLength < 64) {
0355:                        smallValue = mantisa << (-scale);
0356:                    } else {
0357:                        intVal = BigInteger.valueOf(mantisa).shiftLeft(-scale);
0358:                    }
0359:                    scale = 0;
0360:                } else if (scale > 0) {
0361:                    // m * 2^e =  (m * 5^(-e)) * 10^e
0362:                    if (scale < LONG_FIVE_POW.length
0363:                            && mantisaBits + LONG_FIVE_POW_BIT_LENGTH[scale] < 64) {
0364:                        smallValue = mantisa * LONG_FIVE_POW[scale];
0365:                        bitLength = bitLength(smallValue);
0366:                    } else {
0367:                        setUnscaledValue(Multiplication.multiplyByFivePow(
0368:                                BigInteger.valueOf(mantisa), scale));
0369:                    }
0370:                } else { // scale == 0
0371:                    smallValue = mantisa;
0372:                    bitLength = mantisaBits;
0373:                }
0374:            }
0375:
0376:            /** @ar.org.fitc.spec_ref */
0377:            public BigDecimal(double val, MathContext mc) {
0378:                this (val);
0379:                inplaceRound(mc);
0380:            }
0381:
0382:            /** @ar.org.fitc.spec_ref */
0383:            public BigDecimal(BigInteger val) {
0384:                this (val, 0);
0385:            }
0386:
0387:            /** @ar.org.fitc.spec_ref */
0388:            public BigDecimal(BigInteger val, MathContext mc) {
0389:                this (val);
0390:                inplaceRound(mc);
0391:            }
0392:
0393:            /** @ar.org.fitc.spec_ref */
0394:            public BigDecimal(BigInteger unscaledVal, int scale) {
0395:                if (unscaledVal == null) {
0396:                    throw new NullPointerException();
0397:                }
0398:                this .scale = scale;
0399:                setUnscaledValue(unscaledVal);
0400:            }
0401:
0402:            /** @ar.org.fitc.spec_ref */
0403:            public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
0404:                this (unscaledVal, scale);
0405:                inplaceRound(mc);
0406:            }
0407:
0408:            /** @ar.org.fitc.spec_ref */
0409:            public BigDecimal(int val) {
0410:                this (val, 0);
0411:            }
0412:
0413:            /** @ar.org.fitc.spec_ref */
0414:            public BigDecimal(int val, MathContext mc) {
0415:                this (val, 0);
0416:                inplaceRound(mc);
0417:            }
0418:
0419:            /** @ar.org.fitc.spec_ref */
0420:            public BigDecimal(long val) {
0421:                this (val, 0);
0422:            }
0423:
0424:            /** @ar.org.fitc.spec_ref */
0425:            public BigDecimal(long val, MathContext mc) {
0426:                this (val);
0427:                inplaceRound(mc);
0428:            }
0429:
0430:            /* Public Methods */
0431:
0432:            /** @ar.org.fitc.spec_ref */
0433:            public static BigDecimal valueOf(long unscaledVal, int scale) {
0434:                if (scale == 0) {
0435:                    return valueOf(unscaledVal);
0436:                }
0437:                if ((unscaledVal == 0) && (scale >= 0)
0438:                        && (scale < ZERO_SCALED_BY.length)) {
0439:                    return ZERO_SCALED_BY[scale];
0440:                }
0441:                return new BigDecimal(unscaledVal, scale);
0442:            }
0443:
0444:            /** @ar.org.fitc.spec_ref */
0445:            public static BigDecimal valueOf(long unscaledVal) {
0446:                if ((unscaledVal >= 0)
0447:                        && (unscaledVal < BI_SCALED_BY_ZERO_LENGTH)) {
0448:                    return BI_SCALED_BY_ZERO[(int) unscaledVal];
0449:                }
0450:                return new BigDecimal(unscaledVal, 0);
0451:            }
0452:
0453:            /** @ar.org.fitc.spec_ref */
0454:            public static BigDecimal valueOf(double val) {
0455:                if (Double.isInfinite(val) || Double.isNaN(val)) {
0456:                    // math.03=Infinity or NaN
0457:                    throw new NumberFormatException(Messages
0458:                            .getString("math.03")); //$NON-NLS-1$
0459:                }
0460:                return new BigDecimal(Double.toString(val));
0461:            }
0462:
0463:            /** @ar.org.fitc.spec_ref */
0464:            public BigDecimal add(BigDecimal augend) {
0465:                int diffScale = this .scale - augend.scale;
0466:                // Fast return when some operand is zero
0467:                if (this .isZero()) {
0468:                    if (diffScale <= 0) {
0469:                        return augend;
0470:                    }
0471:                    if (augend.isZero()) {
0472:                        return this ;
0473:                    }
0474:                } else if (augend.isZero()) {
0475:                    if (diffScale >= 0) {
0476:                        return this ;
0477:                    }
0478:                }
0479:                // Let be:  this = [u1,s1]  and  augend = [u2,s2]
0480:                if (diffScale == 0) {
0481:                    // case s1 == s2: [u1 + u2 , s1]
0482:                    if (Math.max(this .bitLength, augend.bitLength) + 1 < 64) {
0483:                        return valueOf(this .smallValue + augend.smallValue,
0484:                                this .scale);
0485:                    }
0486:                    return new BigDecimal(this .getUnscaledValue().add(
0487:                            augend.getUnscaledValue()), this .scale);
0488:                } else if (diffScale > 0) {
0489:                    // case s1 > s2 : [(u1 + u2) * 10 ^ (s1 - s2) , s1]
0490:                    return addAndMult10(this , augend, diffScale);
0491:                } else {// case s2 > s1 : [(u2 + u1) * 10 ^ (s2 - s1) , s2]
0492:                    return addAndMult10(augend, this , -diffScale);
0493:                }
0494:            }
0495:
0496:            private static BigDecimal addAndMult10(BigDecimal this Value,
0497:                    BigDecimal augend, int diffScale) {
0498:                if (diffScale < LONG_TEN_POW.length
0499:                        && Math.max(this Value.bitLength, augend.bitLength
0500:                                + LONG_TEN_POW_BIT_LENGTH[diffScale]) + 1 < 64) {
0501:                    return valueOf(this Value.smallValue + augend.smallValue
0502:                            * LONG_TEN_POW[diffScale], this Value.scale);
0503:                }
0504:                return new BigDecimal(this Value.getUnscaledValue().add(
0505:                        Multiplication.multiplyByTenPow(augend
0506:                                .getUnscaledValue(), diffScale)),
0507:                        this Value.scale);
0508:            }
0509:
0510:            /** @ar.org.fitc.spec_ref */
0511:            public BigDecimal add(BigDecimal augend, MathContext mc) {
0512:                BigDecimal larger; // operand with the largest unscaled value
0513:                BigDecimal smaller; // operand with the smallest unscaled value
0514:                BigInteger tempBI;
0515:                long diffScale = (long) this .scale - augend.scale;
0516:                int largerSignum;
0517:                // Some operand is zero or the precision is infinity  
0518:                if ((augend.isZero()) || (this .isZero())
0519:                        || (mc.getPrecision() == 0)) {
0520:                    return add(augend).round(mc);
0521:                }
0522:                // Cases where there is room for optimizations
0523:                if (this .aproxPrecision() < diffScale - 1) {
0524:                    larger = augend;
0525:                    smaller = this ;
0526:                } else if (augend.aproxPrecision() < -diffScale - 1) {
0527:                    larger = this ;
0528:                    smaller = augend;
0529:                } else {// No optimization is done 
0530:                    return add(augend).round(mc);
0531:                }
0532:                if (mc.getPrecision() >= larger.aproxPrecision()) {
0533:                    // No optimization is done
0534:                    return add(augend).round(mc);
0535:                }
0536:                // Cases where it's unnecessary to add two numbers with very different scales 
0537:                largerSignum = larger.signum();
0538:                if (largerSignum == smaller.signum()) {
0539:                    tempBI = Multiplication.multiplyByPositiveInt(
0540:                            larger.getUnscaledValue(), 10).add(
0541:                            BigInteger.valueOf(largerSignum));
0542:                } else {
0543:                    tempBI = larger.getUnscaledValue().subtract(
0544:                            BigInteger.valueOf(largerSignum));
0545:                    tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10)
0546:                            .add(BigInteger.valueOf(largerSignum * 9));
0547:                }
0548:                // Rounding the improved adding 
0549:                larger = new BigDecimal(tempBI, larger.scale + 1);
0550:                return larger.round(mc);
0551:            }
0552:
0553:            /** @ar.org.fitc.spec_ref */
0554:            public BigDecimal subtract(BigDecimal subtrahend) {
0555:                int diffScale = this .scale - subtrahend.scale;
0556:                // Fast return when some operand is zero
0557:                if (this .isZero()) {
0558:                    if (diffScale <= 0) {
0559:                        return subtrahend.negate();
0560:                    }
0561:                    if (subtrahend.isZero()) {
0562:                        return this ;
0563:                    }
0564:                } else if (subtrahend.isZero()) {
0565:                    if (diffScale >= 0) {
0566:                        return this ;
0567:                    }
0568:                }
0569:                // Let be: this = [u1,s1] and subtrahend = [u2,s2] so:
0570:                if (diffScale == 0) {
0571:                    // case s1 = s2 : [u1 - u2 , s1]
0572:                    if (Math.max(this .bitLength, subtrahend.bitLength) + 1 < 64) {
0573:                        return valueOf(this .smallValue - subtrahend.smallValue,
0574:                                this .scale);
0575:                    }
0576:                    return new BigDecimal(this .getUnscaledValue().subtract(
0577:                            subtrahend.getUnscaledValue()), this .scale);
0578:                } else if (diffScale > 0) {
0579:                    // case s1 > s2 : [ u1 - u2 * 10 ^ (s1 - s2) , s1 ]
0580:                    if (diffScale < LONG_TEN_POW.length
0581:                            && Math.max(this .bitLength, subtrahend.bitLength
0582:                                    + LONG_TEN_POW_BIT_LENGTH[diffScale]) + 1 < 64) {
0583:                        return valueOf(this .smallValue - subtrahend.smallValue
0584:                                * LONG_TEN_POW[diffScale], this .scale);
0585:                    }
0586:                    return new BigDecimal(this .getUnscaledValue().subtract(
0587:                            Multiplication.multiplyByTenPow(subtrahend
0588:                                    .getUnscaledValue(), diffScale)),
0589:                            this .scale);
0590:                } else {// case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ]
0591:                    diffScale = -diffScale;
0592:                    if (diffScale < LONG_TEN_POW.length
0593:                            && Math.max(this .bitLength
0594:                                    + LONG_TEN_POW_BIT_LENGTH[diffScale],
0595:                                    subtrahend.bitLength) + 1 < 64) {
0596:                        return valueOf(this .smallValue
0597:                                * LONG_TEN_POW[diffScale]
0598:                                - subtrahend.smallValue, subtrahend.scale);
0599:                    }
0600:                    return new BigDecimal(Multiplication.multiplyByTenPow(
0601:                            this .getUnscaledValue(), diffScale).subtract(
0602:                            subtrahend.getUnscaledValue()), subtrahend.scale);
0603:                }
0604:            }
0605:
0606:            /** @ar.org.fitc.spec_ref */
0607:            public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
0608:                long diffScale = subtrahend.scale - (long) this .scale;
0609:                int this Signum;
0610:                BigDecimal leftOperand; // it will be only the left operand (this) 
0611:                BigInteger tempBI;
0612:                // Some operand is zero or the precision is infinity  
0613:                if ((subtrahend.isZero()) || (this .isZero())
0614:                        || (mc.getPrecision() == 0)) {
0615:                    return subtract(subtrahend).round(mc);
0616:                }
0617:                // Now:   this != 0   and   subtrahend != 0
0618:                if (subtrahend.aproxPrecision() < diffScale - 1) {
0619:                    // Cases where it is unnecessary to subtract two numbers with very different scales
0620:                    if (mc.getPrecision() < this .aproxPrecision()) {
0621:                        this Signum = this .signum();
0622:                        if (this Signum != subtrahend.signum()) {
0623:                            tempBI = Multiplication.multiplyByPositiveInt(
0624:                                    this .getUnscaledValue(), 10).add(
0625:                                    BigInteger.valueOf(this Signum));
0626:                        } else {
0627:                            tempBI = this .getUnscaledValue().subtract(
0628:                                    BigInteger.valueOf(this Signum));
0629:                            tempBI = Multiplication.multiplyByPositiveInt(
0630:                                    tempBI, 10).add(
0631:                                    BigInteger.valueOf(this Signum * 9));
0632:                        }
0633:                        // Rounding the improved subtracting
0634:                        leftOperand = new BigDecimal(tempBI, this .scale + 1);
0635:                        return leftOperand.round(mc);
0636:                    }
0637:                }
0638:                // No optimization is done
0639:                return subtract(subtrahend).round(mc);
0640:            }
0641:
0642:            /** @ar.org.fitc.spec_ref */
0643:            public BigDecimal multiply(BigDecimal multiplicand) {
0644:                long newScale = (long) this .scale + multiplicand.scale;
0645:
0646:                if ((this .isZero()) || (multiplicand.isZero())) {
0647:                    return zeroScaledBy(newScale);
0648:                }
0649:                /* Let be: this = [u1,s1] and multiplicand = [u2,s2] so:
0650:                 * this x multiplicand = [ s1 * s2 , s1 + s2 ] */
0651:                if (this .bitLength + multiplicand.bitLength < 64) {
0652:                    return valueOf(this .smallValue * multiplicand.smallValue,
0653:                            toIntScale(newScale));
0654:                }
0655:                return new BigDecimal(this .getUnscaledValue().multiply(
0656:                        multiplicand.getUnscaledValue()), toIntScale(newScale));
0657:            }
0658:
0659:            /** @ar.org.fitc.spec_ref */
0660:            public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
0661:                BigDecimal result = multiply(multiplicand);
0662:
0663:                result.inplaceRound(mc);
0664:                return result;
0665:            }
0666:
0667:            /** @ar.org.fitc.spec_ref */
0668:            public BigDecimal divide(BigDecimal divisor, int scale,
0669:                    int roundingMode) {
0670:                return divide(divisor, scale, RoundingMode
0671:                        .valueOf(roundingMode));
0672:            }
0673:
0674:            /** @ar.org.fitc.spec_ref */
0675:            public BigDecimal divide(BigDecimal divisor, int scale,
0676:                    RoundingMode roundingMode) {
0677:                // Let be: this = [u1,s1]  and  divisor = [u2,s2]
0678:                if (roundingMode == null) {
0679:                    throw new NullPointerException();
0680:                }
0681:                if (divisor.isZero()) {
0682:                    // math.04=Division by zero
0683:                    throw new ArithmeticException(Messages.getString("math.04")); //$NON-NLS-1$
0684:                }
0685:
0686:                long diffScale = ((long) this .scale - divisor.scale) - scale;
0687:                if (this .bitLength < 64 && divisor.bitLength < 64) {
0688:                    if (diffScale == 0) {
0689:                        return dividePrimitiveLongs(this .smallValue,
0690:                                divisor.smallValue, scale, roundingMode);
0691:                    } else if (diffScale > 0) {
0692:                        if (diffScale < LONG_TEN_POW.length
0693:                                && divisor.bitLength
0694:                                        + LONG_TEN_POW_BIT_LENGTH[(int) diffScale] < 64) {
0695:                            return dividePrimitiveLongs(this .smallValue,
0696:                                    divisor.smallValue
0697:                                            * LONG_TEN_POW[(int) diffScale],
0698:                                    scale, roundingMode);
0699:                        }
0700:                    } else { // diffScale < 0
0701:                        if (-diffScale < LONG_TEN_POW.length
0702:                                && this .bitLength
0703:                                        + LONG_TEN_POW_BIT_LENGTH[(int) -diffScale] < 64) {
0704:                            return dividePrimitiveLongs(this .smallValue
0705:                                    * LONG_TEN_POW[(int) -diffScale],
0706:                                    divisor.smallValue, scale, roundingMode);
0707:                        }
0708:
0709:                    }
0710:                }
0711:                BigInteger scaledDividend = this .getUnscaledValue();
0712:                BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of 'u2'
0713:
0714:                if (diffScale > 0) {
0715:                    // Multiply 'u2'  by:  10^((s1 - s2) - scale)
0716:                    scaledDivisor = Multiplication.multiplyByTenPow(
0717:                            scaledDivisor, (int) diffScale);
0718:                } else if (diffScale < 0) {
0719:                    // Multiply 'u1'  by:  10^(scale - (s1 - s2))
0720:                    scaledDividend = Multiplication.multiplyByTenPow(
0721:                            scaledDividend, (int) -diffScale);
0722:                }
0723:                return divideBigIntegers(scaledDividend, scaledDivisor, scale,
0724:                        roundingMode);
0725:            }
0726:
0727:            private static BigDecimal divideBigIntegers(
0728:                    BigInteger scaledDividend, BigInteger scaledDivisor,
0729:                    int scale, RoundingMode roundingMode) {
0730:
0731:                BigInteger[] quotAndRem = scaledDividend
0732:                        .divideAndRemainder(scaledDivisor); // quotient and remainder
0733:                // If after division there is a remainder...
0734:                BigInteger quotient = quotAndRem[0];
0735:                BigInteger remainder = quotAndRem[1];
0736:                if (remainder.signum() == 0) {
0737:                    return new BigDecimal(quotient, scale);
0738:                }
0739:                int sign = scaledDividend.signum() * scaledDivisor.signum();
0740:                int compRem; // 'compare to remainder'
0741:                if (scaledDivisor.bitLength() < 63) { // 63 in order to avoid out of long after <<1
0742:                    long rem = remainder.longValue();
0743:                    long divisor = scaledDivisor.longValue();
0744:                    compRem = longCompareTo(Math.abs(rem) << 1, Math
0745:                            .abs(divisor));
0746:                    // To look if there is a carry
0747:                    compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
0748:                            sign * (5 + compRem), roundingMode);
0749:
0750:                } else {
0751:                    // Checking if:  remainder * 2 >= scaledDivisor 
0752:                    compRem = remainder.abs().shiftLeft(1).compareTo(
0753:                            scaledDivisor.abs());
0754:                    compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
0755:                            sign * (5 + compRem), roundingMode);
0756:                }
0757:                if (compRem != 0) {
0758:                    if (quotient.bitLength() < 63) {
0759:                        return valueOf(quotient.longValue() + compRem, scale);
0760:                    }
0761:                    quotient = quotient.add(BigInteger.valueOf(compRem));
0762:                    return new BigDecimal(quotient, scale);
0763:                }
0764:                // Constructing the result with the appropriate unscaled value
0765:                return new BigDecimal(quotient, scale);
0766:            }
0767:
0768:            private static BigDecimal dividePrimitiveLongs(long scaledDividend,
0769:                    long scaledDivisor, int scale, RoundingMode roundingMode) {
0770:                long quotient = scaledDividend / scaledDivisor;
0771:                long remainder = scaledDividend % scaledDivisor;
0772:                int sign = Long.signum(scaledDividend)
0773:                        * Long.signum(scaledDivisor);
0774:                if (remainder != 0) {
0775:                    // Checking if:  remainder * 2 >= scaledDivisor
0776:                    int compRem; // 'compare to remainder'
0777:                    compRem = longCompareTo(Math.abs(remainder) << 1, Math
0778:                            .abs(scaledDivisor));
0779:                    // To look if there is a carry
0780:                    quotient += roundingBehavior(((int) quotient) & 1, sign
0781:                            * (5 + compRem), roundingMode);
0782:                }
0783:                // Constructing the result with the appropriate unscaled value
0784:                return valueOf(quotient, scale);
0785:            }
0786:
0787:            /** @ar.org.fitc.spec_ref */
0788:            public BigDecimal divide(BigDecimal divisor, int roundingMode) {
0789:                return divide(divisor, scale, RoundingMode
0790:                        .valueOf(roundingMode));
0791:            }
0792:
0793:            /** @ar.org.fitc.spec_ref */
0794:            public BigDecimal divide(BigDecimal divisor,
0795:                    RoundingMode roundingMode) {
0796:                return divide(divisor, scale, roundingMode);
0797:            }
0798:
0799:            /** @ar.org.fitc.spec_ref */
0800:            public BigDecimal divide(BigDecimal divisor) {
0801:                BigInteger p = this .getUnscaledValue();
0802:                BigInteger q = divisor.getUnscaledValue();
0803:                BigInteger gcd; // greatest common divisor between 'p' and 'q'
0804:                BigInteger quotAndRem[];
0805:                long diffScale = (long) scale - divisor.scale;
0806:                int newScale; // the new scale for final quotient
0807:                int k; // number of factors "2" in 'q'
0808:                int l = 0; // number of factors "5" in 'q'
0809:                int i = 1;
0810:                int lastPow = FIVE_POW.length - 1;
0811:
0812:                if (divisor.isZero()) {
0813:                    // math.04=Division by zero
0814:                    throw new ArithmeticException(Messages.getString("math.04")); //$NON-NLS-1$
0815:                }
0816:                if (p.signum() == 0) {
0817:                    return zeroScaledBy(diffScale);
0818:                }
0819:                // To divide both by the GCD
0820:                gcd = p.gcd(q);
0821:                p = p.divide(gcd);
0822:                q = q.divide(gcd);
0823:                // To simplify all "2" factors of q, dividing by 2^k
0824:                k = q.getLowestSetBit();
0825:                q = q.shiftRight(k);
0826:                // To simplify all "5" factors of q, dividing by 5^l
0827:                do {
0828:                    quotAndRem = q.divideAndRemainder(FIVE_POW[i]);
0829:                    if (quotAndRem[1].signum() == 0) {
0830:                        l += i;
0831:                        if (i < lastPow) {
0832:                            i++;
0833:                        }
0834:                        q = quotAndRem[0];
0835:                    } else {
0836:                        if (i == 1) {
0837:                            break;
0838:                        }
0839:                        i = 1;
0840:                    }
0841:                } while (true);
0842:                // If  abs(q) != 1  then the quotient is periodic
0843:                if (!q.abs().equals(BigInteger.ONE)) {
0844:                    // math.05=Non-terminating decimal expansion; no exact representable decimal result.
0845:                    throw new ArithmeticException(Messages.getString("math.05")); //$NON-NLS-1$
0846:                }
0847:                // The sign of the is fixed and the quotient will be saved in 'p'
0848:                if (q.signum() < 0) {
0849:                    p = p.negate();
0850:                }
0851:                // Checking if the new scale is out of range
0852:                newScale = toIntScale(diffScale + Math.max(k, l));
0853:                // k >= 0  and  l >= 0  implies that  k - l  is in the 32-bit range
0854:                i = k - l;
0855:
0856:                p = (i > 0) ? Multiplication.multiplyByFivePow(p, i) : p
0857:                        .shiftLeft(-i);
0858:                return new BigDecimal(p, newScale);
0859:            }
0860:
0861:            /** @ar.org.fitc.spec_ref */
0862:            public BigDecimal divide(BigDecimal divisor, MathContext mc) {
0863:                /* Calculating how many zeros must be append to 'dividend'
0864:                 * to obtain a  quotient with at least 'mc.precision()' digits */
0865:                long traillingZeros = mc.getPrecision() + 2L
0866:                        + divisor.aproxPrecision() - aproxPrecision();
0867:                long diffScale = (long) scale - divisor.scale;
0868:                long newScale = diffScale; // scale of the final quotient
0869:                int compRem; // to compare the remainder
0870:                int i = 1; // index   
0871:                int lastPow = TEN_POW.length - 1; // last power of ten
0872:                BigInteger integerQuot; // for temporal results
0873:                BigInteger quotAndRem[] = { getUnscaledValue() };
0874:                // In special cases it reduces the problem to call the dual method
0875:                if ((mc.getPrecision() == 0) || (this .isZero())
0876:                        || (divisor.isZero())) {
0877:                    return this .divide(divisor);
0878:                }
0879:                if (traillingZeros > 0) {
0880:                    // To append trailing zeros at end of dividend
0881:                    quotAndRem[0] = getUnscaledValue().multiply(
0882:                            Multiplication.powerOf10(traillingZeros));
0883:                    newScale += traillingZeros;
0884:                }
0885:                quotAndRem = quotAndRem[0].divideAndRemainder(divisor
0886:                        .getUnscaledValue());
0887:                integerQuot = quotAndRem[0];
0888:                // Calculating the exact quotient with at least 'mc.precision()' digits
0889:                if (quotAndRem[1].signum() != 0) {
0890:                    // Checking if:   2 * remainder >= divisor ?
0891:                    compRem = quotAndRem[1].shiftLeft(1).compareTo(
0892:                            divisor.getUnscaledValue());
0893:                    // quot := quot * 10 + r;     with 'r' in {-6,-5,-4, 0,+4,+5,+6}
0894:                    integerQuot = integerQuot.multiply(BigInteger.TEN).add(
0895:                            BigInteger.valueOf(quotAndRem[0].signum()
0896:                                    * (5 + compRem)));
0897:                    newScale++;
0898:                } else {
0899:                    // To strip trailing zeros until the preferred scale is reached
0900:                    while (!integerQuot.testBit(0)) {
0901:                        quotAndRem = integerQuot.divideAndRemainder(TEN_POW[i]);
0902:                        if ((quotAndRem[1].signum() == 0)
0903:                                && (newScale - i >= diffScale)) {
0904:                            newScale -= i;
0905:                            if (i < lastPow) {
0906:                                i++;
0907:                            }
0908:                            integerQuot = quotAndRem[0];
0909:                        } else {
0910:                            if (i == 1) {
0911:                                break;
0912:                            }
0913:                            i = 1;
0914:                        }
0915:                    }
0916:                }
0917:                // To perform rounding
0918:                return new BigDecimal(integerQuot, toIntScale(newScale), mc);
0919:            }
0920:
0921:            /** @ar.org.fitc.spec_ref */
0922:            public BigDecimal divideToIntegralValue(BigDecimal divisor) {
0923:                BigInteger integralValue; // the integer of result
0924:                BigInteger powerOfTen; // some power of ten
0925:                BigInteger quotAndRem[] = { getUnscaledValue() };
0926:                long newScale = (long) this .scale - divisor.scale;
0927:                long tempScale = 0;
0928:                int i = 1;
0929:                int lastPow = TEN_POW.length - 1;
0930:
0931:                if (divisor.isZero()) {
0932:                    // math.04=Division by zero
0933:                    throw new ArithmeticException(Messages.getString("math.04")); //$NON-NLS-1$
0934:                }
0935:                if ((divisor.aproxPrecision() + newScale > this 
0936:                        .aproxPrecision() + 1L)
0937:                        || (this .isZero())) {
0938:                    /* If the divisor's integer part is greater than this's integer part,
0939:                     * the result must be zero with the appropriate scale */
0940:                    integralValue = BigInteger.ZERO;
0941:                } else if (newScale == 0) {
0942:                    integralValue = getUnscaledValue().divide(
0943:                            divisor.getUnscaledValue());
0944:                } else if (newScale > 0) {
0945:                    powerOfTen = Multiplication.powerOf10(newScale);
0946:                    integralValue = getUnscaledValue().divide(
0947:                            divisor.getUnscaledValue().multiply(powerOfTen));
0948:                    integralValue = integralValue.multiply(powerOfTen);
0949:                } else {// (newScale < 0)
0950:                    powerOfTen = Multiplication.powerOf10(-newScale);
0951:                    integralValue = getUnscaledValue().multiply(powerOfTen)
0952:                            .divide(divisor.getUnscaledValue());
0953:                    // To strip trailing zeros approximating to the preferred scale
0954:                    while (!integralValue.testBit(0)) {
0955:                        quotAndRem = integralValue
0956:                                .divideAndRemainder(TEN_POW[i]);
0957:                        if ((quotAndRem[1].signum() == 0)
0958:                                && (tempScale - i >= newScale)) {
0959:                            tempScale -= i;
0960:                            if (i < lastPow) {
0961:                                i++;
0962:                            }
0963:                            integralValue = quotAndRem[0];
0964:                        } else {
0965:                            if (i == 1) {
0966:                                break;
0967:                            }
0968:                            i = 1;
0969:                        }
0970:                    }
0971:                    newScale = tempScale;
0972:                }
0973:                return ((integralValue.signum() == 0) ? zeroScaledBy(newScale)
0974:                        : new BigDecimal(integralValue, toIntScale(newScale)));
0975:            }
0976:
0977:            /** @ar.org.fitc.spec_ref */
0978:            public BigDecimal divideToIntegralValue(BigDecimal divisor,
0979:                    MathContext mc) {
0980:                int mcPrecision = mc.getPrecision();
0981:                int diffPrecision = this .precision() - divisor.precision();
0982:                int lastPow = TEN_POW.length - 1;
0983:                long diffScale = (long) this .scale - divisor.scale;
0984:                long newScale = diffScale;
0985:                long quotPrecision = diffPrecision - diffScale + 1;
0986:                BigInteger quotAndRem[] = new BigInteger[2];
0987:                // In special cases it call the dual method
0988:                if ((mcPrecision == 0) || (this .isZero()) || (divisor.isZero())) {
0989:                    return this .divideToIntegralValue(divisor);
0990:                }
0991:                // Let be:   this = [u1,s1]   and   divisor = [u2,s2]
0992:                if (quotPrecision <= 0) {
0993:                    quotAndRem[0] = BigInteger.ZERO;
0994:                } else if (diffScale == 0) {
0995:                    // CASE s1 == s2:  to calculate   u1 / u2 
0996:                    quotAndRem[0] = this .getUnscaledValue().divide(
0997:                            divisor.getUnscaledValue());
0998:                } else if (diffScale > 0) {
0999:                    // CASE s1 >= s2:  to calculate   u1 / (u2 * 10^(s1-s2)  
1000:                    quotAndRem[0] = this .getUnscaledValue().divide(
1001:                            divisor.getUnscaledValue().multiply(
1002:                                    Multiplication.powerOf10(diffScale)));
1003:                    // To chose  10^newScale  to get a quotient with at least 'mc.precision()' digits
1004:                    newScale = Math.min(diffScale, Math.max(mcPrecision
1005:                            - quotPrecision + 1, 0));
1006:                    // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
1007:                    quotAndRem[0] = quotAndRem[0].multiply(Multiplication
1008:                            .powerOf10(newScale));
1009:                } else {// CASE s2 > s1:   
1010:                    /* To calculate the minimum power of ten, such that the quotient 
1011:                     *   (u1 * 10^exp) / u2   has at least 'mc.precision()' digits. */
1012:                    long exp = Math.min(-diffScale, Math.max((long) mcPrecision
1013:                            - diffPrecision, 0));
1014:                    long compRemDiv;
1015:                    // Let be:   (u1 * 10^exp) / u2 = [q,r]  
1016:                    quotAndRem = this .getUnscaledValue().multiply(
1017:                            Multiplication.powerOf10(exp)).divideAndRemainder(
1018:                            divisor.getUnscaledValue());
1019:                    newScale += exp; // To fix the scale
1020:                    exp = -newScale; // The remaining power of ten
1021:                    // If after division there is a remainder...
1022:                    if ((quotAndRem[1].signum() != 0) && (exp > 0)) {
1023:                        // Log10(r) + ((s2 - s1) - exp) > mc.precision ?
1024:                        compRemDiv = (new BigDecimal(quotAndRem[1]))
1025:                                .precision()
1026:                                + exp - divisor.precision();
1027:                        if (compRemDiv == 0) {
1028:                            // To calculate:  (r * 10^exp2) / u2
1029:                            quotAndRem[1] = quotAndRem[1].multiply(
1030:                                    Multiplication.powerOf10(exp)).divide(
1031:                                    divisor.getUnscaledValue());
1032:                            compRemDiv = Math.abs(quotAndRem[1].signum());
1033:                        }
1034:                        if (compRemDiv > 0) {
1035:                            // The quotient won't fit in 'mc.precision()' digits
1036:                            // math.06=Division impossible
1037:                            throw new ArithmeticException(Messages
1038:                                    .getString("math.06")); //$NON-NLS-1$
1039:                        }
1040:                    }
1041:                }
1042:                // Fast return if the quotient is zero
1043:                if (quotAndRem[0].signum() == 0) {
1044:                    return zeroScaledBy(diffScale);
1045:                }
1046:                BigInteger strippedBI = quotAndRem[0];
1047:                BigDecimal integralValue = new BigDecimal(quotAndRem[0]);
1048:                long resultPrecision = integralValue.precision();
1049:                int i = 1;
1050:                // To strip trailing zeros until the specified precision is reached
1051:                while (!strippedBI.testBit(0)) {
1052:                    quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
1053:                    if ((quotAndRem[1].signum() == 0)
1054:                            && ((resultPrecision - i >= mcPrecision) || (newScale
1055:                                    - i >= diffScale))) {
1056:                        resultPrecision -= i;
1057:                        newScale -= i;
1058:                        if (i < lastPow) {
1059:                            i++;
1060:                        }
1061:                        strippedBI = quotAndRem[0];
1062:                    } else {
1063:                        if (i == 1) {
1064:                            break;
1065:                        }
1066:                        i = 1;
1067:                    }
1068:                }
1069:                // To check if the result fit in 'mc.precision()' digits
1070:                if (resultPrecision > mcPrecision) {
1071:                    // math.06=Division impossible
1072:                    throw new ArithmeticException(Messages.getString("math.06")); //$NON-NLS-1$
1073:                }
1074:                integralValue.scale = toIntScale(newScale);
1075:                integralValue.setUnscaledValue(strippedBI);
1076:                return integralValue;
1077:            }
1078:
1079:            /** @ar.org.fitc.spec_ref */
1080:            public BigDecimal remainder(BigDecimal divisor) {
1081:                return divideAndRemainder(divisor)[1];
1082:            }
1083:
1084:            /** @ar.org.fitc.spec_ref */
1085:            public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
1086:                return divideAndRemainder(divisor, mc)[1];
1087:            }
1088:
1089:            /** @ar.org.fitc.spec_ref */
1090:            public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
1091:                BigDecimal quotAndRem[] = new BigDecimal[2];
1092:
1093:                quotAndRem[0] = this .divideToIntegralValue(divisor);
1094:                quotAndRem[1] = this .subtract(quotAndRem[0].multiply(divisor));
1095:                return quotAndRem;
1096:            }
1097:
1098:            /** @ar.org.fitc.spec_ref */
1099:            public BigDecimal[] divideAndRemainder(BigDecimal divisor,
1100:                    MathContext mc) {
1101:                BigDecimal quotAndRem[] = new BigDecimal[2];
1102:
1103:                quotAndRem[0] = this .divideToIntegralValue(divisor, mc);
1104:                quotAndRem[1] = this .subtract(quotAndRem[0].multiply(divisor));
1105:                return quotAndRem;
1106:            }
1107:
1108:            /** @ar.org.fitc.spec_ref */
1109:            public BigDecimal pow(int n) {
1110:                if (n == 0) {
1111:                    return ONE;
1112:                }
1113:                if ((n < 0) || (n > 999999999)) {
1114:                    // math.07=Invalid Operation
1115:                    throw new ArithmeticException(Messages.getString("math.07")); //$NON-NLS-1$
1116:                }
1117:                long newScale = scale * (long) n;
1118:                // Let be: this = [u,s]   so:  this^n = [u^n, s*n]
1119:                return ((isZero()) ? zeroScaledBy(newScale) : new BigDecimal(
1120:                        getUnscaledValue().pow(n), toIntScale(newScale)));
1121:            }
1122:
1123:            /** @ar.org.fitc.spec_ref */
1124:            public BigDecimal pow(int n, MathContext mc) {
1125:                // The ANSI standard X3.274-1996 algorithm
1126:                int m = Math.abs(n);
1127:                int mcPrecision = mc.getPrecision();
1128:                int elength = (int) Math.log10(m) + 1; // decimal digits in 'n'
1129:                int oneBitMask; // mask of bits
1130:                BigDecimal accum; // the single accumulator
1131:                MathContext newPrecision = mc; // MathContext by default
1132:
1133:                // In particular cases, it reduces the problem to call the other 'pow()'
1134:                if ((n == 0) || ((isZero()) && (n > 0))) {
1135:                    return pow(n);
1136:                }
1137:                if ((m > 999999999) || ((mcPrecision == 0) && (n < 0))
1138:                        || ((mcPrecision > 0) && (elength > mcPrecision))) {
1139:                    // math.07=Invalid Operation
1140:                    throw new ArithmeticException(Messages.getString("math.07")); //$NON-NLS-1$
1141:                }
1142:                if (mcPrecision > 0) {
1143:                    newPrecision = new MathContext(mcPrecision + elength + 1,
1144:                            mc.getRoundingMode());
1145:                }
1146:                // The result is calculated as if 'n' were positive        
1147:                accum = round(newPrecision);
1148:                oneBitMask = Integer.highestOneBit(m) >> 1;
1149:
1150:                while (oneBitMask > 0) {
1151:                    accum = accum.multiply(accum, newPrecision);
1152:                    if ((m & oneBitMask) == oneBitMask) {
1153:                        accum = accum.multiply(this , newPrecision);
1154:                    }
1155:                    oneBitMask >>= 1;
1156:                }
1157:                // If 'n' is negative, the value is divided into 'ONE'
1158:                if (n < 0) {
1159:                    accum = ONE.divide(accum, newPrecision);
1160:                }
1161:                // The final value is rounded to the destination precision
1162:                accum.inplaceRound(mc);
1163:                return accum;
1164:            }
1165:
1166:            /** @ar.org.fitc.spec_ref */
1167:            public BigDecimal abs() {
1168:                return ((signum() < 0) ? negate() : this );
1169:            }
1170:
1171:            /** @ar.org.fitc.spec_ref */
1172:            public BigDecimal abs(MathContext mc) {
1173:                return round(mc).abs();
1174:            }
1175:
1176:            /** @ar.org.fitc.spec_ref */
1177:            public BigDecimal negate() {
1178:                if (bitLength < 63
1179:                        || (bitLength == 63 && smallValue != Long.MIN_VALUE)) {
1180:                    return valueOf(-smallValue, scale);
1181:                }
1182:                return new BigDecimal(getUnscaledValue().negate(), scale);
1183:            }
1184:
1185:            /** @ar.org.fitc.spec_ref */
1186:            public BigDecimal negate(MathContext mc) {
1187:                return round(mc).negate();
1188:            }
1189:
1190:            /** @ar.org.fitc.spec_ref */
1191:            public BigDecimal plus() {
1192:                return this ;
1193:            }
1194:
1195:            /** @ar.org.fitc.spec_ref */
1196:            public BigDecimal plus(MathContext mc) {
1197:                return round(mc);
1198:            }
1199:
1200:            /** @ar.org.fitc.spec_ref */
1201:            public int signum() {
1202:                if (bitLength < 64) {
1203:                    return Long.signum(this .smallValue);
1204:                }
1205:                return getUnscaledValue().signum();
1206:            }
1207:
1208:            private boolean isZero() {
1209:                //Watch out: -1 has a bitLength=0
1210:                return bitLength == 0 && this .smallValue != -1;
1211:            }
1212:
1213:            /** @ar.org.fitc.spec_ref */
1214:            public int scale() {
1215:                return scale;
1216:            }
1217:
1218:            /** @ar.org.fitc.spec_ref */
1219:            public int precision() {
1220:                // Checking if the precision already was calculated
1221:                if (precision > 0) {
1222:                    return precision;
1223:                }
1224:                int bitLength = this .bitLength;
1225:                int decimalDigits = 1; // the precision to be calculated
1226:                double doubleUnsc = 1; // intVal in 'double'
1227:
1228:                if (bitLength < 1024) {
1229:                    // To calculate the precision for small numbers
1230:                    if (bitLength >= 64) {
1231:                        doubleUnsc = getUnscaledValue().doubleValue();
1232:                    } else if (bitLength >= 1) {
1233:                        doubleUnsc = smallValue;
1234:                    }
1235:                    decimalDigits += Math.log10(Math.abs(doubleUnsc));
1236:                } else {// (bitLength >= 1024)
1237:                    /* To calculate the precision for large numbers
1238:                     * Note that: 2 ^(bitlength() - 1) <= intVal < 10 ^(precision()) */
1239:                    decimalDigits += (bitLength - 1) * LOG10_2;
1240:                    // If after division the number isn't zero, exists an aditional digit
1241:                    if (getUnscaledValue().divide(
1242:                            Multiplication.powerOf10(decimalDigits)).signum() != 0) {
1243:                        decimalDigits++;
1244:                    }
1245:                }
1246:                precision = decimalDigits;
1247:                return precision;
1248:            }
1249:
1250:            /** @ar.org.fitc.spec_ref */
1251:            public BigInteger unscaledValue() {
1252:                return getUnscaledValue();
1253:            }
1254:
1255:            /** @ar.org.fitc.spec_ref */
1256:            public BigDecimal round(MathContext mc) {
1257:                BigDecimal this BD = new BigDecimal(getUnscaledValue(), scale);
1258:
1259:                this BD.inplaceRound(mc);
1260:                return this BD;
1261:            }
1262:
1263:            /** @ar.org.fitc.spec_ref */
1264:            public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
1265:                if (roundingMode == null) {
1266:                    throw new NullPointerException();
1267:                }
1268:                long diffScale = newScale - (long) scale;
1269:                // Let be:  'this' = [u,s]        
1270:                if (diffScale == 0) {
1271:                    return this ;
1272:                }
1273:                if (diffScale > 0) {
1274:                    // return  [u * 10^(s2 - s), newScale]
1275:                    if (diffScale < LONG_TEN_POW.length
1276:                            && (this .bitLength + LONG_TEN_POW_BIT_LENGTH[(int) diffScale]) < 64) {
1277:                        return valueOf(this .smallValue
1278:                                * LONG_TEN_POW[(int) diffScale], newScale);
1279:                    }
1280:                    return new BigDecimal(Multiplication.multiplyByTenPow(
1281:                            getUnscaledValue(), (int) diffScale), newScale);
1282:                }
1283:                // diffScale < 0
1284:                // return  [u,s] / [1,newScale]  with the appropriate scale and rounding
1285:                if (this .bitLength < 64 && -diffScale < LONG_TEN_POW.length) {
1286:                    return dividePrimitiveLongs(this .smallValue,
1287:                            LONG_TEN_POW[(int) -diffScale], newScale,
1288:                            roundingMode);
1289:                }
1290:                return divideBigIntegers(this .getUnscaledValue(),
1291:                        Multiplication.powerOf10(-diffScale), newScale,
1292:                        roundingMode);
1293:            }
1294:
1295:            /** @ar.org.fitc.spec_ref */
1296:            public BigDecimal setScale(int newScale, int roundingMode) {
1297:                return setScale(newScale, RoundingMode.valueOf(roundingMode));
1298:            }
1299:
1300:            /** @ar.org.fitc.spec_ref */
1301:            public BigDecimal setScale(int newScale) {
1302:                return setScale(newScale, RoundingMode.UNNECESSARY);
1303:            }
1304:
1305:            /** @ar.org.fitc.spec_ref */
1306:            public BigDecimal movePointLeft(int n) {
1307:                return movePoint(scale + (long) n);
1308:            }
1309:
1310:            private BigDecimal movePoint(long newScale) {
1311:                if (isZero()) {
1312:                    return zeroScaledBy(Math.max(newScale, 0));
1313:                }
1314:                /* When:  'n'== Integer.MIN_VALUE  isn't possible to call to movePointRight(-n)  
1315:                 * since  -Integer.MIN_VALUE == Integer.MIN_VALUE */
1316:                if (newScale >= 0) {
1317:                    if (bitLength < 64) {
1318:                        return valueOf(smallValue, toIntScale(newScale));
1319:                    }
1320:                    return new BigDecimal(getUnscaledValue(),
1321:                            toIntScale(newScale));
1322:                }
1323:                if (-newScale < LONG_TEN_POW.length
1324:                        && bitLength + LONG_TEN_POW_BIT_LENGTH[(int) -newScale] < 64) {
1325:                    return valueOf(smallValue * LONG_TEN_POW[(int) -newScale],
1326:                            0);
1327:                }
1328:                return new BigDecimal(Multiplication.multiplyByTenPow(
1329:                        getUnscaledValue(), (int) -newScale), 0);
1330:            }
1331:
1332:            /** @ar.org.fitc.spec_ref */
1333:            public BigDecimal movePointRight(int n) {
1334:                return movePoint(scale - (long) n);
1335:            }
1336:
1337:            /** @ar.org.fitc.spec_ref */
1338:            public BigDecimal scaleByPowerOfTen(int n) {
1339:                long newScale = scale - (long) n;
1340:                if (bitLength < 64) {
1341:                    //Taking care when a 0 is to be scaled
1342:                    if (smallValue == 0) {
1343:                        return zeroScaledBy(newScale);
1344:                    }
1345:                    return valueOf(smallValue, toIntScale(newScale));
1346:                }
1347:                return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
1348:            }
1349:
1350:            /** @ar.org.fitc.spec_ref */
1351:            public BigDecimal stripTrailingZeros() {
1352:                int i = 1; // 1 <= i <= 18
1353:                int lastPow = TEN_POW.length - 1;
1354:                long newScale = scale;
1355:
1356:                if (isZero()) {
1357:                    return new BigDecimal("0");
1358:                }
1359:                BigInteger strippedBI = getUnscaledValue();
1360:                BigInteger[] quotAndRem;
1361:
1362:                // while the number is even...
1363:                while (!strippedBI.testBit(0)) {
1364:                    // To divide by 10^i
1365:                    quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
1366:                    // To look the remainder
1367:                    if (quotAndRem[1].signum() == 0) {
1368:                        // To adjust the scale
1369:                        newScale -= i;
1370:                        if (i < lastPow) {
1371:                            // To set to the next power
1372:                            i++;
1373:                        }
1374:                        strippedBI = quotAndRem[0];
1375:                    } else {
1376:                        if (i == 1) {
1377:                            // 'this' has no more trailing zeros
1378:                            break;
1379:                        }
1380:                        // To set to the smallest power of ten
1381:                        i = 1;
1382:                    }
1383:                }
1384:                return new BigDecimal(strippedBI, toIntScale(newScale));
1385:            }
1386:
1387:            /** @ar.org.fitc.spec_ref */
1388:            public int compareTo(BigDecimal val) {
1389:                int this Sign = signum();
1390:                int valueSign = val.signum();
1391:
1392:                if (this Sign == valueSign) {
1393:                    if (this .scale == val.scale && this .bitLength < 64
1394:                            && val.bitLength < 64) {
1395:                        return (smallValue < val.smallValue) ? -1
1396:                                : (smallValue > val.smallValue) ? 1 : 0;
1397:                    }
1398:                    long diffScale = (long) this .scale - val.scale;
1399:                    int diffPrecision = this .aproxPrecision()
1400:                            - val.aproxPrecision();
1401:                    if (diffPrecision > diffScale + 1) {
1402:                        return this Sign;
1403:                    } else if (diffPrecision < diffScale - 1) {
1404:                        return -this Sign;
1405:                    } else {// thisSign == val.signum()  and  diffPrecision is aprox. diffScale
1406:                        BigInteger this Unscaled = this .getUnscaledValue();
1407:                        BigInteger valUnscaled = val.getUnscaledValue();
1408:                        // If any of both precision is bigger, append zeros to the shorter one
1409:                        if (diffScale < 0) {
1410:                            this Unscaled = this Unscaled.multiply(Multiplication
1411:                                    .powerOf10(-diffScale));
1412:                        } else if (diffScale > 0) {
1413:                            valUnscaled = valUnscaled.multiply(Multiplication
1414:                                    .powerOf10(diffScale));
1415:                        }
1416:                        return this Unscaled.compareTo(valUnscaled);
1417:                    }
1418:                } else if (this Sign < valueSign) {
1419:                    return -1;
1420:                } else {
1421:                    return 1;
1422:                }
1423:            }
1424:
1425:            /** @ar.org.fitc.spec_ref */
1426:            @Override
1427:            public boolean equals(Object x) {
1428:                if (this  == x) {
1429:                    return true;
1430:                }
1431:                if (x instanceof  BigDecimal) {
1432:                    BigDecimal x1 = (BigDecimal) x;
1433:                    return x1.scale == scale
1434:                            && (bitLength < 64 ? (x1.smallValue == smallValue)
1435:                                    : intVal.equals(x1.intVal));
1436:
1437:                }
1438:                return false;
1439:            }
1440:
1441:            /** @ar.org.fitc.spec_ref */
1442:            public BigDecimal min(BigDecimal val) {
1443:                return ((compareTo(val) <= 0) ? this  : val);
1444:            }
1445:
1446:            /** @ar.org.fitc.spec_ref */
1447:            public BigDecimal max(BigDecimal val) {
1448:                return ((compareTo(val) >= 0) ? this  : val);
1449:            }
1450:
1451:            /** @ar.org.fitc.spec_ref */
1452:            @Override
1453:            public int hashCode() {
1454:                if (hashCode != 0) {
1455:                    return hashCode;
1456:                }
1457:                if (bitLength < 64) {
1458:                    hashCode = (int) (smallValue & 0xffffffff);
1459:                    hashCode = 33 * hashCode
1460:                            + (int) ((smallValue >> 32) & 0xffffffff);
1461:                    hashCode = 17 * hashCode + scale;
1462:                    return hashCode;
1463:                }
1464:                hashCode = 17 * intVal.hashCode() + scale;
1465:                return hashCode;
1466:            }
1467:
1468:            /** @ar.org.fitc.spec_ref */
1469:            @Override
1470:            public String toString() {
1471:                if (toStringImage != null) {
1472:                    return toStringImage;
1473:                }
1474:                if (bitLength < 32) {
1475:                    toStringImage = Conversion.toDecimalScaledString(
1476:                            smallValue, scale);
1477:                    return toStringImage;
1478:                }
1479:                String intString = getUnscaledValue().toString();
1480:                if (scale == 0) {
1481:                    return intString;
1482:                }
1483:                int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
1484:                int end = intString.length();
1485:                long exponent = -(long) scale + end - begin;
1486:                StringBuffer result = new StringBuffer();
1487:
1488:                result.append(intString);
1489:                if ((scale > 0) && (exponent >= -6)) {
1490:                    if (exponent >= 0) {
1491:                        result.insert(end - scale, '.');
1492:                    } else {
1493:                        result.insert(begin - 1, "0."); //$NON-NLS-1$
1494:                        result.insert(begin + 1, CH_ZEROS, 0,
1495:                                -(int) exponent - 1);
1496:                    }
1497:                } else {
1498:                    if (end - begin >= 1) {
1499:                        result.insert(begin, '.');
1500:                        end++;
1501:                    }
1502:                    result.insert(end, 'E');
1503:                    if (exponent > 0) {
1504:                        result.insert(++end, '+');
1505:                    }
1506:                    result.insert(++end, Long.toString(exponent));
1507:                }
1508:                toStringImage = result.toString();
1509:                return toStringImage;
1510:            }
1511:
1512:            /** @ar.org.fitc.spec_ref */
1513:            public String toEngineeringString() {
1514:                String intString = getUnscaledValue().toString();
1515:                if (scale == 0) {
1516:                    return intString;
1517:                }
1518:                int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
1519:                int end = intString.length();
1520:                long exponent = -(long) scale + end - begin;
1521:                StringBuffer result = new StringBuffer(intString);
1522:
1523:                if ((scale > 0) && (exponent >= -6)) {
1524:                    if (exponent >= 0) {
1525:                        result.insert(end - scale, '.');
1526:                    } else {
1527:                        result.insert(begin - 1, "0."); //$NON-NLS-1$
1528:                        result.insert(begin + 1, CH_ZEROS, 0,
1529:                                -(int) exponent - 1);
1530:                    }
1531:                } else {
1532:                    int delta = end - begin;
1533:                    int rem = (int) (exponent % 3);
1534:
1535:                    if (rem != 0) {
1536:                        // adjust exponent so it is a multiple of three
1537:                        if (getUnscaledValue().signum() == 0) {
1538:                            // zero value
1539:                            rem = (rem < 0) ? -rem : 3 - rem;
1540:                            exponent += rem;
1541:                        } else {
1542:                            // nonzero value
1543:                            rem = (rem < 0) ? rem + 3 : rem;
1544:                            exponent -= rem;
1545:                            begin += rem;
1546:                        }
1547:                        if (delta < 3) {
1548:                            for (int i = rem - delta; i > 0; i--) {
1549:                                result.insert(end++, '0');
1550:                            }
1551:                        }
1552:                    }
1553:                    if (end - begin >= 1) {
1554:                        result.insert(begin, '.');
1555:                        end++;
1556:                    }
1557:                    if (exponent != 0) {
1558:                        result.insert(end, 'E');
1559:                        if (exponent > 0) {
1560:                            result.insert(++end, '+');
1561:                        }
1562:                        result.insert(++end, Long.toString(exponent));
1563:                    }
1564:                }
1565:                return result.toString();
1566:            }
1567:
1568:            /** @ar.org.fitc.spec_ref */
1569:            public String toPlainString() {
1570:                String intStr = getUnscaledValue().toString();
1571:                if ((scale == 0) || ((isZero()) && (scale < 0))) {
1572:                    return intStr;
1573:                }
1574:                int begin = (signum() < 0) ? 1 : 0;
1575:                int delta = scale;
1576:                // We take space for all digits, plus a possible decimal point, plus 'scale'
1577:                StringBuffer result = new StringBuffer(intStr.length() + 1
1578:                        + Math.abs(scale));
1579:
1580:                if (begin == 1) {
1581:                    // If the number is negative, we insert a '-' character at front 
1582:                    result.append('-');
1583:                }
1584:                if (scale > 0) {
1585:                    delta -= (intStr.length() - begin);
1586:                    if (delta >= 0) {
1587:                        result.append("0."); //$NON-NLS-1$
1588:                        // To append zeros after the decimal point
1589:                        for (; delta > CH_ZEROS.length; delta -= CH_ZEROS.length) {
1590:                            result.append(CH_ZEROS);
1591:                        }
1592:                        result.append(CH_ZEROS, 0, delta);
1593:                        result.append(intStr.substring(begin));
1594:                    } else {
1595:                        delta = begin - delta;
1596:                        result.append(intStr.substring(begin, delta));
1597:                        result.append('.');
1598:                        result.append(intStr.substring(delta));
1599:                    }
1600:                } else {// (scale <= 0)
1601:                    result.append(intStr.substring(begin));
1602:                    // To append trailing zeros
1603:                    for (; delta < -CH_ZEROS.length; delta += CH_ZEROS.length) {
1604:                        result.append(CH_ZEROS);
1605:                    }
1606:                    result.append(CH_ZEROS, 0, -delta);
1607:                }
1608:                return result.toString();
1609:            }
1610:
1611:            /** @ar.org.fitc.spec_ref */
1612:            public BigInteger toBigInteger() {
1613:                if ((scale == 0) || (isZero())) {
1614:                    return getUnscaledValue();
1615:                } else if (scale < 0) {
1616:                    return getUnscaledValue().multiply(
1617:                            Multiplication.powerOf10(-(long) scale));
1618:                } else {// (scale > 0)
1619:                    return getUnscaledValue().divide(
1620:                            Multiplication.powerOf10(scale));
1621:                }
1622:            }
1623:
1624:            /** @ar.org.fitc.spec_ref */
1625:            public BigInteger toBigIntegerExact() {
1626:                if ((scale == 0) || (isZero())) {
1627:                    return getUnscaledValue();
1628:                } else if (scale < 0) {
1629:                    return getUnscaledValue().multiply(
1630:                            Multiplication.powerOf10(-(long) scale));
1631:                } else {// (scale > 0)
1632:                    BigInteger[] integerAndFraction;
1633:                    // An optimization before do a heavy division
1634:                    if ((scale > aproxPrecision())
1635:                            || (scale > getUnscaledValue().getLowestSetBit())) {
1636:                        // math.08=Rounding necessary
1637:                        throw new ArithmeticException(Messages
1638:                                .getString("math.08")); //$NON-NLS-1$
1639:                    }
1640:                    integerAndFraction = getUnscaledValue().divideAndRemainder(
1641:                            Multiplication.powerOf10(scale));
1642:                    if (integerAndFraction[1].signum() != 0) {
1643:                        // It exists a non-zero fractional part 
1644:                        // math.08=Rounding necessary
1645:                        throw new ArithmeticException(Messages
1646:                                .getString("math.08")); //$NON-NLS-1$
1647:                    }
1648:                    return integerAndFraction[0];
1649:                }
1650:            }
1651:
1652:            /** @ar.org.fitc.spec_ref */
1653:            @Override
1654:            public long longValue() {
1655:                /* If scale <= -64 there are at least 64 trailing bits zero in 10^(-scale).
1656:                 * If the scale is positive and very large the long value could be zero. */
1657:                return ((scale <= -64) || (scale > aproxPrecision()) ? 0L
1658:                        : toBigInteger().longValue());
1659:            }
1660:
1661:            /** @ar.org.fitc.spec_ref */
1662:            public long longValueExact() {
1663:                return valueExact(64);
1664:            }
1665:
1666:            /** @ar.org.fitc.spec_ref */
1667:            @Override
1668:            public int intValue() {
1669:                /* If scale <= -32 there are at least 32 trailing bits zero in 10^(-scale).
1670:                 * If the scale is positive and very large the long value could be zero. */
1671:                return ((scale <= -32) || (scale > aproxPrecision()) ? 0
1672:                        : toBigInteger().intValue());
1673:            }
1674:
1675:            /** @ar.org.fitc.spec_ref */
1676:            public int intValueExact() {
1677:                return (int) valueExact(32);
1678:            }
1679:
1680:            /** @ar.org.fitc.spec_ref */
1681:            public short shortValueExact() {
1682:                return (short) valueExact(16);
1683:            }
1684:
1685:            /** @ar.org.fitc.spec_ref */
1686:            public byte byteValueExact() {
1687:                return (byte) valueExact(8);
1688:            }
1689:
1690:            /** @ar.org.fitc.spec_ref */
1691:            @Override
1692:            public float floatValue() {
1693:                /* A similar code like in doubleValue() could be repeated here,
1694:                 * but this simple implementation is quite efficient. */
1695:                float floatResult = signum();
1696:                long powerOfTwo = this .bitLength - (long) (scale / LOG10_2);
1697:                if ((powerOfTwo < -149) || (floatResult == 0.0f)) {
1698:                    // Cases which 'this' is very small
1699:                    floatResult *= 0.0f;
1700:                } else if (powerOfTwo > 129) {
1701:                    // Cases which 'this' is very large
1702:                    floatResult *= Float.POSITIVE_INFINITY;
1703:                } else {
1704:                    floatResult = (float) doubleValue();
1705:                }
1706:                return floatResult;
1707:            }
1708:
1709:            /** @ar.org.fitc.spec_ref */
1710:            @Override
1711:            public double doubleValue() {
1712:                int sign = signum();
1713:                int exponent = 1076; // bias + 53
1714:                int lowestSetBit;
1715:                int discardedSize;
1716:                long powerOfTwo = this .bitLength - (long) (scale / LOG10_2);
1717:                long bits; // IEEE-754 Standard
1718:                long tempBits; // for temporal calculations     
1719:                BigInteger mantisa;
1720:
1721:                if ((powerOfTwo < -1074) || (sign == 0)) {
1722:                    // Cases which 'this' is very small            
1723:                    return (sign * 0.0d);
1724:                } else if (powerOfTwo > 1025) {
1725:                    // Cases which 'this' is very large            
1726:                    return (sign * Double.POSITIVE_INFINITY);
1727:                }
1728:                mantisa = getUnscaledValue().abs();
1729:                // Let be:  this = [u,s], with s > 0
1730:                if (scale <= 0) {
1731:                    // mantisa = abs(u) * 10^s
1732:                    mantisa = mantisa
1733:                            .multiply(Multiplication.powerOf10(-scale));
1734:                } else {// (scale > 0)
1735:                    BigInteger quotAndRem[];
1736:                    BigInteger powerOfTen = Multiplication.powerOf10(scale);
1737:                    int k = 100 - (int) powerOfTwo;
1738:                    int compRem;
1739:
1740:                    if (k > 0) {
1741:                        /* Computing (mantisa * 2^k) , where 'k' is a enough big
1742:                         * power of '2' to can divide by 10^s */
1743:                        mantisa = mantisa.shiftLeft(k);
1744:                        exponent -= k;
1745:                    }
1746:                    // Computing (mantisa * 2^k) / 10^s
1747:                    quotAndRem = mantisa.divideAndRemainder(powerOfTen);
1748:                    // To check if the fractional part >= 0.5
1749:                    compRem = quotAndRem[1].shiftLeft(1).compareTo(powerOfTen);
1750:                    // To add two rounded bits at end of mantisa
1751:                    mantisa = quotAndRem[0]
1752:                            .shiftLeft(2)
1753:                            .add(
1754:                                    BigInteger
1755:                                            .valueOf((compRem * (compRem + 3)) / 2 + 1));
1756:                    exponent -= 2;
1757:                }
1758:                lowestSetBit = mantisa.getLowestSetBit();
1759:                discardedSize = mantisa.bitLength() - 54;
1760:                if (discardedSize > 0) {// (n > 54)
1761:                    // mantisa = (abs(u) * 10^s) >> (n - 54)
1762:                    bits = mantisa.shiftRight(discardedSize).longValue();
1763:                    tempBits = bits;
1764:                    // #bits = 54, to check if the discarded fraction produces a carry             
1765:                    if ((((bits & 1) == 1) && (lowestSetBit < discardedSize))
1766:                            || ((bits & 3) == 3)) {
1767:                        bits += 2;
1768:                    }
1769:                } else {// (n <= 54)
1770:                    // mantisa = (abs(u) * 10^s) << (54 - n)                
1771:                    bits = mantisa.longValue() << -discardedSize;
1772:                    tempBits = bits;
1773:                    // #bits = 54, to check if the discarded fraction produces a carry:
1774:                    if ((bits & 3) == 3) {
1775:                        bits += 2;
1776:                    }
1777:                }
1778:                // Testing bit 54 to check if the carry creates a new binary digit
1779:                if ((bits & 0x40000000000000L) == 0) {
1780:                    // To drop the last bit of mantisa (first discarded)
1781:                    bits >>= 1;
1782:                    // exponent = 2^(s-n+53+bias)
1783:                    exponent += discardedSize;
1784:                } else {// #bits = 54
1785:                    bits >>= 2;
1786:                    exponent += discardedSize + 1;
1787:                }
1788:                // To test if the 53-bits number fits in 'double'            
1789:                if (exponent > 2046) {// (exponent - bias > 1023)
1790:                    return (sign * Double.POSITIVE_INFINITY);
1791:                } else if (exponent <= 0) {// (exponent - bias <= -1023)
1792:                    // Denormalized numbers (having exponent == 0)
1793:                    if (exponent < -53) {// exponent - bias < -1076
1794:                        return (sign * 0.0d);
1795:                    }
1796:                    // -1076 <= exponent - bias <= -1023 
1797:                    // To discard '- exponent + 1' bits
1798:                    bits = tempBits >> 1;
1799:                    tempBits = bits & (-1L >>> (63 + exponent));
1800:                    bits >>= (-exponent);
1801:                    // To test if after discard bits, a new carry is generated
1802:                    if (((bits & 3) == 3)
1803:                            || (((bits & 1) == 1) && (tempBits != 0) && (lowestSetBit < discardedSize))) {
1804:                        bits += 1;
1805:                    }
1806:                    exponent = 0;
1807:                    bits >>= 1;
1808:                }
1809:                // Construct the 64 double bits: [sign(1), exponent(11), mantisa(52)]
1810:                bits = (sign & 0x8000000000000000L) | ((long) exponent << 52)
1811:                        | (bits & 0xFFFFFFFFFFFFFL);
1812:                return Double.longBitsToDouble(bits);
1813:            }
1814:
1815:            /** @ar.org.fitc.spec_ref */
1816:            public BigDecimal ulp() {
1817:                return valueOf(1, scale);
1818:            }
1819:
1820:            /* Private Methods */
1821:
1822:            /**
1823:             * It does all rounding work of the public method <code>round(MathContext)</code>, 
1824:             * performing an inplace rounding without creating a new object.
1825:             * @param mc the <code>MathContext</code> for perform the rounding.
1826:             * @see #round(MathContext).
1827:             */
1828:            private void inplaceRound(MathContext mc) {
1829:                int mcPrecision = mc.getPrecision();
1830:                if (aproxPrecision() - mcPrecision <= 0 || mcPrecision == 0) {
1831:                    return;
1832:                }
1833:                int discardedPrecision = precision() - mcPrecision;
1834:                // If no rounding is necessary it returns immediately
1835:                if ((discardedPrecision <= 0)) {
1836:                    return;
1837:                }
1838:                // When the number is small perform an efficient rounding
1839:                if (this .bitLength < 64) {
1840:                    smallRound(mc, discardedPrecision);
1841:                    return;
1842:                }
1843:                // Getting the integer part and the discarded fraction
1844:                BigInteger sizeOfFraction = Multiplication
1845:                        .powerOf10(discardedPrecision);
1846:                BigInteger[] integerAndFraction = getUnscaledValue()
1847:                        .divideAndRemainder(sizeOfFraction);
1848:                long newScale = (long) scale - discardedPrecision;
1849:                int compRem;
1850:                BigDecimal tempBD;
1851:                // If the discarded fraction is non-zero, perform rounding
1852:                if (integerAndFraction[1].signum() != 0) {
1853:                    // To check if the discarded fraction >= 0.5
1854:                    compRem = (integerAndFraction[1].abs().shiftLeft(1)
1855:                            .compareTo(sizeOfFraction));
1856:                    // To look if there is a carry
1857:                    compRem = roundingBehavior(
1858:                            integerAndFraction[0].testBit(0) ? 1 : 0,
1859:                            integerAndFraction[1].signum() * (5 + compRem), mc
1860:                                    .getRoundingMode());
1861:                    if (compRem != 0) {
1862:                        integerAndFraction[0] = integerAndFraction[0]
1863:                                .add(BigInteger.valueOf(compRem));
1864:                    }
1865:                    tempBD = new BigDecimal(integerAndFraction[0]);
1866:                    // If after to add the increment the precision changed, we normalize the size
1867:                    if (tempBD.precision() > mcPrecision) {
1868:                        integerAndFraction[0] = integerAndFraction[0]
1869:                                .divide(BigInteger.TEN);
1870:                        newScale--;
1871:                    }
1872:                }
1873:                // To update all internal fields
1874:                scale = toIntScale(newScale);
1875:                precision = mcPrecision;
1876:                setUnscaledValue(integerAndFraction[0]);
1877:            }
1878:
1879:            private static int longCompareTo(long value1, long value2) {
1880:                return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
1881:            }
1882:
1883:            /**
1884:             * This method implements an efficient rounding for numbers which unscaled 
1885:             * value fits in the type <code>long</code>.
1886:             * @param mc the context to use.
1887:             * @param discardedPrecision the number of decimal digits that are discarded.
1888:             * @see #round(MathContext).
1889:             */
1890:            private void smallRound(MathContext mc, int discardedPrecision) {
1891:                long sizeOfFraction = LONG_TEN_POW[discardedPrecision];
1892:                long newScale = (long) scale - discardedPrecision;
1893:                long unscaledVal = smallValue;
1894:                // Getting the integer part and the discarded fraction
1895:                long integer = unscaledVal / sizeOfFraction;
1896:                long fraction = unscaledVal % sizeOfFraction;
1897:                int compRem;
1898:                // If the discarded fraction is non-zero perform rounding
1899:                if (fraction != 0) {
1900:                    // To check if the discarded fraction >= 0.5
1901:                    compRem = longCompareTo(Math.abs(fraction) << 1,
1902:                            sizeOfFraction);
1903:                    // To look if there is a carry
1904:                    integer += roundingBehavior(((int) integer) & 1, Long
1905:                            .signum(fraction)
1906:                            * (5 + compRem), mc.getRoundingMode());
1907:                    // If after to add the increment the precision changed, we normalize the size
1908:                    if (Math.log10(Math.abs(integer)) >= mc.getPrecision()) {
1909:                        integer /= 10;
1910:                        newScale--;
1911:                    }
1912:                }
1913:                // To update all internal fields
1914:                scale = toIntScale(newScale);
1915:                precision = mc.getPrecision();
1916:                smallValue = integer;
1917:                bitLength = bitLength(integer);
1918:                intVal = null;
1919:            }
1920:
1921:            /**
1922:             * Return an increment that can be -1,0 or 1, depending of <code>roundingMode</code>.
1923:             * @param parityBit can be 0 or 1, it's only used in the case <code>HALF_EVEN</code>.  
1924:             * @param fraction the mantisa to be analyzed.
1925:             * @param roundingMode the type of rounding.
1926:             * @return the carry propagated after rounding.
1927:             */
1928:            private static int roundingBehavior(int parityBit, int fraction,
1929:                    RoundingMode roundingMode) {
1930:                int increment = 0; // the carry after rounding
1931:
1932:                switch (roundingMode) {
1933:                case UNNECESSARY:
1934:                    if (fraction != 0) {
1935:                        // math.08=Rounding necessary
1936:                        throw new ArithmeticException(Messages
1937:                                .getString("math.08")); //$NON-NLS-1$
1938:                    }
1939:                    break;
1940:                case UP:
1941:                    increment = Integer.signum(fraction);
1942:                    break;
1943:                case DOWN:
1944:                    break;
1945:                case CEILING:
1946:                    increment = Math.max(Integer.signum(fraction), 0);
1947:                    break;
1948:                case FLOOR:
1949:                    increment = Math.min(Integer.signum(fraction), 0);
1950:                    break;
1951:                case HALF_UP:
1952:                    if (Math.abs(fraction) >= 5) {
1953:                        increment = Integer.signum(fraction);
1954:                    }
1955:                    break;
1956:                case HALF_DOWN:
1957:                    if (Math.abs(fraction) > 5) {
1958:                        increment = Integer.signum(fraction);
1959:                    }
1960:                    break;
1961:                case HALF_EVEN:
1962:                    if (Math.abs(fraction) + parityBit > 5) {
1963:                        increment = Integer.signum(fraction);
1964:                    }
1965:                    break;
1966:                }
1967:                return increment;
1968:            }
1969:
1970:            /**
1971:             * If <code>intVal</code> has a fractional part throws an exception,
1972:             * otherwise it counts the number of bits of value and checks if it's out 
1973:             * of the range of the primitive type. If the number fits in the primitive
1974:             * type returns this number as <code>long</code>, otherwise throws an
1975:             * exception. 
1976:             *
1977:             * @param bitLengthOfType number of bits of the type whose value will be 
1978:             *         calculated exactly.
1979:             * @return the exact value of the integer part of <code>BigDecimal</code>
1980:             *         when is possible.
1981:             * @throws <code>ArithmeticException</code> when rounding is necessary or
1982:             *      the number don't fit in the primitive type.        
1983:             */
1984:            private long valueExact(int bitLengthOfType) {
1985:                BigInteger bigInteger = toBigIntegerExact();
1986:
1987:                if (bigInteger.bitLength() < bitLengthOfType) {
1988:                    // It fits in the primitive type
1989:                    return bigInteger.longValue();
1990:                }
1991:                // math.08=Rounding necessary
1992:                throw new ArithmeticException(Messages.getString("math.08")); //$NON-NLS-1$
1993:            }
1994:
1995:            /**
1996:             * If the precision already was calculated it returns that value, otherwise
1997:             * it calculates a very good approximation efficiently . Note that this 
1998:             * value will be <code>precision()</code> or <code>precision()-1</code>
1999:             * in the worst case.
2000:             * @return an approximation of <code>precision()</code> value
2001:             */
2002:            private int aproxPrecision() {
2003:                return ((precision > 0) ? precision
2004:                        : (int) ((this .bitLength - 1) * LOG10_2)) + 1;
2005:            }
2006:
2007:            /**
2008:             * It tests if a scale of type <code>long</code> fits in 32 bits. 
2009:             * It returns the same scale being casted to <code>int</code> type when 
2010:             * is possible, otherwise throws an exception.
2011:             * @param longScale a 64 bit scale.
2012:             * @return a 32 bit scale when is possible.
2013:             * @throws <code>ArithmeticException</code> when <code>scale</code> 
2014:             *      doesn't fit in <code>int</code> type. 
2015:             * @see #scale     
2016:             */
2017:            private static int toIntScale(long longScale) {
2018:                if (longScale < Integer.MIN_VALUE) {
2019:                    // math.09=Overflow
2020:                    throw new ArithmeticException(Messages.getString("math.09")); //$NON-NLS-1$
2021:                } else if (longScale > Integer.MAX_VALUE) {
2022:                    // math.0A=Underflow
2023:                    throw new ArithmeticException(Messages.getString("math.0A")); //$NON-NLS-1$
2024:                } else {
2025:                    return (int) longScale;
2026:                }
2027:            }
2028:
2029:            /**
2030:             * It returns the value 0 with the most approximated scale of type 
2031:             * <code>int</code>. if <code>longScale > Integer.MAX_VALUE</code> 
2032:             * the scale will be <code>Integer.MAX_VALUE</code>; if 
2033:             * <code>longScale < Integer.MIN_VALUE</code> the scale will be
2034:             * <code>Integer.MIN_VALUE</code>; otherwise <code>longScale</code> is 
2035:             * casted to the type <code>int</code>. 
2036:             * @param longScale the scale to which the value 0 will be scaled.
2037:             * @return the value 0 scaled by the closer scale of type <code>int</code>.
2038:             * @see #scale
2039:             */
2040:            private static BigDecimal zeroScaledBy(long longScale) {
2041:                if (longScale == (int) longScale) {
2042:                    return valueOf(0, (int) longScale);
2043:                }
2044:                if (longScale >= 0) {
2045:                    return new BigDecimal(0, Integer.MAX_VALUE);
2046:                }
2047:                return new BigDecimal(0, Integer.MIN_VALUE);
2048:            }
2049:
2050:            /** @ar.org.fitc.spec_ref */
2051:            private void readObject(ObjectInputStream in) throws IOException,
2052:                    ClassNotFoundException {
2053:                in.defaultReadObject();
2054:
2055:                this .bitLength = intVal.bitLength();
2056:                if (this .bitLength < 64) {
2057:                    this .smallValue = intVal.longValue();
2058:                }
2059:            }
2060:
2061:            private void writeObject(ObjectOutputStream out) throws IOException {
2062:                getUnscaledValue();
2063:                out.defaultWriteObject();
2064:            }
2065:
2066:            private BigInteger getUnscaledValue() {
2067:                if (intVal == null) {
2068:                    intVal = BigInteger.valueOf(smallValue);
2069:                }
2070:                return intVal;
2071:            }
2072:
2073:            private void setUnscaledValue(BigInteger unscaledValue) {
2074:                this .intVal = unscaledValue;
2075:                this .bitLength = unscaledValue.bitLength();
2076:                if (this .bitLength < 64) {
2077:                    this .smallValue = unscaledValue.longValue();
2078:                }
2079:            }
2080:
2081:            private static int bitLength(long smallValue) {
2082:                if (smallValue < 0) {
2083:                    smallValue = ~smallValue;
2084:                }
2085:                return 64 - Long.numberOfLeadingZeros(smallValue);
2086:            }
2087:
2088:            private static int bitLength(int smallValue) {
2089:                if (smallValue < 0) {
2090:                    smallValue = ~smallValue;
2091:                }
2092:                return 32 - Integer.numberOfLeadingZeros(smallValue);
2093:            }
2094:
2095:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.