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