1 /*
   2  * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 //package sun.misc;
  25 
  26 /*
  27  * A really, really simple bigint package
  28  * tailored to the needs of floating base conversion.
  29  */
  30 class OldFDBigIntForTest {
  31     int nWords; // number of words used
  32     int data[]; // value: data[0] is least significant
  33 
  34 
  35     public OldFDBigIntForTest( int v ){
  36         nWords = 1;
  37         data = new int[1];
  38         data[0] = v;
  39     }
  40 
  41     public OldFDBigIntForTest( long v ){
  42         data = new int[2];
  43         data[0] = (int)v;
  44         data[1] = (int)(v>>>32);
  45         nWords = (data[1]==0) ? 1 : 2;
  46     }
  47 
  48     public OldFDBigIntForTest( OldFDBigIntForTest other ){
  49         data = new int[nWords = other.nWords];
  50         System.arraycopy( other.data, 0, data, 0, nWords );
  51     }
  52 
  53     private OldFDBigIntForTest( int [] d, int n ){
  54         data = d;
  55         nWords = n;
  56     }
  57 
  58     public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
  59         int n= (nd+8)/9;        // estimate size needed.
  60         if ( n < 2 ) n = 2;
  61         data = new int[n];      // allocate enough space
  62         data[0] = (int)seed;    // starting value
  63         data[1] = (int)(seed>>>32);
  64         nWords = (data[1]==0) ? 1 : 2;
  65         int i = nd0;
  66         int limit = nd-5;       // slurp digits 5 at a time.
  67         int v;
  68         while ( i < limit ){
  69             int ilim = i+5;
  70             v = (int)digit[i++]-(int)'0';
  71             while( i <ilim ){
  72                 v = 10*v + (int)digit[i++]-(int)'0';
  73             }
  74             multaddMe( 100000, v); // ... where 100000 is 10^5.
  75         }
  76         int factor = 1;
  77         v = 0;
  78         while ( i < nd ){
  79             v = 10*v + (int)digit[i++]-(int)'0';
  80             factor *= 10;
  81         }
  82         if ( factor != 1 ){
  83             multaddMe( factor, v );
  84         }
  85     }
  86 
  87     /*
  88      * Left shift by c bits.
  89      * Shifts this in place.
  90      */
  91     public void
  92     lshiftMe( int c )throws IllegalArgumentException {
  93         if ( c <= 0 ){
  94             if ( c == 0 )
  95                 return; // silly.
  96             else
  97                 throw new IllegalArgumentException("negative shift count");
  98         }
  99         int wordcount = c>>5;
 100         int bitcount  = c & 0x1f;
 101         int anticount = 32-bitcount;
 102         int t[] = data;
 103         int s[] = data;
 104         if ( nWords+wordcount+1 > t.length ){
 105             // reallocate.
 106             t = new int[ nWords+wordcount+1 ];
 107         }
 108         int target = nWords+wordcount;
 109         int src    = nWords-1;
 110         if ( bitcount == 0 ){
 111             // special hack, since an anticount of 32 won't go!
 112             System.arraycopy( s, 0, t, wordcount, nWords );
 113             target = wordcount-1;
 114         } else {
 115             t[target--] = s[src]>>>anticount;
 116             while ( src >= 1 ){
 117                 t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
 118             }
 119             t[target--] = s[src]<<bitcount;
 120         }
 121         while( target >= 0 ){
 122             t[target--] = 0;
 123         }
 124         data = t;
 125         nWords += wordcount + 1;
 126         // may have constructed high-order word of 0.
 127         // if so, trim it
 128         while ( nWords > 1 && data[nWords-1] == 0 )
 129             nWords--;
 130     }
 131 
 132     /*
 133      * normalize this number by shifting until
 134      * the MSB of the number is at 0x08000000.
 135      * This is in preparation for quoRemIteration, below.
 136      * The idea is that, to make division easier, we want the
 137      * divisor to be "normalized" -- usually this means shifting
 138      * the MSB into the high words sign bit. But because we know that
 139      * the quotient will be 0 < q < 10, we would like to arrange that
 140      * the dividend not span up into another word of precision.
 141      * (This needs to be explained more clearly!)
 142      */
 143     public int
 144     normalizeMe() throws IllegalArgumentException {
 145         int src;
 146         int wordcount = 0;
 147         int bitcount  = 0;
 148         int v = 0;
 149         for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
 150             wordcount += 1;
 151         }
 152         if ( src < 0 ){
 153             // oops. Value is zero. Cannot normalize it!
 154             throw new IllegalArgumentException("zero value");
 155         }
 156         /*
 157          * In most cases, we assume that wordcount is zero. This only
 158          * makes sense, as we try not to maintain any high-order
 159          * words full of zeros. In fact, if there are zeros, we will
 160          * simply SHORTEN our number at this point. Watch closely...
 161          */
 162         nWords -= wordcount;
 163         /*
 164          * Compute how far left we have to shift v s.t. its highest-
 165          * order bit is in the right place. Then call lshiftMe to
 166          * do the work.
 167          */
 168         if ( (v & 0xf0000000) != 0 ){
 169             // will have to shift up into the next word.
 170             // too bad.
 171             for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
 172                 v >>>= 1;
 173         } else {
 174             while ( v <= 0x000fffff ){
 175                 // hack: byte-at-a-time shifting
 176                 v <<= 8;
 177                 bitcount += 8;
 178             }
 179             while ( v <= 0x07ffffff ){
 180                 v <<= 1;
 181                 bitcount += 1;
 182             }
 183         }
 184         if ( bitcount != 0 )
 185             lshiftMe( bitcount );
 186         return bitcount;
 187     }
 188 
 189     /*
 190      * Multiply a OldFDBigIntForTest by an int.
 191      * Result is a new OldFDBigIntForTest.
 192      */
 193     public OldFDBigIntForTest
 194     mult( int iv ) {
 195         long v = iv;
 196         int r[];
 197         long p;
 198 
 199         // guess adequate size of r.
 200         r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
 201         p = 0L;
 202         for( int i=0; i < nWords; i++ ) {
 203             p += v * ((long)data[i]&0xffffffffL);
 204             r[i] = (int)p;
 205             p >>>= 32;
 206         }
 207         if ( p == 0L){
 208             return new OldFDBigIntForTest( r, nWords );
 209         } else {
 210             r[nWords] = (int)p;
 211             return new OldFDBigIntForTest( r, nWords+1 );
 212         }
 213     }
 214 
 215     /*
 216      * Multiply a OldFDBigIntForTest by an int and add another int.
 217      * Result is computed in place.
 218      * Hope it fits!
 219      */
 220     public void
 221     multaddMe( int iv, int addend ) {
 222         long v = iv;
 223         long p;
 224 
 225         // unroll 0th iteration, doing addition.
 226         p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
 227         data[0] = (int)p;
 228         p >>>= 32;
 229         for( int i=1; i < nWords; i++ ) {
 230             p += v * ((long)data[i]&0xffffffffL);
 231             data[i] = (int)p;
 232             p >>>= 32;
 233         }
 234         if ( p != 0L){
 235             data[nWords] = (int)p; // will fail noisily if illegal!
 236             nWords++;
 237         }
 238     }
 239 
 240     /*
 241      * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
 242      * Result is a new OldFDBigIntForTest.
 243      */
 244     public OldFDBigIntForTest
 245     mult( OldFDBigIntForTest other ){
 246         // crudely guess adequate size for r
 247         int r[] = new int[ nWords + other.nWords ];
 248         int i;
 249         // I think I am promised zeros...
 250 
 251         for( i = 0; i < this.nWords; i++ ){
 252             long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
 253             long p = 0L;
 254             int j;
 255             for( j = 0; j < other.nWords; j++ ){
 256                 p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
 257                 r[i+j] = (int)p;
 258                 p >>>= 32;
 259             }
 260             r[i+j] = (int)p;
 261         }
 262         // compute how much of r we actually needed for all that.
 263         for ( i = r.length-1; i> 0; i--)
 264             if ( r[i] != 0 )
 265                 break;
 266         return new OldFDBigIntForTest( r, i+1 );
 267     }
 268 
 269     /*
 270      * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
 271      */
 272     public OldFDBigIntForTest
 273     add( OldFDBigIntForTest other ){
 274         int i;
 275         int a[], b[];
 276         int n, m;
 277         long c = 0L;
 278         // arrange such that a.nWords >= b.nWords;
 279         // n = a.nWords, m = b.nWords
 280         if ( this.nWords >= other.nWords ){
 281             a = this.data;
 282             n = this.nWords;
 283             b = other.data;
 284             m = other.nWords;
 285         } else {
 286             a = other.data;
 287             n = other.nWords;
 288             b = this.data;
 289             m = this.nWords;
 290         }
 291         int r[] = new int[ n ];
 292         for ( i = 0; i < n; i++ ){
 293             c += (long)a[i] & 0xffffffffL;
 294             if ( i < m ){
 295                 c += (long)b[i] & 0xffffffffL;
 296             }
 297             r[i] = (int) c;
 298             c >>= 32; // signed shift.
 299         }
 300         if ( c != 0L ){
 301             // oops -- carry out -- need longer result.
 302             int s[] = new int[ r.length+1 ];
 303             System.arraycopy( r, 0, s, 0, r.length );
 304             s[i++] = (int)c;
 305             return new OldFDBigIntForTest( s, i );
 306         }
 307         return new OldFDBigIntForTest( r, i );
 308     }
 309 
 310     /*
 311      * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
 312      * Assert that the result is positive.
 313      */
 314     public OldFDBigIntForTest
 315     sub( OldFDBigIntForTest other ){
 316         int r[] = new int[ this.nWords ];
 317         int i;
 318         int n = this.nWords;
 319         int m = other.nWords;
 320         int nzeros = 0;
 321         long c = 0L;
 322         for ( i = 0; i < n; i++ ){
 323             c += (long)this.data[i] & 0xffffffffL;
 324             if ( i < m ){
 325                 c -= (long)other.data[i] & 0xffffffffL;
 326             }
 327             if ( ( r[i] = (int) c ) == 0 )
 328                 nzeros++;
 329             else
 330                 nzeros = 0;
 331             c >>= 32; // signed shift
 332         }
 333         assert c == 0L : c; // borrow out of subtract
 334         assert dataInRangeIsZero(i, m, other); // negative result of subtract
 335         return new OldFDBigIntForTest( r, n-nzeros );
 336     }
 337 
 338     private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
 339         while ( i < m )
 340             if (other.data[i++] != 0)
 341                 return false;
 342         return true;
 343     }
 344 
 345     /*
 346      * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
 347      * >0: this > other
 348      *  0: this == other
 349      * <0: this < other
 350      */
 351     public int
 352     cmp( OldFDBigIntForTest other ){
 353         int i;
 354         if ( this.nWords > other.nWords ){
 355             // if any of my high-order words is non-zero,
 356             // then the answer is evident
 357             int j = other.nWords-1;
 358             for ( i = this.nWords-1; i > j ; i-- )
 359                 if ( this.data[i] != 0 ) return 1;
 360         }else if ( this.nWords < other.nWords ){
 361             // if any of other's high-order words is non-zero,
 362             // then the answer is evident
 363             int j = this.nWords-1;
 364             for ( i = other.nWords-1; i > j ; i-- )
 365                 if ( other.data[i] != 0 ) return -1;
 366         } else{
 367             i = this.nWords-1;
 368         }
 369         for ( ; i > 0 ; i-- )
 370             if ( this.data[i] != other.data[i] )
 371                 break;
 372         // careful! want unsigned compare!
 373         // use brute force here.
 374         int a = this.data[i];
 375         int b = other.data[i];
 376         if ( a < 0 ){
 377             // a is really big, unsigned
 378             if ( b < 0 ){
 379                 return a-b; // both big, negative
 380             } else {
 381                 return 1; // b not big, answer is obvious;
 382             }
 383         } else {
 384             // a is not really big
 385             if ( b < 0 ) {
 386                 // but b is really big
 387                 return -1;
 388             } else {
 389                 return a - b;
 390             }
 391         }
 392     }
 393 
 394     /*
 395      * Compute
 396      * q = (int)( this / S )
 397      * this = 10 * ( this mod S )
 398      * Return q.
 399      * This is the iteration step of digit development for output.
 400      * We assume that S has been normalized, as above, and that
 401      * "this" has been lshift'ed accordingly.
 402      * Also assume, of course, that the result, q, can be expressed
 403      * as an integer, 0 <= q < 10.
 404      */
 405     public int
 406     quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
 407         // ensure that this and S have the same number of
 408         // digits. If S is properly normalized and q < 10 then
 409         // this must be so.
 410         if ( nWords != S.nWords ){
 411             throw new IllegalArgumentException("disparate values");
 412         }
 413         // estimate q the obvious way. We will usually be
 414         // right. If not, then we're only off by a little and
 415         // will re-add.
 416         int n = nWords-1;
 417         long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
 418         long diff = 0L;
 419         for ( int i = 0; i <= n ; i++ ){
 420             diff += ((long)data[i]&0xffffffffL) -  q*((long)S.data[i]&0xffffffffL);
 421             data[i] = (int)diff;
 422             diff >>= 32; // N.B. SIGNED shift.
 423         }
 424         if ( diff != 0L ) {
 425             // damn, damn, damn. q is too big.
 426             // add S back in until this turns +. This should
 427             // not be very many times!
 428             long sum = 0L;
 429             while ( sum ==  0L ){
 430                 sum = 0L;
 431                 for ( int i = 0; i <= n; i++ ){
 432                     sum += ((long)data[i]&0xffffffffL) +  ((long)S.data[i]&0xffffffffL);
 433                     data[i] = (int) sum;
 434                     sum >>= 32; // Signed or unsigned, answer is 0 or 1
 435                 }
 436                 /*
 437                  * Originally the following line read
 438                  * "if ( sum !=0 && sum != -1 )"
 439                  * but that would be wrong, because of the
 440                  * treatment of the two values as entirely unsigned,
 441                  * it would be impossible for a carry-out to be interpreted
 442                  * as -1 -- it would have to be a single-bit carry-out, or
 443                  * +1.
 444                  */
 445                 assert sum == 0 || sum == 1 : sum; // carry out of division correction
 446                 q -= 1;
 447             }
 448         }
 449         // finally, we can multiply this by 10.
 450         // it cannot overflow, right, as the high-order word has
 451         // at least 4 high-order zeros!
 452         long p = 0L;
 453         for ( int i = 0; i <= n; i++ ){
 454             p += 10*((long)data[i]&0xffffffffL);
 455             data[i] = (int)p;
 456             p >>= 32; // SIGNED shift.
 457         }
 458         assert p == 0L : p; // Carry out of *10
 459         return (int)q;
 460     }
 461 
 462     public long
 463     longValue(){
 464         // if this can be represented as a long, return the value
 465         assert this.nWords > 0 : this.nWords; // longValue confused
 466 
 467         if (this.nWords == 1)
 468             return ((long)data[0]&0xffffffffL);
 469 
 470         assert dataInRangeIsZero(2, this.nWords, this); // value too big
 471         assert data[1] >= 0;  // value too big
 472         return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
 473     }
 474 
 475     public String
 476     toString() {
 477         StringBuffer r = new StringBuffer(30);
 478         r.append('[');
 479         int i = Math.min( nWords-1, data.length-1) ;
 480         if ( nWords > data.length ){
 481             r.append( "("+data.length+"<"+nWords+"!)" );
 482         }
 483         for( ; i> 0 ; i-- ){
 484             r.append( Integer.toHexString( data[i] ) );
 485             r.append(' ');
 486         }
 487         r.append( Integer.toHexString( data[0] ) );
 488         r.append(']');
 489         return new String( r );
 490     }
 491 }