Path: blob/master/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java
41159 views
/*1* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package jdk.internal.math;2526import jdk.internal.misc.CDS;2728import java.math.BigInteger;29import java.util.Arrays;30//@ model import org.jmlspecs.models.JMLMath;3132/**33* A simple big integer package specifically for floating point base conversion.34*/35public /*@ spec_bigint_math @*/ class FDBigInteger {3637//38// This class contains many comments that start with "/*@" mark.39// They are behavourial specification in40// the Java Modelling Language (JML):41// http://www.eecs.ucf.edu/~leavens/JML//index.shtml42//4344/*@45@ public pure model static \bigint UNSIGNED(int v) {46@ return v >= 0 ? v : v + (((\bigint)1) << 32);47@ }48@49@ public pure model static \bigint UNSIGNED(long v) {50@ return v >= 0 ? v : v + (((\bigint)1) << 64);51@ }52@53@ public pure model static \bigint AP(int[] data, int len) {54@ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));55@ }56@57@ public pure model static \bigint pow52(int p5, int p2) {58@ ghost \bigint v = 1;59@ for (int i = 0; i < p5; i++) v *= 5;60@ return v << p2;61@ }62@63@ public pure model static \bigint pow10(int p10) {64@ return pow52(p10, p10);65@ }66@*/6768static final int[] SMALL_5_POW;6970static final long[] LONG_5_POW;7172// Maximum size of cache of powers of 5 as FDBigIntegers.73private static final int MAX_FIVE_POW = 340;7475// Cache of big powers of 5 as FDBigIntegers.76private static final FDBigInteger POW_5_CACHE[];7778// Zero as an FDBigInteger.79public static final FDBigInteger ZERO;8081// Archive proxy82private static Object[] archivedCaches;8384// Initialize FDBigInteger cache of powers of 5.85static {86CDS.initializeFromArchive(FDBigInteger.class);87Object[] caches = archivedCaches;88if (caches == null) {89long[] long5pow = {901L,915L,925L * 5,935L * 5 * 5,945L * 5 * 5 * 5,955L * 5 * 5 * 5 * 5,965L * 5 * 5 * 5 * 5 * 5,975L * 5 * 5 * 5 * 5 * 5 * 5,985L * 5 * 5 * 5 * 5 * 5 * 5 * 5,995L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1005L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1015L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1025L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1035L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1045L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1055L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1065L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1075L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1085L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1095L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1105L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1115L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1125L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1135L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1145L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1155L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1165L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,117};118int[] small5pow = {1191,1205,1215 * 5,1225 * 5 * 5,1235 * 5 * 5 * 5,1245 * 5 * 5 * 5 * 5,1255 * 5 * 5 * 5 * 5 * 5,1265 * 5 * 5 * 5 * 5 * 5 * 5,1275 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1285 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1295 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1305 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1315 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,1325 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5133};134FDBigInteger[] pow5cache = new FDBigInteger[MAX_FIVE_POW];135int i = 0;136while (i < small5pow.length) {137FDBigInteger pow5 = new FDBigInteger(new int[] { small5pow[i] }, 0);138pow5.makeImmutable();139pow5cache[i] = pow5;140i++;141}142FDBigInteger prev = pow5cache[i - 1];143while (i < MAX_FIVE_POW) {144pow5cache[i] = prev = prev.mult(5);145prev.makeImmutable();146i++;147}148FDBigInteger zero = new FDBigInteger(new int[0], 0);149zero.makeImmutable();150archivedCaches = caches = new Object[] {small5pow, long5pow, pow5cache, zero};151}152SMALL_5_POW = (int[])caches[0];153LONG_5_POW = (long[])caches[1];154POW_5_CACHE = (FDBigInteger[])caches[2];155ZERO = (FDBigInteger)caches[3];156}157158// Constant for casting an int to a long via bitwise AND.159private static final long LONG_MASK = 0xffffffffL;160161//@ spec_public non_null;162private int data[]; // value: data[0] is least significant163//@ spec_public;164private int offset; // number of least significant zero padding ints165//@ spec_public;166private int nWords; // data[nWords-1]!=0, all values above are zero167// if nWords==0 -> this FDBigInteger is zero168//@ spec_public;169private boolean isImmutable = false;170171/*@172@ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;173@ public invariant nWords == 0 ==> offset == 0;174@ public invariant nWords > 0 ==> data[nWords - 1] != 0;175@ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);176@ public pure model \bigint value() {177@ return AP(data, nWords) << (offset*32);178@ }179@*/180181/**182* Constructs an <code>FDBigInteger</code> from data and padding. The183* <code>data</code> parameter has the least significant <code>int</code> at184* the zeroth index. The <code>offset</code> parameter gives the number of185* zero <code>int</code>s to be inferred below the least significant element186* of <code>data</code>.187*188* @param data An array containing all non-zero <code>int</code>s of the value.189* @param offset An offset indicating the number of zero <code>int</code>s to pad190* below the least significant element of <code>data</code>.191*/192/*@193@ requires data != null && offset >= 0;194@ ensures this.value() == \old(AP(data, data.length) << (offset*32));195@ ensures this.data == \old(data);196@*/197private FDBigInteger(int[] data, int offset) {198this.data = data;199this.offset = offset;200this.nWords = data.length;201trimLeadingZeros();202}203204/**205* Constructs an <code>FDBigInteger</code> from a starting value and some206* decimal digits.207*208* @param lValue The starting value.209* @param digits The decimal digits.210* @param kDigits The initial index into <code>digits</code>.211* @param nDigits The final index into <code>digits</code>.212*/213/*@214@ requires digits != null;215@ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;216@ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');217@ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));218@*/219public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {220int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.221data = new int[n]; // allocate enough space222data[0] = (int) lValue; // starting value223data[1] = (int) (lValue >>> 32);224offset = 0;225nWords = 2;226int i = kDigits;227int limit = nDigits - 5; // slurp digits 5 at a time.228int v;229while (i < limit) {230int ilim = i + 5;231v = (int) digits[i++] - (int) '0';232while (i < ilim) {233v = 10 * v + (int) digits[i++] - (int) '0';234}235multAddMe(100000, v); // ... where 100000 is 10^5.236}237int factor = 1;238v = 0;239while (i < nDigits) {240v = 10 * v + (int) digits[i++] - (int) '0';241factor *= 10;242}243if (factor != 1) {244multAddMe(factor, v);245}246trimLeadingZeros();247}248249/**250* Returns an <code>FDBigInteger</code> with the numerical value251* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.252*253* @param p5 The exponent of the power-of-five factor.254* @param p2 The exponent of the power-of-two factor.255* @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>256*/257/*@258@ requires p5 >= 0 && p2 >= 0;259@ assignable \nothing;260@ ensures \result.value() == \old(pow52(p5, p2));261@*/262public static FDBigInteger valueOfPow52(int p5, int p2) {263if (p5 != 0) {264if (p2 == 0) {265return big5pow(p5);266} else if (p5 < SMALL_5_POW.length) {267int pow5 = SMALL_5_POW[p5];268int wordcount = p2 >> 5;269int bitcount = p2 & 0x1f;270if (bitcount == 0) {271return new FDBigInteger(new int[]{pow5}, wordcount);272} else {273return new FDBigInteger(new int[]{274pow5 << bitcount,275pow5 >>> (32 - bitcount)276}, wordcount);277}278} else {279return big5pow(p5).leftShift(p2);280}281} else {282return valueOfPow2(p2);283}284}285286/**287* Returns an <code>FDBigInteger</code> with the numerical value288* <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.289*290* @param value The constant factor.291* @param p5 The exponent of the power-of-five factor.292* @param p2 The exponent of the power-of-two factor.293* @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>294*/295/*@296@ requires p5 >= 0 && p2 >= 0;297@ assignable \nothing;298@ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));299@*/300public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {301assert p5 >= 0 : p5;302assert p2 >= 0 : p2;303int v0 = (int) value;304int v1 = (int) (value >>> 32);305int wordcount = p2 >> 5;306int bitcount = p2 & 0x1f;307if (p5 != 0) {308if (p5 < SMALL_5_POW.length) {309long pow5 = SMALL_5_POW[p5] & LONG_MASK;310long carry = (v0 & LONG_MASK) * pow5;311v0 = (int) carry;312carry >>>= 32;313carry = (v1 & LONG_MASK) * pow5 + carry;314v1 = (int) carry;315int v2 = (int) (carry >>> 32);316if (bitcount == 0) {317return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);318} else {319return new FDBigInteger(new int[]{320v0 << bitcount,321(v1 << bitcount) | (v0 >>> (32 - bitcount)),322(v2 << bitcount) | (v1 >>> (32 - bitcount)),323v2 >>> (32 - bitcount)324}, wordcount);325}326} else {327FDBigInteger pow5 = big5pow(p5);328int[] r;329if (v1 == 0) {330r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];331mult(pow5.data, pow5.nWords, v0, r);332} else {333r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];334mult(pow5.data, pow5.nWords, v0, v1, r);335}336return (new FDBigInteger(r, pow5.offset)).leftShift(p2);337}338} else if (p2 != 0) {339if (bitcount == 0) {340return new FDBigInteger(new int[]{v0, v1}, wordcount);341} else {342return new FDBigInteger(new int[]{343v0 << bitcount,344(v1 << bitcount) | (v0 >>> (32 - bitcount)),345v1 >>> (32 - bitcount)346}, wordcount);347}348}349return new FDBigInteger(new int[]{v0, v1}, 0);350}351352/**353* Returns an <code>FDBigInteger</code> with the numerical value354* <code>2<sup>p2</sup></code>.355*356* @param p2 The exponent of 2.357* @return <code>2<sup>p2</sup></code>358*/359/*@360@ requires p2 >= 0;361@ assignable \nothing;362@ ensures \result.value() == pow52(0, p2);363@*/364private static FDBigInteger valueOfPow2(int p2) {365int wordcount = p2 >> 5;366int bitcount = p2 & 0x1f;367return new FDBigInteger(new int[]{1 << bitcount}, wordcount);368}369370/**371* Removes all leading zeros from this <code>FDBigInteger</code> adjusting372* the offset and number of non-zero leading words accordingly.373*/374/*@375@ requires data != null;376@ requires 0 <= nWords && nWords <= data.length && offset >= 0;377@ requires nWords == 0 ==> offset == 0;378@ ensures nWords == 0 ==> offset == 0;379@ ensures nWords > 0 ==> data[nWords - 1] != 0;380@*/381private /*@ helper @*/ void trimLeadingZeros() {382int i = nWords;383if (i > 0 && (data[--i] == 0)) {384//for (; i > 0 && data[i - 1] == 0; i--) ;385while(i > 0 && data[i - 1] == 0) {386i--;387}388this.nWords = i;389if (i == 0) { // all words are zero390this.offset = 0;391}392}393}394395/**396* Retrieves the normalization bias of the <code>FDBigIntger</code>. The397* normalization bias is a left shift such that after it the highest word398* of the value will have the 4 highest bits equal to zero:399* {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1400* {@code (highestWord & 0x08000000) != 0}.401*402* @return The normalization bias.403*/404/*@405@ requires this.value() > 0;406@*/407public /*@ pure @*/ int getNormalizationBias() {408if (nWords == 0) {409throw new IllegalArgumentException("Zero value cannot be normalized");410}411int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);412return (zeros < 4) ? 28 + zeros : zeros - 4;413}414415// TODO: Why is anticount param needed if it is always 32 - bitcount?416/**417* Left shifts the contents of one int array into another.418*419* @param src The source array.420* @param idx The initial index of the source array.421* @param result The destination array.422* @param bitcount The left shift.423* @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.424* @param prev The prior source value.425*/426/*@427@ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;428@ requires src.length >= idx && result.length > idx;429@ assignable result[*];430@ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);431@*/432private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){433for (; idx > 0; idx--) {434int v = (prev << bitcount);435prev = src[idx - 1];436v |= (prev >>> anticount);437result[idx] = v;438}439int v = prev << bitcount;440result[0] = v;441}442443/**444* Shifts this <code>FDBigInteger</code> to the left. The shift is performed445* in-place unless the <code>FDBigInteger</code> is immutable in which case446* a new instance of <code>FDBigInteger</code> is returned.447*448* @param shift The number of bits to shift left.449* @return The shifted <code>FDBigInteger</code>.450*/451/*@452@ requires this.value() == 0 || shift == 0;453@ assignable \nothing;454@ ensures \result == this;455@456@ also457@458@ requires this.value() > 0 && shift > 0 && this.isImmutable;459@ assignable \nothing;460@ ensures \result.value() == \old(this.value() << shift);461@462@ also463@464@ requires this.value() > 0 && shift > 0 && this.isImmutable;465@ assignable \nothing;466@ ensures \result == this;467@ ensures \result.value() == \old(this.value() << shift);468@*/469public FDBigInteger leftShift(int shift) {470if (shift == 0 || nWords == 0) {471return this;472}473int wordcount = shift >> 5;474int bitcount = shift & 0x1f;475if (this.isImmutable) {476if (bitcount == 0) {477return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);478} else {479int anticount = 32 - bitcount;480int idx = nWords - 1;481int prev = data[idx];482int hi = prev >>> anticount;483int[] result;484if (hi != 0) {485result = new int[nWords + 1];486result[nWords] = hi;487} else {488result = new int[nWords];489}490leftShift(data,idx,result,bitcount,anticount,prev);491return new FDBigInteger(result, offset + wordcount);492}493} else {494if (bitcount != 0) {495int anticount = 32 - bitcount;496if ((data[0] << bitcount) == 0) {497int idx = 0;498int prev = data[idx];499for (; idx < nWords - 1; idx++) {500int v = (prev >>> anticount);501prev = data[idx + 1];502v |= (prev << bitcount);503data[idx] = v;504}505int v = prev >>> anticount;506data[idx] = v;507if(v==0) {508nWords--;509}510offset++;511} else {512int idx = nWords - 1;513int prev = data[idx];514int hi = prev >>> anticount;515int[] result = data;516int[] src = data;517if (hi != 0) {518if(nWords == data.length) {519data = result = new int[nWords + 1];520}521result[nWords++] = hi;522}523leftShift(src,idx,result,bitcount,anticount,prev);524}525}526offset += wordcount;527return this;528}529}530531/**532* Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.533*534* @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.535*/536/*@537@ requires this.value() == 0;538@ ensures \result == 0;539@540@ also541@542@ requires this.value() > 0;543@ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;544@*/545private /*@ pure @*/ int size() {546return nWords + offset;547}548549550/**551* Computes552* <pre>553* q = (int)( this / S )554* this = 10 * ( this mod S )555* Return q.556* </pre>557* This is the iteration step of digit development for output.558* We assume that S has been normalized, as above, and that559* "this" has been left-shifted accordingly.560* Also assumed, of course, is that the result, q, can be expressed561* as an integer, {@code 0 <= q < 10}.562*563* @param S The divisor of this <code>FDBigInteger</code>.564* @return <code>q = (int)(this / S)</code>.565*/566/*@567@ requires !this.isImmutable;568@ requires this.size() <= S.size();569@ requires this.data.length + this.offset >= S.size();570@ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);571@ assignable this.nWords, this.offset, this.data, this.data[*];572@ ensures \result == \old(this.value() / S.value());573@ ensures this.value() == \old(10 * (this.value() % S.value()));574@*/575public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {576assert !this.isImmutable : "cannot modify immutable value";577// ensure that this and S have the same number of578// digits. If S is properly normalized and q < 10 then579// this must be so.580int thSize = this.size();581int sSize = S.size();582if (thSize < sSize) {583// this value is significantly less than S, result of division is zero.584// just mult this by 10.585int p = multAndCarryBy10(this.data, this.nWords, this.data);586if(p!=0) {587this.data[nWords++] = p;588} else {589trimLeadingZeros();590}591return 0;592} else if (thSize > sSize) {593throw new IllegalArgumentException("disparate values");594}595// estimate q the obvious way. We will usually be596// right. If not, then we're only off by a little and597// will re-add.598long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);599long diff = multDiffMe(q, S);600if (diff != 0L) {601//@ assert q != 0;602//@ assert this.offset == \old(Math.min(this.offset, S.offset));603//@ assert this.offset <= S.offset;604605// q is too big.606// add S back in until this turns +. This should607// not be very many times!608long sum = 0L;609int tStart = S.offset - this.offset;610//@ assert tStart >= 0;611int[] sd = S.data;612int[] td = this.data;613while (sum == 0L) {614for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {615sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);616td[tIndex] = (int) sum;617sum >>>= 32; // Signed or unsigned, answer is 0 or 1618}619//620// Originally the following line read621// "if ( sum !=0 && sum != -1 )"622// but that would be wrong, because of the623// treatment of the two values as entirely unsigned,624// it would be impossible for a carry-out to be interpreted625// as -1 -- it would have to be a single-bit carry-out, or +1.626//627assert sum == 0 || sum == 1 : sum; // carry out of division correction628q -= 1;629}630}631// finally, we can multiply this by 10.632// it cannot overflow, right, as the high-order word has633// at least 4 high-order zeros!634int p = multAndCarryBy10(this.data, this.nWords, this.data);635assert p == 0 : p; // Carry out of *10636trimLeadingZeros();637return (int) q;638}639640/**641* Multiplies this <code>FDBigInteger</code> by 10. The operation will be642* performed in place unless the <code>FDBigInteger</code> is immutable in643* which case a new <code>FDBigInteger</code> will be returned.644*645* @return The <code>FDBigInteger</code> multiplied by 10.646*/647/*@648@ requires this.value() == 0;649@ assignable \nothing;650@ ensures \result == this;651@652@ also653@654@ requires this.value() > 0 && this.isImmutable;655@ assignable \nothing;656@ ensures \result.value() == \old(this.value() * 10);657@658@ also659@660@ requires this.value() > 0 && !this.isImmutable;661@ assignable this.nWords, this.data, this.data[*];662@ ensures \result == this;663@ ensures \result.value() == \old(this.value() * 10);664@*/665public FDBigInteger multBy10() {666if (nWords == 0) {667return this;668}669if (isImmutable) {670int[] res = new int[nWords + 1];671res[nWords] = multAndCarryBy10(data, nWords, res);672return new FDBigInteger(res, offset);673} else {674int p = multAndCarryBy10(this.data, this.nWords, this.data);675if (p != 0) {676if (nWords == data.length) {677if (data[0] == 0) {678System.arraycopy(data, 1, data, 0, --nWords);679offset++;680} else {681data = Arrays.copyOf(data, data.length + 1);682}683}684data[nWords++] = p;685} else {686trimLeadingZeros();687}688return this;689}690}691692/**693* Multiplies this <code>FDBigInteger</code> by694* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be695* performed in place if possible, otherwise a new <code>FDBigInteger</code>696* will be returned.697*698* @param p5 The exponent of the power-of-five factor.699* @param p2 The exponent of the power-of-two factor.700* @return The multiplication result.701*/702/*@703@ requires this.value() == 0 || p5 == 0 && p2 == 0;704@ assignable \nothing;705@ ensures \result == this;706@707@ also708@709@ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);710@ assignable \nothing;711@ ensures \result.value() == \old(this.value() * pow52(p5, p2));712@713@ also714@715@ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;716@ assignable this.nWords, this.data, this.data[*];717@ ensures \result == this;718@ ensures \result.value() == \old(this.value() * pow52(p5, p2));719@*/720public FDBigInteger multByPow52(int p5, int p2) {721if (this.nWords == 0) {722return this;723}724FDBigInteger res = this;725if (p5 != 0) {726int[] r;727int extraSize = (p2 != 0) ? 1 : 0;728if (p5 < SMALL_5_POW.length) {729r = new int[this.nWords + 1 + extraSize];730mult(this.data, this.nWords, SMALL_5_POW[p5], r);731res = new FDBigInteger(r, this.offset);732} else {733FDBigInteger pow5 = big5pow(p5);734r = new int[this.nWords + pow5.size() + extraSize];735mult(this.data, this.nWords, pow5.data, pow5.nWords, r);736res = new FDBigInteger(r, this.offset + pow5.offset);737}738}739return res.leftShift(p2);740}741742/**743* Multiplies two big integers represented as int arrays.744*745* @param s1 The first array factor.746* @param s1Len The number of elements of <code>s1</code> to use.747* @param s2 The second array factor.748* @param s2Len The number of elements of <code>s2</code> to use.749* @param dst The product array.750*/751/*@752@ requires s1 != dst && s2 != dst;753@ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;754@ assignable dst[0 .. s1Len + s2Len - 1];755@ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));756@*/757private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {758for (int i = 0; i < s1Len; i++) {759long v = s1[i] & LONG_MASK;760long p = 0L;761for (int j = 0; j < s2Len; j++) {762p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);763dst[i + j] = (int) p;764p >>>= 32;765}766dst[i + s2Len] = (int) p;767}768}769770/**771* Subtracts the supplied <code>FDBigInteger</code> subtrahend from this772* <code>FDBigInteger</code>. Assert that the result is positive.773* If the subtrahend is immutable, store the result in this(minuend).774* If this(minuend) is immutable a new <code>FDBigInteger</code> is created.775*776* @param subtrahend The <code>FDBigInteger</code> to be subtracted.777* @return This <code>FDBigInteger</code> less the subtrahend.778*/779/*@780@ requires this.isImmutable;781@ requires this.value() >= subtrahend.value();782@ assignable \nothing;783@ ensures \result.value() == \old(this.value() - subtrahend.value());784@785@ also786@787@ requires !subtrahend.isImmutable;788@ requires this.value() >= subtrahend.value();789@ assignable this.nWords, this.offset, this.data, this.data[*];790@ ensures \result == this;791@ ensures \result.value() == \old(this.value() - subtrahend.value());792@*/793public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {794assert this.size() >= subtrahend.size() : "result should be positive";795FDBigInteger minuend;796if (this.isImmutable) {797minuend = new FDBigInteger(this.data.clone(), this.offset);798} else {799minuend = this;800}801int offsetDiff = subtrahend.offset - minuend.offset;802int[] sData = subtrahend.data;803int[] mData = minuend.data;804int subLen = subtrahend.nWords;805int minLen = minuend.nWords;806if (offsetDiff < 0) {807// need to expand minuend808int rLen = minLen - offsetDiff;809if (rLen < mData.length) {810System.arraycopy(mData, 0, mData, -offsetDiff, minLen);811Arrays.fill(mData, 0, -offsetDiff, 0);812} else {813int[] r = new int[rLen];814System.arraycopy(mData, 0, r, -offsetDiff, minLen);815minuend.data = mData = r;816}817minuend.offset = subtrahend.offset;818minuend.nWords = minLen = rLen;819offsetDiff = 0;820}821long borrow = 0L;822int mIndex = offsetDiff;823for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {824long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;825mData[mIndex] = (int) diff;826borrow = diff >> 32; // signed shift827}828for (; borrow != 0 && mIndex < minLen; mIndex++) {829long diff = (mData[mIndex] & LONG_MASK) + borrow;830mData[mIndex] = (int) diff;831borrow = diff >> 32; // signed shift832}833assert borrow == 0L : borrow; // borrow out of subtract,834// result should be positive835minuend.trimLeadingZeros();836return minuend;837}838839/**840* Subtracts the supplied <code>FDBigInteger</code> subtrahend from this841* <code>FDBigInteger</code>. Assert that the result is positive.842* If the this(minuend) is immutable, store the result in subtrahend.843* If subtrahend is immutable a new <code>FDBigInteger</code> is created.844*845* @param subtrahend The <code>FDBigInteger</code> to be subtracted.846* @return This <code>FDBigInteger</code> less the subtrahend.847*/848/*@849@ requires subtrahend.isImmutable;850@ requires this.value() >= subtrahend.value();851@ assignable \nothing;852@ ensures \result.value() == \old(this.value() - subtrahend.value());853@854@ also855@856@ requires !subtrahend.isImmutable;857@ requires this.value() >= subtrahend.value();858@ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];859@ ensures \result == subtrahend;860@ ensures \result.value() == \old(this.value() - subtrahend.value());861@*/862public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {863assert this.size() >= subtrahend.size() : "result should be positive";864FDBigInteger minuend = this;865if (subtrahend.isImmutable) {866subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);867}868int offsetDiff = minuend.offset - subtrahend.offset;869int[] sData = subtrahend.data;870int[] mData = minuend.data;871int subLen = subtrahend.nWords;872int minLen = minuend.nWords;873if (offsetDiff < 0) {874int rLen = minLen;875if (rLen < sData.length) {876System.arraycopy(sData, 0, sData, -offsetDiff, subLen);877Arrays.fill(sData, 0, -offsetDiff, 0);878} else {879int[] r = new int[rLen];880System.arraycopy(sData, 0, r, -offsetDiff, subLen);881subtrahend.data = sData = r;882}883subtrahend.offset = minuend.offset;884subLen -= offsetDiff;885offsetDiff = 0;886} else {887int rLen = minLen + offsetDiff;888if (rLen >= sData.length) {889subtrahend.data = sData = Arrays.copyOf(sData, rLen);890}891}892//@ assert minuend == this && minuend.value() == \old(this.value());893//@ assert mData == minuend.data && minLen == minuend.nWords;894//@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();895//@ assert sData == subtrahend.data;896//@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());897//@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);898//@ assert offsetDiff == minuend.offset - subtrahend.offset;899//@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;900int sIndex = 0;901long borrow = 0L;902for (; sIndex < offsetDiff; sIndex++) {903long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;904sData[sIndex] = (int) diff;905borrow = diff >> 32; // signed shift906}907//@ assert sIndex == offsetDiff;908for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {909//@ assert sIndex == offsetDiff + mIndex;910long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;911sData[sIndex] = (int) diff;912borrow = diff >> 32; // signed shift913}914assert borrow == 0L : borrow; // borrow out of subtract,915// result should be positive916subtrahend.nWords = sIndex;917subtrahend.trimLeadingZeros();918return subtrahend;919920}921922/**923* Determines whether all elements of an array are zero for all indices less924* than a given index.925*926* @param a The array to be examined.927* @param from The index strictly below which elements are to be examined.928* @return Zero if all elements in range are zero, 1 otherwise.929*/930/*@931@ requires 0 <= from && from <= a.length;932@ ensures \result == (AP(a, from) == 0 ? 0 : 1);933@*/934private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {935while (from > 0) {936if (a[--from] != 0) {937return 1;938}939}940return 0;941}942943/**944* Compares the parameter with this <code>FDBigInteger</code>. Returns an945* integer accordingly as:946* <pre>{@code947* > 0: this > other948* 0: this == other949* < 0: this < other950* }</pre>951*952* @param other The <code>FDBigInteger</code> to compare.953* @return A negative value, zero, or a positive value according to the954* result of the comparison.955*/956/*@957@ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);958@*/959public /*@ pure @*/ int cmp(FDBigInteger other) {960int aSize = nWords + offset;961int bSize = other.nWords + other.offset;962if (aSize > bSize) {963return 1;964} else if (aSize < bSize) {965return -1;966}967int aLen = nWords;968int bLen = other.nWords;969while (aLen > 0 && bLen > 0) {970int a = data[--aLen];971int b = other.data[--bLen];972if (a != b) {973return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;974}975}976if (aLen > 0) {977return checkZeroTail(data, aLen);978}979if (bLen > 0) {980return -checkZeroTail(other.data, bLen);981}982return 0;983}984985/**986* Compares this <code>FDBigInteger</code> with987* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.988* Returns an integer accordingly as:989* <pre>{@code990* > 0: this > other991* 0: this == other992* < 0: this < other993* }</pre>994* @param p5 The exponent of the power-of-five factor.995* @param p2 The exponent of the power-of-two factor.996* @return A negative value, zero, or a positive value according to the997* result of the comparison.998*/999/*@1000@ requires p5 >= 0 && p2 >= 0;1001@ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);1002@*/1003public /*@ pure @*/ int cmpPow52(int p5, int p2) {1004if (p5 == 0) {1005int wordcount = p2 >> 5;1006int bitcount = p2 & 0x1f;1007int size = this.nWords + this.offset;1008if (size > wordcount + 1) {1009return 1;1010} else if (size < wordcount + 1) {1011return -1;1012}1013int a = this.data[this.nWords -1];1014int b = 1 << bitcount;1015if (a != b) {1016return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;1017}1018return checkZeroTail(this.data, this.nWords - 1);1019}1020return this.cmp(big5pow(p5).leftShift(p2));1021}10221023/**1024* Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a1025* value according to the comparison as:1026* <pre>{@code1027* -1: this < x + y1028* 0: this == x + y1029* 1: this > x + y1030* }</pre>1031* @param x The first addend of the sum to compare.1032* @param y The second addend of the sum to compare.1033* @return -1, 0, or 1 according to the result of the comparison.1034*/1035/*@1036@ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);1037@*/1038public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {1039FDBigInteger big;1040FDBigInteger small;1041int xSize = x.size();1042int ySize = y.size();1043int bSize;1044int sSize;1045if (xSize >= ySize) {1046big = x;1047small = y;1048bSize = xSize;1049sSize = ySize;1050} else {1051big = y;1052small = x;1053bSize = ySize;1054sSize = xSize;1055}1056int thSize = this.size();1057if (bSize == 0) {1058return thSize == 0 ? 0 : 1;1059}1060if (sSize == 0) {1061return this.cmp(big);1062}1063if (bSize > thSize) {1064return -1;1065}1066if (bSize + 1 < thSize) {1067return 1;1068}1069long top = (big.data[big.nWords - 1] & LONG_MASK);1070if (sSize == bSize) {1071top += (small.data[small.nWords - 1] & LONG_MASK);1072}1073if ((top >>> 32) == 0) {1074if (((top + 1) >>> 32) == 0) {1075// good case - no carry extension1076if (bSize < thSize) {1077return 1;1078}1079// here sum.nWords == this.nWords1080long v = (this.data[this.nWords - 1] & LONG_MASK);1081if (v < top) {1082return -1;1083}1084if (v > top + 1) {1085return 1;1086}1087}1088} else { // (top>>>32)!=0 guaranteed carry extension1089if (bSize + 1 > thSize) {1090return -1;1091}1092// here sum.nWords == this.nWords1093top >>>= 32;1094long v = (this.data[this.nWords - 1] & LONG_MASK);1095if (v < top) {1096return -1;1097}1098if (v > top + 1) {1099return 1;1100}1101}1102return this.cmp(big.add(small));1103}11041105/**1106* Makes this <code>FDBigInteger</code> immutable.1107*/1108/*@1109@ assignable this.isImmutable;1110@ ensures this.isImmutable;1111@*/1112public void makeImmutable() {1113this.isImmutable = true;1114}11151116/**1117* Multiplies this <code>FDBigInteger</code> by an integer.1118*1119* @param i The factor by which to multiply this <code>FDBigInteger</code>.1120* @return This <code>FDBigInteger</code> multiplied by an integer.1121*/1122/*@1123@ requires this.value() == 0;1124@ assignable \nothing;1125@ ensures \result == this;1126@1127@ also1128@1129@ requires this.value() != 0;1130@ assignable \nothing;1131@ ensures \result.value() == \old(this.value() * UNSIGNED(i));1132@*/1133private FDBigInteger mult(int i) {1134if (this.nWords == 0) {1135return this;1136}1137int[] r = new int[nWords + 1];1138mult(data, nWords, i, r);1139return new FDBigInteger(r, offset);1140}11411142/**1143* Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.1144*1145* @param other The <code>FDBigInteger</code> factor by which to multiply.1146* @return The product of this and the parameter <code>FDBigInteger</code>s.1147*/1148/*@1149@ requires this.value() == 0;1150@ assignable \nothing;1151@ ensures \result == this;1152@1153@ also1154@1155@ requires this.value() != 0 && other.value() == 0;1156@ assignable \nothing;1157@ ensures \result == other;1158@1159@ also1160@1161@ requires this.value() != 0 && other.value() != 0;1162@ assignable \nothing;1163@ ensures \result.value() == \old(this.value() * other.value());1164@*/1165private FDBigInteger mult(FDBigInteger other) {1166if (this.nWords == 0) {1167return this;1168}1169if (this.size() == 1) {1170return other.mult(data[0]);1171}1172if (other.nWords == 0) {1173return other;1174}1175if (other.size() == 1) {1176return this.mult(other.data[0]);1177}1178int[] r = new int[nWords + other.nWords];1179mult(this.data, this.nWords, other.data, other.nWords, r);1180return new FDBigInteger(r, this.offset + other.offset);1181}11821183/**1184* Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.1185*1186* @param other The <code>FDBigInteger</code> to add.1187* @return The sum of the <code>FDBigInteger</code>s.1188*/1189/*@1190@ assignable \nothing;1191@ ensures \result.value() == \old(this.value() + other.value());1192@*/1193private FDBigInteger add(FDBigInteger other) {1194FDBigInteger big, small;1195int bigLen, smallLen;1196int tSize = this.size();1197int oSize = other.size();1198if (tSize >= oSize) {1199big = this;1200bigLen = tSize;1201small = other;1202smallLen = oSize;1203} else {1204big = other;1205bigLen = oSize;1206small = this;1207smallLen = tSize;1208}1209int[] r = new int[bigLen + 1];1210int i = 0;1211long carry = 0L;1212for (; i < smallLen; i++) {1213carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )1214+ ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));1215r[i] = (int) carry;1216carry >>= 32; // signed shift.1217}1218for (; i < bigLen; i++) {1219carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );1220r[i] = (int) carry;1221carry >>= 32; // signed shift.1222}1223r[bigLen] = (int) carry;1224return new FDBigInteger(r, 0);1225}122612271228/**1229* Multiplies a <code>FDBigInteger</code> by an int and adds another int. The1230* result is computed in place. This method is intended only to be invoked1231* from1232* <code>1233* FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)1234* </code>.1235*1236* @param iv The factor by which to multiply this <code>FDBigInteger</code>.1237* @param addend The value to add to the product of this1238* <code>FDBigInteger</code> and <code>iv</code>.1239*/1240/*@1241@ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);1242@ assignable this.data[*];1243@ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));1244@*/1245private /*@ helper @*/ void multAddMe(int iv, int addend) {1246long v = iv & LONG_MASK;1247// unroll 0th iteration, doing addition.1248long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);1249data[0] = (int) p;1250p >>>= 32;1251for (int i = 1; i < nWords; i++) {1252p += v * (data[i] & LONG_MASK);1253data[i] = (int) p;1254p >>>= 32;1255}1256if (p != 0L) {1257data[nWords++] = (int) p; // will fail noisily if illegal!1258}1259}12601261//1262// original doc:1263//1264// do this -=q*S1265// returns borrow1266//1267/**1268* Multiplies the parameters and subtracts them from this1269* <code>FDBigInteger</code>.1270*1271* @param q The integer parameter.1272* @param S The <code>FDBigInteger</code> parameter.1273* @return <code>this - q*S</code>.1274*/1275/*@1276@ ensures nWords == 0 ==> offset == 0;1277@ ensures nWords > 0 ==> data[nWords - 1] != 0;1278@*/1279/*@1280@ requires 0 < q && q <= (1L << 31);1281@ requires data != null;1282@ requires 0 <= nWords && nWords <= data.length && offset >= 0;1283@ requires !this.isImmutable;1284@ requires this.size() == S.size();1285@ requires this != S;1286@ assignable this.nWords, this.offset, this.data, this.data[*];1287@ ensures -q <= \result && \result <= 0;1288@ ensures this.size() == \old(this.size());1289@ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());1290@ ensures this.offset == \old(Math.min(this.offset, S.offset));1291@ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);1292@ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);1293@ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);1294@1295@ also1296@1297@ requires q == 0;1298@ assignable \nothing;1299@ ensures \result == 0;1300@*/1301private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {1302long diff = 0L;1303if (q != 0) {1304int deltaSize = S.offset - this.offset;1305if (deltaSize >= 0) {1306int[] sd = S.data;1307int[] td = this.data;1308for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {1309diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);1310td[tIndex] = (int) diff;1311diff >>= 32; // N.B. SIGNED shift.1312}1313} else {1314deltaSize = -deltaSize;1315int[] rd = new int[nWords + deltaSize];1316int sIndex = 0;1317int rIndex = 0;1318int[] sd = S.data;1319for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {1320diff -= q * (sd[sIndex] & LONG_MASK);1321rd[rIndex] = (int) diff;1322diff >>= 32; // N.B. SIGNED shift.1323}1324int tIndex = 0;1325int[] td = this.data;1326for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {1327diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);1328rd[rIndex] = (int) diff;1329diff >>= 32; // N.B. SIGNED shift.1330}1331this.nWords += deltaSize;1332this.offset -= deltaSize;1333this.data = rd;1334}1335}1336return diff;1337}133813391340/**1341* Multiplies by 10 a big integer represented as an array. The final carry1342* is returned.1343*1344* @param src The array representation of the big integer.1345* @param srcLen The number of elements of <code>src</code> to use.1346* @param dst The product array.1347* @return The final carry of the multiplication.1348*/1349/*@1350@ requires src.length >= srcLen && dst.length >= srcLen;1351@ assignable dst[0 .. srcLen - 1];1352@ ensures 0 <= \result && \result < 10;1353@ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);1354@*/1355private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {1356long carry = 0;1357for (int i = 0; i < srcLen; i++) {1358long product = (src[i] & LONG_MASK) * 10L + carry;1359dst[i] = (int) product;1360carry = product >>> 32;1361}1362return (int) carry;1363}13641365/**1366* Multiplies by a constant value a big integer represented as an array.1367* The constant factor is an <code>int</code>.1368*1369* @param src The array representation of the big integer.1370* @param srcLen The number of elements of <code>src</code> to use.1371* @param value The constant factor by which to multiply.1372* @param dst The product array.1373*/1374/*@1375@ requires src.length >= srcLen && dst.length >= srcLen + 1;1376@ assignable dst[0 .. srcLen];1377@ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));1378@*/1379private static void mult(int[] src, int srcLen, int value, int[] dst) {1380long val = value & LONG_MASK;1381long carry = 0;1382for (int i = 0; i < srcLen; i++) {1383long product = (src[i] & LONG_MASK) * val + carry;1384dst[i] = (int) product;1385carry = product >>> 32;1386}1387dst[srcLen] = (int) carry;1388}13891390/**1391* Multiplies by a constant value a big integer represented as an array.1392* The constant factor is a long represent as two <code>int</code>s.1393*1394* @param src The array representation of the big integer.1395* @param srcLen The number of elements of <code>src</code> to use.1396* @param v0 The lower 32 bits of the long factor.1397* @param v1 The upper 32 bits of the long factor.1398* @param dst The product array.1399*/1400/*@1401@ requires src != dst;1402@ requires src.length >= srcLen && dst.length >= srcLen + 2;1403@ assignable dst[0 .. srcLen + 1];1404@ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));1405@*/1406private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {1407long v = v0 & LONG_MASK;1408long carry = 0;1409for (int j = 0; j < srcLen; j++) {1410long product = v * (src[j] & LONG_MASK) + carry;1411dst[j] = (int) product;1412carry = product >>> 32;1413}1414dst[srcLen] = (int) carry;1415v = v1 & LONG_MASK;1416carry = 0;1417for (int j = 0; j < srcLen; j++) {1418long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;1419dst[j + 1] = (int) product;1420carry = product >>> 32;1421}1422dst[srcLen + 1] = (int) carry;1423}14241425// Fails assertion for negative exponent.1426/**1427* Computes <code>5</code> raised to a given power.1428*1429* @param p The exponent of 5.1430* @return <code>5<sup>p</sup></code>.1431*/1432private static FDBigInteger big5pow(int p) {1433assert p >= 0 : p; // negative power of 51434if (p < MAX_FIVE_POW) {1435return POW_5_CACHE[p];1436}1437return big5powRec(p);1438}14391440// slow path1441/**1442* Computes <code>5</code> raised to a given power.1443*1444* @param p The exponent of 5.1445* @return <code>5<sup>p</sup></code>.1446*/1447private static FDBigInteger big5powRec(int p) {1448if (p < MAX_FIVE_POW) {1449return POW_5_CACHE[p];1450}1451// construct the value.1452// recursively.1453int q, r;1454// in order to compute 5^p,1455// compute its square root, 5^(p/2) and square.1456// or, let q = p / 2, r = p -q, then1457// 5^p = 5^(q+r) = 5^q * 5^r1458q = p >> 1;1459r = p - q;1460FDBigInteger bigq = big5powRec(q);1461if (r < SMALL_5_POW.length) {1462return bigq.mult(SMALL_5_POW[r]);1463} else {1464return bigq.mult(big5powRec(r));1465}1466}14671468// for debugging ...1469/**1470* Converts this <code>FDBigInteger</code> to a hexadecimal string.1471*1472* @return The hexadecimal string representation.1473*/1474public String toHexString(){1475if(nWords ==0) {1476return "0";1477}1478StringBuilder sb = new StringBuilder((nWords +offset)*8);1479for(int i= nWords -1; i>=0; i--) {1480String subStr = Integer.toHexString(data[i]);1481for(int j = subStr.length(); j<8; j++) {1482sb.append('0');1483}1484sb.append(subStr);1485}1486for(int i=offset; i>0; i--) {1487sb.append("00000000");1488}1489return sb.toString();1490}14911492// for debugging ...1493/**1494* Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.1495*1496* @return The <code>BigInteger</code> representation.1497*/1498public BigInteger toBigInteger() {1499byte[] magnitude = new byte[nWords * 4 + 1];1500for (int i = 0; i < nWords; i++) {1501int w = data[i];1502magnitude[magnitude.length - 4 * i - 1] = (byte) w;1503magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);1504magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);1505magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);1506}1507return new BigInteger(magnitude).shiftLeft(offset * 32);1508}15091510// for debugging ...1511/**1512* Converts this <code>FDBigInteger</code> to a string.1513*1514* @return The string representation.1515*/1516@Override1517public String toString(){1518return toBigInteger().toString();1519}1520}152115221523