/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.math; /** * Static library that provides all multiplication of {@link BigInteger} methods. */ class Multiplication { /** Just to denote that this class can't be instantiated. */ private Multiplication() {} // BEGIN android-removed // /** // * Break point in digits (number of {@code int} elements) // * between Karatsuba and Pencil and Paper multiply. // */ // static final int whenUseKaratsuba = 63; // an heuristic value // END android-removed /** * An array with powers of ten that fit in the type {@code int}. * ({@code 10^0,10^1,...,10^9}) */ static final int[] tenPows = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; /** * An array with powers of five that fit in the type {@code int}. * ({@code 5^0,5^1,...,5^13}) */ static final int[] fivePows = { 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125 }; /** * An array with the first powers of ten in {@code BigInteger} version. * ({@code 10^0,10^1,...,10^31}) */ static final BigInteger[] bigTenPows = new BigInteger[32]; /** * An array with the first powers of five in {@code BigInteger} version. * ({@code 5^0,5^1,...,5^31}) */ static final BigInteger bigFivePows[] = new BigInteger[32]; static { int i; long fivePow = 1L; for (i = 0; i <= 18; i++) { bigFivePows[i] = BigInteger.valueOf(fivePow); bigTenPows[i] = BigInteger.valueOf(fivePow << i); fivePow *= 5; } for (; i < bigTenPows.length; i++) { bigFivePows[i] = bigFivePows[i - 1].multiply(bigFivePows[1]); bigTenPows[i] = bigTenPows[i - 1].multiply(BigInteger.TEN); } } // BEGIN android-note // The method multiply has been removed in favor of using OpenSSL BIGNUM // END android-note /** * Multiplies a number by a positive integer. * @param val an arbitrary {@code BigInteger} * @param factor a positive {@code int} number * @return {@code val * factor} */ static BigInteger multiplyByPositiveInt(BigInteger val, int factor) { BigInt bi = val.getBigInt().copy(); bi.multiplyByPositiveInt(factor); return new BigInteger(bi); } /** * Multiplies a number by a power of ten. * This method is used in {@code BigDecimal} class. * @param val the number to be multiplied * @param exp a positive {@code long} exponent * @return {@code val * 10exp} */ static BigInteger multiplyByTenPow(BigInteger val, long exp) { // PRE: exp >= 0 return ((exp < tenPows.length) ? multiplyByPositiveInt(val, tenPows[(int)exp]) : val.multiply(powerOf10(exp))); } /** * It calculates a power of ten, which exponent could be out of 32-bit range. * Note that internally this method will be used in the worst case with * an exponent equals to: {@code Integer.MAX_VALUE - Integer.MIN_VALUE}. * @param exp the exponent of power of ten, it must be positive. * @return a {@code BigInteger} with value {@code 10exp}. */ static BigInteger powerOf10(long exp) { // PRE: exp >= 0 int intExp = (int)exp; // "SMALL POWERS" if (exp < bigTenPows.length) { // The largest power that fit in 'long' type return bigTenPows[intExp]; } else if (exp <= 50) { // To calculate: 10^exp return BigInteger.TEN.pow(intExp); } else if (exp <= 1000) { // To calculate: 5^exp * 2^exp return bigFivePows[1].pow(intExp).shiftLeft(intExp); } // "LARGE POWERS" /* * To check if there is free memory to allocate a BigInteger of the * estimated size, measured in bytes: 1 + [exp / log10(2)] */ long byteArraySize = 1 + (long)(exp / 2.4082399653118496); if (byteArraySize > Runtime.getRuntime().freeMemory()) { throw new ArithmeticException(); } if (exp <= Integer.MAX_VALUE) { // To calculate: 5^exp * 2^exp return bigFivePows[1].pow(intExp).shiftLeft(intExp); } /* * "HUGE POWERS" * * This branch probably won't be executed since the power of ten is too * big. */ // To calculate: 5^exp BigInteger powerOfFive = bigFivePows[1].pow(Integer.MAX_VALUE); BigInteger res = powerOfFive; long longExp = exp - Integer.MAX_VALUE; intExp = (int)(exp % Integer.MAX_VALUE); while (longExp > Integer.MAX_VALUE) { res = res.multiply(powerOfFive); longExp -= Integer.MAX_VALUE; } res = res.multiply(bigFivePows[1].pow(intExp)); // To calculate: 5^exp << exp res = res.shiftLeft(Integer.MAX_VALUE); longExp = exp - Integer.MAX_VALUE; while (longExp > Integer.MAX_VALUE) { res = res.shiftLeft(Integer.MAX_VALUE); longExp -= Integer.MAX_VALUE; } res = res.shiftLeft(intExp); return res; } /** * Multiplies a number by a power of five. * This method is used in {@code BigDecimal} class. * @param val the number to be multiplied * @param exp a positive {@code int} exponent * @return {@code val * 5exp} */ static BigInteger multiplyByFivePow(BigInteger val, int exp) { // PRE: exp >= 0 if (exp < fivePows.length) { return multiplyByPositiveInt(val, fivePows[exp]); } else if (exp < bigFivePows.length) { return val.multiply(bigFivePows[exp]); } else {// Large powers of five return val.multiply(bigFivePows[1].pow(exp)); } } }