Home | History | Annotate | Download | only in math
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.math;
     19 
     20 /**
     21  * Static library that provides all multiplication of {@link BigInteger} methods.
     22  */
     23 class Multiplication {
     24 
     25     /** Just to denote that this class can't be instantiated. */
     26     private Multiplication() {}
     27 
     28     // BEGIN android-removed
     29     // /**
     30     //  * Break point in digits (number of {@code int} elements)
     31     //  * between Karatsuba and Pencil and Paper multiply.
     32     //  */
     33     // static final int whenUseKaratsuba = 63; // an heuristic value
     34     // END android-removed
     35 
     36     /**
     37      * An array with powers of ten that fit in the type {@code int}.
     38      * ({@code 10^0,10^1,...,10^9})
     39      */
     40     static final int[] tenPows = {
     41         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
     42     };
     43 
     44     /**
     45      * An array with powers of five that fit in the type {@code int}.
     46      * ({@code 5^0,5^1,...,5^13})
     47      */
     48     static final int[] fivePows = {
     49         1, 5, 25, 125, 625, 3125, 15625, 78125, 390625,
     50         1953125, 9765625, 48828125, 244140625, 1220703125
     51     };
     52 
     53     /**
     54      * An array with the first powers of ten in {@code BigInteger} version.
     55      * ({@code 10^0,10^1,...,10^31})
     56      */
     57     static final BigInteger[] bigTenPows = new BigInteger[32];
     58 
     59     /**
     60      * An array with the first powers of five in {@code BigInteger} version.
     61      * ({@code 5^0,5^1,...,5^31})
     62      */
     63     static final BigInteger bigFivePows[] = new BigInteger[32];
     64 
     65 
     66 
     67     static {
     68         int i;
     69         long fivePow = 1L;
     70 
     71         for (i = 0; i <= 18; i++) {
     72             bigFivePows[i] = BigInteger.valueOf(fivePow);
     73             bigTenPows[i] = BigInteger.valueOf(fivePow << i);
     74             fivePow *= 5;
     75         }
     76         for (; i < bigTenPows.length; i++) {
     77             bigFivePows[i] = bigFivePows[i - 1].multiply(bigFivePows[1]);
     78             bigTenPows[i] = bigTenPows[i - 1].multiply(BigInteger.TEN);
     79         }
     80     }
     81 
     82     // BEGIN android-note: multiply has been removed in favor of using OpenSSL BIGNUM
     83     // END android-note
     84 
     85     /**
     86      * Multiplies a number by a positive integer.
     87      * @param val an arbitrary {@code BigInteger}
     88      * @param factor a positive {@code int} number
     89      * @return {@code val * factor}
     90      */
     91     static BigInteger multiplyByPositiveInt(BigInteger val, int factor) {
     92         BigInt bi = val.getBigInt().copy();
     93         bi.multiplyByPositiveInt(factor);
     94         return new BigInteger(bi);
     95     }
     96 
     97     /**
     98      * Multiplies a number by a power of ten.
     99      * This method is used in {@code BigDecimal} class.
    100      * @param val the number to be multiplied
    101      * @param exp a positive {@code long} exponent
    102      * @return {@code val * 10<sup>exp</sup>}
    103      */
    104     static BigInteger multiplyByTenPow(BigInteger val, long exp) {
    105         // PRE: exp >= 0
    106         return ((exp < tenPows.length)
    107         ? multiplyByPositiveInt(val, tenPows[(int)exp])
    108         : val.multiply(powerOf10(exp)));
    109     }
    110 
    111     /**
    112      * It calculates a power of ten, which exponent could be out of 32-bit range.
    113      * Note that internally this method will be used in the worst case with
    114      * an exponent equals to: {@code Integer.MAX_VALUE - Integer.MIN_VALUE}.
    115      * @param exp the exponent of power of ten, it must be positive.
    116      * @return a {@code BigInteger} with value {@code 10<sup>exp</sup>}.
    117      */
    118     static BigInteger powerOf10(long exp) {
    119         // PRE: exp >= 0
    120         int intExp = (int)exp;
    121         // "SMALL POWERS"
    122         if (exp < bigTenPows.length) {
    123             // The largest power that fit in 'long' type
    124             return bigTenPows[intExp];
    125         } else if (exp <= 50) {
    126             // To calculate:    10^exp
    127             return BigInteger.TEN.pow(intExp);
    128         } else if (exp <= 1000) {
    129             // To calculate:    5^exp * 2^exp
    130             return bigFivePows[1].pow(intExp).shiftLeft(intExp);
    131         }
    132         // "LARGE POWERS"
    133         /*
    134          * To check if there is free memory to allocate a BigInteger of the
    135          * estimated size, measured in bytes: 1 + [exp / log10(2)]
    136          */
    137         long byteArraySize = 1 + (long)(exp / 2.4082399653118496);
    138 
    139         if (byteArraySize > Runtime.getRuntime().freeMemory()) {
    140             throw new ArithmeticException();
    141         }
    142         if (exp <= Integer.MAX_VALUE) {
    143             // To calculate:    5^exp * 2^exp
    144             return bigFivePows[1].pow(intExp).shiftLeft(intExp);
    145         }
    146         /*
    147          * "HUGE POWERS"
    148          *
    149          * This branch probably won't be executed since the power of ten is too
    150          * big.
    151          */
    152         // To calculate:    5^exp
    153         BigInteger powerOfFive = bigFivePows[1].pow(Integer.MAX_VALUE);
    154         BigInteger res = powerOfFive;
    155         long longExp = exp - Integer.MAX_VALUE;
    156 
    157         intExp = (int)(exp % Integer.MAX_VALUE);
    158         while (longExp > Integer.MAX_VALUE) {
    159             res = res.multiply(powerOfFive);
    160             longExp -= Integer.MAX_VALUE;
    161         }
    162         res = res.multiply(bigFivePows[1].pow(intExp));
    163         // To calculate:    5^exp << exp
    164         res = res.shiftLeft(Integer.MAX_VALUE);
    165         longExp = exp - Integer.MAX_VALUE;
    166         while (longExp > Integer.MAX_VALUE) {
    167             res = res.shiftLeft(Integer.MAX_VALUE);
    168             longExp -= Integer.MAX_VALUE;
    169         }
    170         res = res.shiftLeft(intExp);
    171         return res;
    172     }
    173 
    174     /**
    175      * Multiplies a number by a power of five.
    176      * This method is used in {@code BigDecimal} class.
    177      * @param val the number to be multiplied
    178      * @param exp a positive {@code int} exponent
    179      * @return {@code val * 5<sup>exp</sup>}
    180      */
    181     static BigInteger multiplyByFivePow(BigInteger val, int exp) {
    182         // PRE: exp >= 0
    183         if (exp < fivePows.length) {
    184             return multiplyByPositiveInt(val, fivePows[exp]);
    185         } else if (exp < bigFivePows.length) {
    186             return val.multiply(bigFivePows[exp]);
    187         } else {// Large powers of five
    188             return val.multiply(bigFivePows[1].pow(exp));
    189         }
    190     }
    191 }
    192