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. 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 class FDBigInt { |
|
33 int nWords; // number of words used |
|
34 int data[]; // value: data[0] is least significant |
|
35 |
|
36 |
|
37 public FDBigInt( int v ){ |
|
38 nWords = 1; |
|
39 data = new int[1]; |
|
40 data[0] = v; |
|
41 } |
|
42 |
|
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 |
|
50 public FDBigInt( FDBigInt other ){ |
|
51 data = new int[nWords = other.nWords]; |
|
52 System.arraycopy( other.data, 0, data, 0, nWords ); |
|
53 } |
|
54 |
|
55 private FDBigInt( int [] d, int n ){ |
|
56 data = d; |
|
57 nWords = n; |
|
58 } |
|
59 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 } |
|