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 } |