Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java
38839 views
1
/*
2
* Copyright (c) 1996, 2013, 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
}
492
493