jdk/src/java.base/share/classes/java/math/BigDecimal.java
changeset 28869 9725237b107d
parent 28257 070ef0dc9f5c
child 29220 b07abc731618
equal deleted inserted replaced
28868:445be2b2eae8 28869:9725237b107d
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
  4812     private static BigDecimal divideAndRound128(final long dividendHi, final long dividendLo, long divisor, int sign,
  4812     private static BigDecimal divideAndRound128(final long dividendHi, final long dividendLo, long divisor, int sign,
  4813                                                 int scale, int roundingMode, int preferredScale) {
  4813                                                 int scale, int roundingMode, int preferredScale) {
  4814         if (dividendHi >= divisor) {
  4814         if (dividendHi >= divisor) {
  4815             return null;
  4815             return null;
  4816         }
  4816         }
       
  4817 
  4817         final int shift = Long.numberOfLeadingZeros(divisor);
  4818         final int shift = Long.numberOfLeadingZeros(divisor);
  4818         divisor <<= shift;
  4819         divisor <<= shift;
  4819 
  4820 
  4820         final long v1 = divisor >>> 32;
  4821         final long v1 = divisor >>> 32;
  4821         final long v0 = divisor & LONG_MASK;
  4822         final long v0 = divisor & LONG_MASK;
  4822 
       
  4823         long q1, q0;
       
  4824         long r_tmp;
       
  4825 
  4823 
  4826         long tmp = dividendLo << shift;
  4824         long tmp = dividendLo << shift;
  4827         long u1 = tmp >>> 32;
  4825         long u1 = tmp >>> 32;
  4828         long u0 = tmp & LONG_MASK;
  4826         long u0 = tmp & LONG_MASK;
  4829 
  4827 
  4830         tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift);
  4828         tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift);
  4831         long u2 = tmp & LONG_MASK;
  4829         long u2 = tmp & LONG_MASK;
  4832         tmp = divWord(tmp,v1);
  4830         long q1, r_tmp;
  4833         q1 = tmp & LONG_MASK;
  4831         if (v1 == 1) {
  4834         r_tmp = tmp >>> 32;
  4832             q1 = tmp;
       
  4833             r_tmp = 0;
       
  4834         } else if (tmp >= 0) {
       
  4835             q1 = tmp / v1;
       
  4836             r_tmp = tmp - q1 * v1;
       
  4837         } else {
       
  4838             long[] rq = divRemNegativeLong(tmp, v1);
       
  4839             q1 = rq[1];
       
  4840             r_tmp = rq[0];
       
  4841         }
       
  4842 
  4835         while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) {
  4843         while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) {
  4836             q1--;
  4844             q1--;
  4837             r_tmp += v1;
  4845             r_tmp += v1;
  4838             if (r_tmp >= DIV_NUM_BASE)
  4846             if (r_tmp >= DIV_NUM_BASE)
  4839                 break;
  4847                 break;
  4840         }
  4848         }
       
  4849 
  4841         tmp = mulsub(u2,u1,v1,v0,q1);
  4850         tmp = mulsub(u2,u1,v1,v0,q1);
  4842         u1 = tmp & LONG_MASK;
  4851         u1 = tmp & LONG_MASK;
  4843         tmp = divWord(tmp,v1);
  4852         long q0;
  4844         q0 = tmp & LONG_MASK;
  4853         if (v1 == 1) {
  4845         r_tmp = tmp >>> 32;
  4854             q0 = tmp;
       
  4855             r_tmp = 0;
       
  4856         } else if (tmp >= 0) {
       
  4857             q0 = tmp / v1;
       
  4858             r_tmp = tmp - q0 * v1;
       
  4859         } else {
       
  4860             long[] rq = divRemNegativeLong(tmp, v1);
       
  4861             q0 = rq[1];
       
  4862             r_tmp = rq[0];
       
  4863         }
       
  4864 
  4846         while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) {
  4865         while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) {
  4847             q0--;
  4866             q0--;
  4848             r_tmp += v1;
  4867             r_tmp += v1;
  4849             if (r_tmp >= DIV_NUM_BASE)
  4868             if (r_tmp >= DIV_NUM_BASE)
  4850                 break;
  4869                 break;
  4851         }
  4870         }
       
  4871 
  4852         if((int)q1 < 0) {
  4872         if((int)q1 < 0) {
  4853             // result (which is positive and unsigned here)
  4873             // result (which is positive and unsigned here)
  4854             // can't fit into long due to sign bit is used for value
  4874             // can't fit into long due to sign bit is used for value
  4855             MutableBigInteger mq = new MutableBigInteger(new int[]{(int)q1, (int)q0});
  4875             MutableBigInteger mq = new MutableBigInteger(new int[]{(int)q1, (int)q0});
  4856             if (roundingMode == ROUND_DOWN && scale == preferredScale) {
  4876             if (roundingMode == ROUND_DOWN && scale == preferredScale) {
  4869                 } else {
  4889                 } else {
  4870                     return mq.toBigDecimal(sign, scale);
  4890                     return mq.toBigDecimal(sign, scale);
  4871                 }
  4891                 }
  4872             }
  4892             }
  4873         }
  4893         }
       
  4894 
  4874         long q = make64(q1,q0);
  4895         long q = make64(q1,q0);
  4875         q*=sign;
  4896         q*=sign;
       
  4897 
  4876         if (roundingMode == ROUND_DOWN && scale == preferredScale)
  4898         if (roundingMode == ROUND_DOWN && scale == preferredScale)
  4877             return valueOf(q, scale);
  4899             return valueOf(q, scale);
       
  4900 
  4878         long r = mulsub(u1, u0, v1, v0, q0) >>> shift;
  4901         long r = mulsub(u1, u0, v1, v0, q0) >>> shift;
  4879         if (r != 0) {
  4902         if (r != 0) {
  4880             boolean increment = needIncrement(divisor >>> shift, roundingMode, sign, q, r);
  4903             boolean increment = needIncrement(divisor >>> shift, roundingMode, sign, q, r);
  4881             return valueOf((increment ? q + sign : q), scale);
  4904             return valueOf((increment ? q + sign : q), scale);
  4882         } else {
  4905         } else {
  4915             }
  4938             }
  4916             return new BigDecimal(unscaledVal, INFLATED, scale, n+1);
  4939             return new BigDecimal(unscaledVal, INFLATED, scale, n+1);
  4917         }
  4940         }
  4918     }
  4941     }
  4919 
  4942 
  4920     private static long divWord(long n, long dLong) {
  4943     /**
  4921         long r;
  4944      * Calculate the quotient and remainder of dividing a negative long by
  4922         long q;
  4945      * another long.
  4923         if (dLong == 1) {
  4946      *
  4924             q = (int)n;
  4947      * @param n the numerator; must be negative
  4925             return (q & LONG_MASK);
  4948      * @param d the denominator; must not be unity
  4926         }
  4949      * @return a two-element {@long} array with the remainder and quotient in
       
  4950      *         the initial and final elements, respectively
       
  4951      */
       
  4952     private static long[] divRemNegativeLong(long n, long d) {
       
  4953         assert n < 0 : "Non-negative numerator " + n;
       
  4954         assert d != 1 : "Unity denominator";
       
  4955 
  4927         // Approximate the quotient and remainder
  4956         // Approximate the quotient and remainder
  4928         q = (n >>> 1) / (dLong >>> 1);
  4957         long q = (n >>> 1) / (d >>> 1);
  4929         r = n - q*dLong;
  4958         long r = n - q * d;
  4930 
  4959 
  4931         // Correct the approximation
  4960         // Correct the approximation
  4932         while (r < 0) {
  4961         while (r < 0) {
  4933             r += dLong;
  4962             r += d;
  4934             q--;
  4963             q--;
  4935         }
  4964         }
  4936         while (r >= dLong) {
  4965         while (r >= d) {
  4937             r -= dLong;
  4966             r -= d;
  4938             q++;
  4967             q++;
  4939         }
  4968         }
  4940         // n - q*dlong == r && 0 <= r <dLong, hence we're done.
  4969 
  4941         return (r << 32) | (q & LONG_MASK);
  4970         // n - q*d == r && 0 <= r < d, hence we're done.
       
  4971         return new long[] {r, q};
  4942     }
  4972     }
  4943 
  4973 
  4944     private static long make64(long hi, long lo) {
  4974     private static long make64(long hi, long lo) {
  4945         return hi<<32 | lo;
  4975         return hi<<32 | lo;
  4946     }
  4976     }