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
26package sun.misc;
27
28/*
29 * A really, really simple bigint package
30 * tailored to the needs of floating base conversion.
31 */
32public 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}
494