Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java
38839 views
/*1* Copyright (c) 1996, 2013, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223//package sun.misc;2425/*26* A really, really simple bigint package27* tailored to the needs of floating base conversion.28*/29class OldFDBigIntForTest {30int nWords; // number of words used31int data[]; // value: data[0] is least significant323334public OldFDBigIntForTest( int v ){35nWords = 1;36data = new int[1];37data[0] = v;38}3940public OldFDBigIntForTest( long v ){41data = new int[2];42data[0] = (int)v;43data[1] = (int)(v>>>32);44nWords = (data[1]==0) ? 1 : 2;45}4647public OldFDBigIntForTest( OldFDBigIntForTest other ){48data = new int[nWords = other.nWords];49System.arraycopy( other.data, 0, data, 0, nWords );50}5152private OldFDBigIntForTest( int [] d, int n ){53data = d;54nWords = n;55}5657public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){58int n= (nd+8)/9; // estimate size needed.59if ( n < 2 ) n = 2;60data = new int[n]; // allocate enough space61data[0] = (int)seed; // starting value62data[1] = (int)(seed>>>32);63nWords = (data[1]==0) ? 1 : 2;64int i = nd0;65int limit = nd-5; // slurp digits 5 at a time.66int v;67while ( i < limit ){68int ilim = i+5;69v = (int)digit[i++]-(int)'0';70while( i <ilim ){71v = 10*v + (int)digit[i++]-(int)'0';72}73multaddMe( 100000, v); // ... where 100000 is 10^5.74}75int factor = 1;76v = 0;77while ( i < nd ){78v = 10*v + (int)digit[i++]-(int)'0';79factor *= 10;80}81if ( factor != 1 ){82multaddMe( factor, v );83}84}8586/*87* Left shift by c bits.88* Shifts this in place.89*/90public void91lshiftMe( int c )throws IllegalArgumentException {92if ( c <= 0 ){93if ( c == 0 )94return; // silly.95else96throw new IllegalArgumentException("negative shift count");97}98int wordcount = c>>5;99int bitcount = c & 0x1f;100int anticount = 32-bitcount;101int t[] = data;102int s[] = data;103if ( nWords+wordcount+1 > t.length ){104// reallocate.105t = new int[ nWords+wordcount+1 ];106}107int target = nWords+wordcount;108int src = nWords-1;109if ( bitcount == 0 ){110// special hack, since an anticount of 32 won't go!111System.arraycopy( s, 0, t, wordcount, nWords );112target = wordcount-1;113} else {114t[target--] = s[src]>>>anticount;115while ( src >= 1 ){116t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);117}118t[target--] = s[src]<<bitcount;119}120while( target >= 0 ){121t[target--] = 0;122}123data = t;124nWords += wordcount + 1;125// may have constructed high-order word of 0.126// if so, trim it127while ( nWords > 1 && data[nWords-1] == 0 )128nWords--;129}130131/*132* normalize this number by shifting until133* the MSB of the number is at 0x08000000.134* This is in preparation for quoRemIteration, below.135* The idea is that, to make division easier, we want the136* divisor to be "normalized" -- usually this means shifting137* the MSB into the high words sign bit. But because we know that138* the quotient will be 0 < q < 10, we would like to arrange that139* the dividend not span up into another word of precision.140* (This needs to be explained more clearly!)141*/142public int143normalizeMe() throws IllegalArgumentException {144int src;145int wordcount = 0;146int bitcount = 0;147int v = 0;148for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){149wordcount += 1;150}151if ( src < 0 ){152// oops. Value is zero. Cannot normalize it!153throw new IllegalArgumentException("zero value");154}155/*156* In most cases, we assume that wordcount is zero. This only157* makes sense, as we try not to maintain any high-order158* words full of zeros. In fact, if there are zeros, we will159* simply SHORTEN our number at this point. Watch closely...160*/161nWords -= wordcount;162/*163* Compute how far left we have to shift v s.t. its highest-164* order bit is in the right place. Then call lshiftMe to165* do the work.166*/167if ( (v & 0xf0000000) != 0 ){168// will have to shift up into the next word.169// too bad.170for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )171v >>>= 1;172} else {173while ( v <= 0x000fffff ){174// hack: byte-at-a-time shifting175v <<= 8;176bitcount += 8;177}178while ( v <= 0x07ffffff ){179v <<= 1;180bitcount += 1;181}182}183if ( bitcount != 0 )184lshiftMe( bitcount );185return bitcount;186}187188/*189* Multiply a OldFDBigIntForTest by an int.190* Result is a new OldFDBigIntForTest.191*/192public OldFDBigIntForTest193mult( int iv ) {194long v = iv;195int r[];196long p;197198// guess adequate size of r.199r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];200p = 0L;201for( int i=0; i < nWords; i++ ) {202p += v * ((long)data[i]&0xffffffffL);203r[i] = (int)p;204p >>>= 32;205}206if ( p == 0L){207return new OldFDBigIntForTest( r, nWords );208} else {209r[nWords] = (int)p;210return new OldFDBigIntForTest( r, nWords+1 );211}212}213214/*215* Multiply a OldFDBigIntForTest by an int and add another int.216* Result is computed in place.217* Hope it fits!218*/219public void220multaddMe( int iv, int addend ) {221long v = iv;222long p;223224// unroll 0th iteration, doing addition.225p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);226data[0] = (int)p;227p >>>= 32;228for( int i=1; i < nWords; i++ ) {229p += v * ((long)data[i]&0xffffffffL);230data[i] = (int)p;231p >>>= 32;232}233if ( p != 0L){234data[nWords] = (int)p; // will fail noisily if illegal!235nWords++;236}237}238239/*240* Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.241* Result is a new OldFDBigIntForTest.242*/243public OldFDBigIntForTest244mult( OldFDBigIntForTest other ){245// crudely guess adequate size for r246int r[] = new int[ nWords + other.nWords ];247int i;248// I think I am promised zeros...249250for( i = 0; i < this.nWords; i++ ){251long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION252long p = 0L;253int j;254for( j = 0; j < other.nWords; j++ ){255p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.256r[i+j] = (int)p;257p >>>= 32;258}259r[i+j] = (int)p;260}261// compute how much of r we actually needed for all that.262for ( i = r.length-1; i> 0; i--)263if ( r[i] != 0 )264break;265return new OldFDBigIntForTest( r, i+1 );266}267268/*269* Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest270*/271public OldFDBigIntForTest272add( OldFDBigIntForTest other ){273int i;274int a[], b[];275int n, m;276long c = 0L;277// arrange such that a.nWords >= b.nWords;278// n = a.nWords, m = b.nWords279if ( this.nWords >= other.nWords ){280a = this.data;281n = this.nWords;282b = other.data;283m = other.nWords;284} else {285a = other.data;286n = other.nWords;287b = this.data;288m = this.nWords;289}290int r[] = new int[ n ];291for ( i = 0; i < n; i++ ){292c += (long)a[i] & 0xffffffffL;293if ( i < m ){294c += (long)b[i] & 0xffffffffL;295}296r[i] = (int) c;297c >>= 32; // signed shift.298}299if ( c != 0L ){300// oops -- carry out -- need longer result.301int s[] = new int[ r.length+1 ];302System.arraycopy( r, 0, s, 0, r.length );303s[i++] = (int)c;304return new OldFDBigIntForTest( s, i );305}306return new OldFDBigIntForTest( r, i );307}308309/*310* Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest311* Assert that the result is positive.312*/313public OldFDBigIntForTest314sub( OldFDBigIntForTest other ){315int r[] = new int[ this.nWords ];316int i;317int n = this.nWords;318int m = other.nWords;319int nzeros = 0;320long c = 0L;321for ( i = 0; i < n; i++ ){322c += (long)this.data[i] & 0xffffffffL;323if ( i < m ){324c -= (long)other.data[i] & 0xffffffffL;325}326if ( ( r[i] = (int) c ) == 0 )327nzeros++;328else329nzeros = 0;330c >>= 32; // signed shift331}332assert c == 0L : c; // borrow out of subtract333assert dataInRangeIsZero(i, m, other); // negative result of subtract334return new OldFDBigIntForTest( r, n-nzeros );335}336337private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {338while ( i < m )339if (other.data[i++] != 0)340return false;341return true;342}343344/*345* Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer346* >0: this > other347* 0: this == other348* <0: this < other349*/350public int351cmp( OldFDBigIntForTest other ){352int i;353if ( this.nWords > other.nWords ){354// if any of my high-order words is non-zero,355// then the answer is evident356int j = other.nWords-1;357for ( i = this.nWords-1; i > j ; i-- )358if ( this.data[i] != 0 ) return 1;359}else if ( this.nWords < other.nWords ){360// if any of other's high-order words is non-zero,361// then the answer is evident362int j = this.nWords-1;363for ( i = other.nWords-1; i > j ; i-- )364if ( other.data[i] != 0 ) return -1;365} else{366i = this.nWords-1;367}368for ( ; i > 0 ; i-- )369if ( this.data[i] != other.data[i] )370break;371// careful! want unsigned compare!372// use brute force here.373int a = this.data[i];374int b = other.data[i];375if ( a < 0 ){376// a is really big, unsigned377if ( b < 0 ){378return a-b; // both big, negative379} else {380return 1; // b not big, answer is obvious;381}382} else {383// a is not really big384if ( b < 0 ) {385// but b is really big386return -1;387} else {388return a - b;389}390}391}392393/*394* Compute395* q = (int)( this / S )396* this = 10 * ( this mod S )397* Return q.398* This is the iteration step of digit development for output.399* We assume that S has been normalized, as above, and that400* "this" has been lshift'ed accordingly.401* Also assume, of course, that the result, q, can be expressed402* as an integer, 0 <= q < 10.403*/404public int405quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {406// ensure that this and S have the same number of407// digits. If S is properly normalized and q < 10 then408// this must be so.409if ( nWords != S.nWords ){410throw new IllegalArgumentException("disparate values");411}412// estimate q the obvious way. We will usually be413// right. If not, then we're only off by a little and414// will re-add.415int n = nWords-1;416long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];417long diff = 0L;418for ( int i = 0; i <= n ; i++ ){419diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);420data[i] = (int)diff;421diff >>= 32; // N.B. SIGNED shift.422}423if ( diff != 0L ) {424// damn, damn, damn. q is too big.425// add S back in until this turns +. This should426// not be very many times!427long sum = 0L;428while ( sum == 0L ){429sum = 0L;430for ( int i = 0; i <= n; i++ ){431sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);432data[i] = (int) sum;433sum >>= 32; // Signed or unsigned, answer is 0 or 1434}435/*436* Originally the following line read437* "if ( sum !=0 && sum != -1 )"438* but that would be wrong, because of the439* treatment of the two values as entirely unsigned,440* it would be impossible for a carry-out to be interpreted441* as -1 -- it would have to be a single-bit carry-out, or442* +1.443*/444assert sum == 0 || sum == 1 : sum; // carry out of division correction445q -= 1;446}447}448// finally, we can multiply this by 10.449// it cannot overflow, right, as the high-order word has450// at least 4 high-order zeros!451long p = 0L;452for ( int i = 0; i <= n; i++ ){453p += 10*((long)data[i]&0xffffffffL);454data[i] = (int)p;455p >>= 32; // SIGNED shift.456}457assert p == 0L : p; // Carry out of *10458return (int)q;459}460461public long462longValue(){463// if this can be represented as a long, return the value464assert this.nWords > 0 : this.nWords; // longValue confused465466if (this.nWords == 1)467return ((long)data[0]&0xffffffffL);468469assert dataInRangeIsZero(2, this.nWords, this); // value too big470assert data[1] >= 0; // value too big471return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);472}473474public String475toString() {476StringBuffer r = new StringBuffer(30);477r.append('[');478int i = Math.min( nWords-1, data.length-1) ;479if ( nWords > data.length ){480r.append( "("+data.length+"<"+nWords+"!)" );481}482for( ; i> 0 ; i-- ){483r.append( Integer.toHexString( data[i] ) );484r.append(' ');485}486r.append( Integer.toHexString( data[0] ) );487r.append(']');488return new String( r );489}490}491492493