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