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 }