Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java
41159 views
1
/*
2
* Copyright (c) 2013, 2020, 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
package jdk.internal.math;
26
27
import jdk.internal.misc.CDS;
28
29
import java.math.BigInteger;
30
import java.util.Arrays;
31
//@ model import org.jmlspecs.models.JMLMath;
32
33
/**
34
* A simple big integer package specifically for floating point base conversion.
35
*/
36
public /*@ spec_bigint_math @*/ class FDBigInteger {
37
38
//
39
// This class contains many comments that start with "/*@" mark.
40
// They are behavourial specification in
41
// the Java Modelling Language (JML):
42
// http://www.eecs.ucf.edu/~leavens/JML//index.shtml
43
//
44
45
/*@
46
@ public pure model static \bigint UNSIGNED(int v) {
47
@ return v >= 0 ? v : v + (((\bigint)1) << 32);
48
@ }
49
@
50
@ public pure model static \bigint UNSIGNED(long v) {
51
@ return v >= 0 ? v : v + (((\bigint)1) << 64);
52
@ }
53
@
54
@ public pure model static \bigint AP(int[] data, int len) {
55
@ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
56
@ }
57
@
58
@ public pure model static \bigint pow52(int p5, int p2) {
59
@ ghost \bigint v = 1;
60
@ for (int i = 0; i < p5; i++) v *= 5;
61
@ return v << p2;
62
@ }
63
@
64
@ public pure model static \bigint pow10(int p10) {
65
@ return pow52(p10, p10);
66
@ }
67
@*/
68
69
static final int[] SMALL_5_POW;
70
71
static final long[] LONG_5_POW;
72
73
// Maximum size of cache of powers of 5 as FDBigIntegers.
74
private static final int MAX_FIVE_POW = 340;
75
76
// Cache of big powers of 5 as FDBigIntegers.
77
private static final FDBigInteger POW_5_CACHE[];
78
79
// Zero as an FDBigInteger.
80
public static final FDBigInteger ZERO;
81
82
// Archive proxy
83
private static Object[] archivedCaches;
84
85
// Initialize FDBigInteger cache of powers of 5.
86
static {
87
CDS.initializeFromArchive(FDBigInteger.class);
88
Object[] caches = archivedCaches;
89
if (caches == null) {
90
long[] long5pow = {
91
1L,
92
5L,
93
5L * 5,
94
5L * 5 * 5,
95
5L * 5 * 5 * 5,
96
5L * 5 * 5 * 5 * 5,
97
5L * 5 * 5 * 5 * 5 * 5,
98
5L * 5 * 5 * 5 * 5 * 5 * 5,
99
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
100
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
101
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
102
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
103
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
104
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
105
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
106
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
107
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
108
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
109
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
110
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
111
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
112
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
113
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
114
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
115
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
116
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
117
5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
118
};
119
int[] small5pow = {
120
1,
121
5,
122
5 * 5,
123
5 * 5 * 5,
124
5 * 5 * 5 * 5,
125
5 * 5 * 5 * 5 * 5,
126
5 * 5 * 5 * 5 * 5 * 5,
127
5 * 5 * 5 * 5 * 5 * 5 * 5,
128
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
129
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
130
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
131
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
132
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
133
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
134
};
135
FDBigInteger[] pow5cache = new FDBigInteger[MAX_FIVE_POW];
136
int i = 0;
137
while (i < small5pow.length) {
138
FDBigInteger pow5 = new FDBigInteger(new int[] { small5pow[i] }, 0);
139
pow5.makeImmutable();
140
pow5cache[i] = pow5;
141
i++;
142
}
143
FDBigInteger prev = pow5cache[i - 1];
144
while (i < MAX_FIVE_POW) {
145
pow5cache[i] = prev = prev.mult(5);
146
prev.makeImmutable();
147
i++;
148
}
149
FDBigInteger zero = new FDBigInteger(new int[0], 0);
150
zero.makeImmutable();
151
archivedCaches = caches = new Object[] {small5pow, long5pow, pow5cache, zero};
152
}
153
SMALL_5_POW = (int[])caches[0];
154
LONG_5_POW = (long[])caches[1];
155
POW_5_CACHE = (FDBigInteger[])caches[2];
156
ZERO = (FDBigInteger)caches[3];
157
}
158
159
// Constant for casting an int to a long via bitwise AND.
160
private static final long LONG_MASK = 0xffffffffL;
161
162
//@ spec_public non_null;
163
private int data[]; // value: data[0] is least significant
164
//@ spec_public;
165
private int offset; // number of least significant zero padding ints
166
//@ spec_public;
167
private int nWords; // data[nWords-1]!=0, all values above are zero
168
// if nWords==0 -> this FDBigInteger is zero
169
//@ spec_public;
170
private boolean isImmutable = false;
171
172
/*@
173
@ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
174
@ public invariant nWords == 0 ==> offset == 0;
175
@ public invariant nWords > 0 ==> data[nWords - 1] != 0;
176
@ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
177
@ public pure model \bigint value() {
178
@ return AP(data, nWords) << (offset*32);
179
@ }
180
@*/
181
182
/**
183
* Constructs an <code>FDBigInteger</code> from data and padding. The
184
* <code>data</code> parameter has the least significant <code>int</code> at
185
* the zeroth index. The <code>offset</code> parameter gives the number of
186
* zero <code>int</code>s to be inferred below the least significant element
187
* of <code>data</code>.
188
*
189
* @param data An array containing all non-zero <code>int</code>s of the value.
190
* @param offset An offset indicating the number of zero <code>int</code>s to pad
191
* below the least significant element of <code>data</code>.
192
*/
193
/*@
194
@ requires data != null && offset >= 0;
195
@ ensures this.value() == \old(AP(data, data.length) << (offset*32));
196
@ ensures this.data == \old(data);
197
@*/
198
private FDBigInteger(int[] data, int offset) {
199
this.data = data;
200
this.offset = offset;
201
this.nWords = data.length;
202
trimLeadingZeros();
203
}
204
205
/**
206
* Constructs an <code>FDBigInteger</code> from a starting value and some
207
* decimal digits.
208
*
209
* @param lValue The starting value.
210
* @param digits The decimal digits.
211
* @param kDigits The initial index into <code>digits</code>.
212
* @param nDigits The final index into <code>digits</code>.
213
*/
214
/*@
215
@ requires digits != null;
216
@ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
217
@ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
218
@ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
219
@*/
220
public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
221
int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
222
data = new int[n]; // allocate enough space
223
data[0] = (int) lValue; // starting value
224
data[1] = (int) (lValue >>> 32);
225
offset = 0;
226
nWords = 2;
227
int i = kDigits;
228
int limit = nDigits - 5; // slurp digits 5 at a time.
229
int v;
230
while (i < limit) {
231
int ilim = i + 5;
232
v = (int) digits[i++] - (int) '0';
233
while (i < ilim) {
234
v = 10 * v + (int) digits[i++] - (int) '0';
235
}
236
multAddMe(100000, v); // ... where 100000 is 10^5.
237
}
238
int factor = 1;
239
v = 0;
240
while (i < nDigits) {
241
v = 10 * v + (int) digits[i++] - (int) '0';
242
factor *= 10;
243
}
244
if (factor != 1) {
245
multAddMe(factor, v);
246
}
247
trimLeadingZeros();
248
}
249
250
/**
251
* Returns an <code>FDBigInteger</code> with the numerical value
252
* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
253
*
254
* @param p5 The exponent of the power-of-five factor.
255
* @param p2 The exponent of the power-of-two factor.
256
* @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
257
*/
258
/*@
259
@ requires p5 >= 0 && p2 >= 0;
260
@ assignable \nothing;
261
@ ensures \result.value() == \old(pow52(p5, p2));
262
@*/
263
public static FDBigInteger valueOfPow52(int p5, int p2) {
264
if (p5 != 0) {
265
if (p2 == 0) {
266
return big5pow(p5);
267
} else if (p5 < SMALL_5_POW.length) {
268
int pow5 = SMALL_5_POW[p5];
269
int wordcount = p2 >> 5;
270
int bitcount = p2 & 0x1f;
271
if (bitcount == 0) {
272
return new FDBigInteger(new int[]{pow5}, wordcount);
273
} else {
274
return new FDBigInteger(new int[]{
275
pow5 << bitcount,
276
pow5 >>> (32 - bitcount)
277
}, wordcount);
278
}
279
} else {
280
return big5pow(p5).leftShift(p2);
281
}
282
} else {
283
return valueOfPow2(p2);
284
}
285
}
286
287
/**
288
* Returns an <code>FDBigInteger</code> with the numerical value
289
* <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
290
*
291
* @param value The constant factor.
292
* @param p5 The exponent of the power-of-five factor.
293
* @param p2 The exponent of the power-of-two factor.
294
* @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
295
*/
296
/*@
297
@ requires p5 >= 0 && p2 >= 0;
298
@ assignable \nothing;
299
@ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
300
@*/
301
public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
302
assert p5 >= 0 : p5;
303
assert p2 >= 0 : p2;
304
int v0 = (int) value;
305
int v1 = (int) (value >>> 32);
306
int wordcount = p2 >> 5;
307
int bitcount = p2 & 0x1f;
308
if (p5 != 0) {
309
if (p5 < SMALL_5_POW.length) {
310
long pow5 = SMALL_5_POW[p5] & LONG_MASK;
311
long carry = (v0 & LONG_MASK) * pow5;
312
v0 = (int) carry;
313
carry >>>= 32;
314
carry = (v1 & LONG_MASK) * pow5 + carry;
315
v1 = (int) carry;
316
int v2 = (int) (carry >>> 32);
317
if (bitcount == 0) {
318
return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
319
} else {
320
return new FDBigInteger(new int[]{
321
v0 << bitcount,
322
(v1 << bitcount) | (v0 >>> (32 - bitcount)),
323
(v2 << bitcount) | (v1 >>> (32 - bitcount)),
324
v2 >>> (32 - bitcount)
325
}, wordcount);
326
}
327
} else {
328
FDBigInteger pow5 = big5pow(p5);
329
int[] r;
330
if (v1 == 0) {
331
r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
332
mult(pow5.data, pow5.nWords, v0, r);
333
} else {
334
r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
335
mult(pow5.data, pow5.nWords, v0, v1, r);
336
}
337
return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
338
}
339
} else if (p2 != 0) {
340
if (bitcount == 0) {
341
return new FDBigInteger(new int[]{v0, v1}, wordcount);
342
} else {
343
return new FDBigInteger(new int[]{
344
v0 << bitcount,
345
(v1 << bitcount) | (v0 >>> (32 - bitcount)),
346
v1 >>> (32 - bitcount)
347
}, wordcount);
348
}
349
}
350
return new FDBigInteger(new int[]{v0, v1}, 0);
351
}
352
353
/**
354
* Returns an <code>FDBigInteger</code> with the numerical value
355
* <code>2<sup>p2</sup></code>.
356
*
357
* @param p2 The exponent of 2.
358
* @return <code>2<sup>p2</sup></code>
359
*/
360
/*@
361
@ requires p2 >= 0;
362
@ assignable \nothing;
363
@ ensures \result.value() == pow52(0, p2);
364
@*/
365
private static FDBigInteger valueOfPow2(int p2) {
366
int wordcount = p2 >> 5;
367
int bitcount = p2 & 0x1f;
368
return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
369
}
370
371
/**
372
* Removes all leading zeros from this <code>FDBigInteger</code> adjusting
373
* the offset and number of non-zero leading words accordingly.
374
*/
375
/*@
376
@ requires data != null;
377
@ requires 0 <= nWords && nWords <= data.length && offset >= 0;
378
@ requires nWords == 0 ==> offset == 0;
379
@ ensures nWords == 0 ==> offset == 0;
380
@ ensures nWords > 0 ==> data[nWords - 1] != 0;
381
@*/
382
private /*@ helper @*/ void trimLeadingZeros() {
383
int i = nWords;
384
if (i > 0 && (data[--i] == 0)) {
385
//for (; i > 0 && data[i - 1] == 0; i--) ;
386
while(i > 0 && data[i - 1] == 0) {
387
i--;
388
}
389
this.nWords = i;
390
if (i == 0) { // all words are zero
391
this.offset = 0;
392
}
393
}
394
}
395
396
/**
397
* Retrieves the normalization bias of the <code>FDBigIntger</code>. The
398
* normalization bias is a left shift such that after it the highest word
399
* of the value will have the 4 highest bits equal to zero:
400
* {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
401
* {@code (highestWord & 0x08000000) != 0}.
402
*
403
* @return The normalization bias.
404
*/
405
/*@
406
@ requires this.value() > 0;
407
@*/
408
public /*@ pure @*/ int getNormalizationBias() {
409
if (nWords == 0) {
410
throw new IllegalArgumentException("Zero value cannot be normalized");
411
}
412
int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
413
return (zeros < 4) ? 28 + zeros : zeros - 4;
414
}
415
416
// TODO: Why is anticount param needed if it is always 32 - bitcount?
417
/**
418
* Left shifts the contents of one int array into another.
419
*
420
* @param src The source array.
421
* @param idx The initial index of the source array.
422
* @param result The destination array.
423
* @param bitcount The left shift.
424
* @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
425
* @param prev The prior source value.
426
*/
427
/*@
428
@ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
429
@ requires src.length >= idx && result.length > idx;
430
@ assignable result[*];
431
@ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
432
@*/
433
private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
434
for (; idx > 0; idx--) {
435
int v = (prev << bitcount);
436
prev = src[idx - 1];
437
v |= (prev >>> anticount);
438
result[idx] = v;
439
}
440
int v = prev << bitcount;
441
result[0] = v;
442
}
443
444
/**
445
* Shifts this <code>FDBigInteger</code> to the left. The shift is performed
446
* in-place unless the <code>FDBigInteger</code> is immutable in which case
447
* a new instance of <code>FDBigInteger</code> is returned.
448
*
449
* @param shift The number of bits to shift left.
450
* @return The shifted <code>FDBigInteger</code>.
451
*/
452
/*@
453
@ requires this.value() == 0 || shift == 0;
454
@ assignable \nothing;
455
@ ensures \result == this;
456
@
457
@ also
458
@
459
@ requires this.value() > 0 && shift > 0 && this.isImmutable;
460
@ assignable \nothing;
461
@ ensures \result.value() == \old(this.value() << shift);
462
@
463
@ also
464
@
465
@ requires this.value() > 0 && shift > 0 && this.isImmutable;
466
@ assignable \nothing;
467
@ ensures \result == this;
468
@ ensures \result.value() == \old(this.value() << shift);
469
@*/
470
public FDBigInteger leftShift(int shift) {
471
if (shift == 0 || nWords == 0) {
472
return this;
473
}
474
int wordcount = shift >> 5;
475
int bitcount = shift & 0x1f;
476
if (this.isImmutable) {
477
if (bitcount == 0) {
478
return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
479
} else {
480
int anticount = 32 - bitcount;
481
int idx = nWords - 1;
482
int prev = data[idx];
483
int hi = prev >>> anticount;
484
int[] result;
485
if (hi != 0) {
486
result = new int[nWords + 1];
487
result[nWords] = hi;
488
} else {
489
result = new int[nWords];
490
}
491
leftShift(data,idx,result,bitcount,anticount,prev);
492
return new FDBigInteger(result, offset + wordcount);
493
}
494
} else {
495
if (bitcount != 0) {
496
int anticount = 32 - bitcount;
497
if ((data[0] << bitcount) == 0) {
498
int idx = 0;
499
int prev = data[idx];
500
for (; idx < nWords - 1; idx++) {
501
int v = (prev >>> anticount);
502
prev = data[idx + 1];
503
v |= (prev << bitcount);
504
data[idx] = v;
505
}
506
int v = prev >>> anticount;
507
data[idx] = v;
508
if(v==0) {
509
nWords--;
510
}
511
offset++;
512
} else {
513
int idx = nWords - 1;
514
int prev = data[idx];
515
int hi = prev >>> anticount;
516
int[] result = data;
517
int[] src = data;
518
if (hi != 0) {
519
if(nWords == data.length) {
520
data = result = new int[nWords + 1];
521
}
522
result[nWords++] = hi;
523
}
524
leftShift(src,idx,result,bitcount,anticount,prev);
525
}
526
}
527
offset += wordcount;
528
return this;
529
}
530
}
531
532
/**
533
* Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
534
*
535
* @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
536
*/
537
/*@
538
@ requires this.value() == 0;
539
@ ensures \result == 0;
540
@
541
@ also
542
@
543
@ requires this.value() > 0;
544
@ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
545
@*/
546
private /*@ pure @*/ int size() {
547
return nWords + offset;
548
}
549
550
551
/**
552
* Computes
553
* <pre>
554
* q = (int)( this / S )
555
* this = 10 * ( this mod S )
556
* Return q.
557
* </pre>
558
* This is the iteration step of digit development for output.
559
* We assume that S has been normalized, as above, and that
560
* "this" has been left-shifted accordingly.
561
* Also assumed, of course, is that the result, q, can be expressed
562
* as an integer, {@code 0 <= q < 10}.
563
*
564
* @param S The divisor of this <code>FDBigInteger</code>.
565
* @return <code>q = (int)(this / S)</code>.
566
*/
567
/*@
568
@ requires !this.isImmutable;
569
@ requires this.size() <= S.size();
570
@ requires this.data.length + this.offset >= S.size();
571
@ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
572
@ assignable this.nWords, this.offset, this.data, this.data[*];
573
@ ensures \result == \old(this.value() / S.value());
574
@ ensures this.value() == \old(10 * (this.value() % S.value()));
575
@*/
576
public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
577
assert !this.isImmutable : "cannot modify immutable value";
578
// ensure that this and S have the same number of
579
// digits. If S is properly normalized and q < 10 then
580
// this must be so.
581
int thSize = this.size();
582
int sSize = S.size();
583
if (thSize < sSize) {
584
// this value is significantly less than S, result of division is zero.
585
// just mult this by 10.
586
int p = multAndCarryBy10(this.data, this.nWords, this.data);
587
if(p!=0) {
588
this.data[nWords++] = p;
589
} else {
590
trimLeadingZeros();
591
}
592
return 0;
593
} else if (thSize > sSize) {
594
throw new IllegalArgumentException("disparate values");
595
}
596
// estimate q the obvious way. We will usually be
597
// right. If not, then we're only off by a little and
598
// will re-add.
599
long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
600
long diff = multDiffMe(q, S);
601
if (diff != 0L) {
602
//@ assert q != 0;
603
//@ assert this.offset == \old(Math.min(this.offset, S.offset));
604
//@ assert this.offset <= S.offset;
605
606
// q is too big.
607
// add S back in until this turns +. This should
608
// not be very many times!
609
long sum = 0L;
610
int tStart = S.offset - this.offset;
611
//@ assert tStart >= 0;
612
int[] sd = S.data;
613
int[] td = this.data;
614
while (sum == 0L) {
615
for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
616
sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
617
td[tIndex] = (int) sum;
618
sum >>>= 32; // Signed or unsigned, answer is 0 or 1
619
}
620
//
621
// Originally the following line read
622
// "if ( sum !=0 && sum != -1 )"
623
// but that would be wrong, because of the
624
// treatment of the two values as entirely unsigned,
625
// it would be impossible for a carry-out to be interpreted
626
// as -1 -- it would have to be a single-bit carry-out, or +1.
627
//
628
assert sum == 0 || sum == 1 : sum; // carry out of division correction
629
q -= 1;
630
}
631
}
632
// finally, we can multiply this by 10.
633
// it cannot overflow, right, as the high-order word has
634
// at least 4 high-order zeros!
635
int p = multAndCarryBy10(this.data, this.nWords, this.data);
636
assert p == 0 : p; // Carry out of *10
637
trimLeadingZeros();
638
return (int) q;
639
}
640
641
/**
642
* Multiplies this <code>FDBigInteger</code> by 10. The operation will be
643
* performed in place unless the <code>FDBigInteger</code> is immutable in
644
* which case a new <code>FDBigInteger</code> will be returned.
645
*
646
* @return The <code>FDBigInteger</code> multiplied by 10.
647
*/
648
/*@
649
@ requires this.value() == 0;
650
@ assignable \nothing;
651
@ ensures \result == this;
652
@
653
@ also
654
@
655
@ requires this.value() > 0 && this.isImmutable;
656
@ assignable \nothing;
657
@ ensures \result.value() == \old(this.value() * 10);
658
@
659
@ also
660
@
661
@ requires this.value() > 0 && !this.isImmutable;
662
@ assignable this.nWords, this.data, this.data[*];
663
@ ensures \result == this;
664
@ ensures \result.value() == \old(this.value() * 10);
665
@*/
666
public FDBigInteger multBy10() {
667
if (nWords == 0) {
668
return this;
669
}
670
if (isImmutable) {
671
int[] res = new int[nWords + 1];
672
res[nWords] = multAndCarryBy10(data, nWords, res);
673
return new FDBigInteger(res, offset);
674
} else {
675
int p = multAndCarryBy10(this.data, this.nWords, this.data);
676
if (p != 0) {
677
if (nWords == data.length) {
678
if (data[0] == 0) {
679
System.arraycopy(data, 1, data, 0, --nWords);
680
offset++;
681
} else {
682
data = Arrays.copyOf(data, data.length + 1);
683
}
684
}
685
data[nWords++] = p;
686
} else {
687
trimLeadingZeros();
688
}
689
return this;
690
}
691
}
692
693
/**
694
* Multiplies this <code>FDBigInteger</code> by
695
* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
696
* performed in place if possible, otherwise a new <code>FDBigInteger</code>
697
* will be returned.
698
*
699
* @param p5 The exponent of the power-of-five factor.
700
* @param p2 The exponent of the power-of-two factor.
701
* @return The multiplication result.
702
*/
703
/*@
704
@ requires this.value() == 0 || p5 == 0 && p2 == 0;
705
@ assignable \nothing;
706
@ ensures \result == this;
707
@
708
@ also
709
@
710
@ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
711
@ assignable \nothing;
712
@ ensures \result.value() == \old(this.value() * pow52(p5, p2));
713
@
714
@ also
715
@
716
@ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
717
@ assignable this.nWords, this.data, this.data[*];
718
@ ensures \result == this;
719
@ ensures \result.value() == \old(this.value() * pow52(p5, p2));
720
@*/
721
public FDBigInteger multByPow52(int p5, int p2) {
722
if (this.nWords == 0) {
723
return this;
724
}
725
FDBigInteger res = this;
726
if (p5 != 0) {
727
int[] r;
728
int extraSize = (p2 != 0) ? 1 : 0;
729
if (p5 < SMALL_5_POW.length) {
730
r = new int[this.nWords + 1 + extraSize];
731
mult(this.data, this.nWords, SMALL_5_POW[p5], r);
732
res = new FDBigInteger(r, this.offset);
733
} else {
734
FDBigInteger pow5 = big5pow(p5);
735
r = new int[this.nWords + pow5.size() + extraSize];
736
mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
737
res = new FDBigInteger(r, this.offset + pow5.offset);
738
}
739
}
740
return res.leftShift(p2);
741
}
742
743
/**
744
* Multiplies two big integers represented as int arrays.
745
*
746
* @param s1 The first array factor.
747
* @param s1Len The number of elements of <code>s1</code> to use.
748
* @param s2 The second array factor.
749
* @param s2Len The number of elements of <code>s2</code> to use.
750
* @param dst The product array.
751
*/
752
/*@
753
@ requires s1 != dst && s2 != dst;
754
@ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
755
@ assignable dst[0 .. s1Len + s2Len - 1];
756
@ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
757
@*/
758
private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
759
for (int i = 0; i < s1Len; i++) {
760
long v = s1[i] & LONG_MASK;
761
long p = 0L;
762
for (int j = 0; j < s2Len; j++) {
763
p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
764
dst[i + j] = (int) p;
765
p >>>= 32;
766
}
767
dst[i + s2Len] = (int) p;
768
}
769
}
770
771
/**
772
* Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
773
* <code>FDBigInteger</code>. Assert that the result is positive.
774
* If the subtrahend is immutable, store the result in this(minuend).
775
* If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
776
*
777
* @param subtrahend The <code>FDBigInteger</code> to be subtracted.
778
* @return This <code>FDBigInteger</code> less the subtrahend.
779
*/
780
/*@
781
@ requires this.isImmutable;
782
@ requires this.value() >= subtrahend.value();
783
@ assignable \nothing;
784
@ ensures \result.value() == \old(this.value() - subtrahend.value());
785
@
786
@ also
787
@
788
@ requires !subtrahend.isImmutable;
789
@ requires this.value() >= subtrahend.value();
790
@ assignable this.nWords, this.offset, this.data, this.data[*];
791
@ ensures \result == this;
792
@ ensures \result.value() == \old(this.value() - subtrahend.value());
793
@*/
794
public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
795
assert this.size() >= subtrahend.size() : "result should be positive";
796
FDBigInteger minuend;
797
if (this.isImmutable) {
798
minuend = new FDBigInteger(this.data.clone(), this.offset);
799
} else {
800
minuend = this;
801
}
802
int offsetDiff = subtrahend.offset - minuend.offset;
803
int[] sData = subtrahend.data;
804
int[] mData = minuend.data;
805
int subLen = subtrahend.nWords;
806
int minLen = minuend.nWords;
807
if (offsetDiff < 0) {
808
// need to expand minuend
809
int rLen = minLen - offsetDiff;
810
if (rLen < mData.length) {
811
System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
812
Arrays.fill(mData, 0, -offsetDiff, 0);
813
} else {
814
int[] r = new int[rLen];
815
System.arraycopy(mData, 0, r, -offsetDiff, minLen);
816
minuend.data = mData = r;
817
}
818
minuend.offset = subtrahend.offset;
819
minuend.nWords = minLen = rLen;
820
offsetDiff = 0;
821
}
822
long borrow = 0L;
823
int mIndex = offsetDiff;
824
for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
825
long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
826
mData[mIndex] = (int) diff;
827
borrow = diff >> 32; // signed shift
828
}
829
for (; borrow != 0 && mIndex < minLen; mIndex++) {
830
long diff = (mData[mIndex] & LONG_MASK) + borrow;
831
mData[mIndex] = (int) diff;
832
borrow = diff >> 32; // signed shift
833
}
834
assert borrow == 0L : borrow; // borrow out of subtract,
835
// result should be positive
836
minuend.trimLeadingZeros();
837
return minuend;
838
}
839
840
/**
841
* Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
842
* <code>FDBigInteger</code>. Assert that the result is positive.
843
* If the this(minuend) is immutable, store the result in subtrahend.
844
* If subtrahend is immutable a new <code>FDBigInteger</code> is created.
845
*
846
* @param subtrahend The <code>FDBigInteger</code> to be subtracted.
847
* @return This <code>FDBigInteger</code> less the subtrahend.
848
*/
849
/*@
850
@ requires subtrahend.isImmutable;
851
@ requires this.value() >= subtrahend.value();
852
@ assignable \nothing;
853
@ ensures \result.value() == \old(this.value() - subtrahend.value());
854
@
855
@ also
856
@
857
@ requires !subtrahend.isImmutable;
858
@ requires this.value() >= subtrahend.value();
859
@ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
860
@ ensures \result == subtrahend;
861
@ ensures \result.value() == \old(this.value() - subtrahend.value());
862
@*/
863
public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
864
assert this.size() >= subtrahend.size() : "result should be positive";
865
FDBigInteger minuend = this;
866
if (subtrahend.isImmutable) {
867
subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
868
}
869
int offsetDiff = minuend.offset - subtrahend.offset;
870
int[] sData = subtrahend.data;
871
int[] mData = minuend.data;
872
int subLen = subtrahend.nWords;
873
int minLen = minuend.nWords;
874
if (offsetDiff < 0) {
875
int rLen = minLen;
876
if (rLen < sData.length) {
877
System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
878
Arrays.fill(sData, 0, -offsetDiff, 0);
879
} else {
880
int[] r = new int[rLen];
881
System.arraycopy(sData, 0, r, -offsetDiff, subLen);
882
subtrahend.data = sData = r;
883
}
884
subtrahend.offset = minuend.offset;
885
subLen -= offsetDiff;
886
offsetDiff = 0;
887
} else {
888
int rLen = minLen + offsetDiff;
889
if (rLen >= sData.length) {
890
subtrahend.data = sData = Arrays.copyOf(sData, rLen);
891
}
892
}
893
//@ assert minuend == this && minuend.value() == \old(this.value());
894
//@ assert mData == minuend.data && minLen == minuend.nWords;
895
//@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
896
//@ assert sData == subtrahend.data;
897
//@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
898
//@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
899
//@ assert offsetDiff == minuend.offset - subtrahend.offset;
900
//@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
901
int sIndex = 0;
902
long borrow = 0L;
903
for (; sIndex < offsetDiff; sIndex++) {
904
long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
905
sData[sIndex] = (int) diff;
906
borrow = diff >> 32; // signed shift
907
}
908
//@ assert sIndex == offsetDiff;
909
for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
910
//@ assert sIndex == offsetDiff + mIndex;
911
long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
912
sData[sIndex] = (int) diff;
913
borrow = diff >> 32; // signed shift
914
}
915
assert borrow == 0L : borrow; // borrow out of subtract,
916
// result should be positive
917
subtrahend.nWords = sIndex;
918
subtrahend.trimLeadingZeros();
919
return subtrahend;
920
921
}
922
923
/**
924
* Determines whether all elements of an array are zero for all indices less
925
* than a given index.
926
*
927
* @param a The array to be examined.
928
* @param from The index strictly below which elements are to be examined.
929
* @return Zero if all elements in range are zero, 1 otherwise.
930
*/
931
/*@
932
@ requires 0 <= from && from <= a.length;
933
@ ensures \result == (AP(a, from) == 0 ? 0 : 1);
934
@*/
935
private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
936
while (from > 0) {
937
if (a[--from] != 0) {
938
return 1;
939
}
940
}
941
return 0;
942
}
943
944
/**
945
* Compares the parameter with this <code>FDBigInteger</code>. Returns an
946
* integer accordingly as:
947
* <pre>{@code
948
* > 0: this > other
949
* 0: this == other
950
* < 0: this < other
951
* }</pre>
952
*
953
* @param other The <code>FDBigInteger</code> to compare.
954
* @return A negative value, zero, or a positive value according to the
955
* result of the comparison.
956
*/
957
/*@
958
@ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
959
@*/
960
public /*@ pure @*/ int cmp(FDBigInteger other) {
961
int aSize = nWords + offset;
962
int bSize = other.nWords + other.offset;
963
if (aSize > bSize) {
964
return 1;
965
} else if (aSize < bSize) {
966
return -1;
967
}
968
int aLen = nWords;
969
int bLen = other.nWords;
970
while (aLen > 0 && bLen > 0) {
971
int a = data[--aLen];
972
int b = other.data[--bLen];
973
if (a != b) {
974
return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
975
}
976
}
977
if (aLen > 0) {
978
return checkZeroTail(data, aLen);
979
}
980
if (bLen > 0) {
981
return -checkZeroTail(other.data, bLen);
982
}
983
return 0;
984
}
985
986
/**
987
* Compares this <code>FDBigInteger</code> with
988
* <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
989
* Returns an integer accordingly as:
990
* <pre>{@code
991
* > 0: this > other
992
* 0: this == other
993
* < 0: this < other
994
* }</pre>
995
* @param p5 The exponent of the power-of-five factor.
996
* @param p2 The exponent of the power-of-two factor.
997
* @return A negative value, zero, or a positive value according to the
998
* result of the comparison.
999
*/
1000
/*@
1001
@ requires p5 >= 0 && p2 >= 0;
1002
@ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
1003
@*/
1004
public /*@ pure @*/ int cmpPow52(int p5, int p2) {
1005
if (p5 == 0) {
1006
int wordcount = p2 >> 5;
1007
int bitcount = p2 & 0x1f;
1008
int size = this.nWords + this.offset;
1009
if (size > wordcount + 1) {
1010
return 1;
1011
} else if (size < wordcount + 1) {
1012
return -1;
1013
}
1014
int a = this.data[this.nWords -1];
1015
int b = 1 << bitcount;
1016
if (a != b) {
1017
return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
1018
}
1019
return checkZeroTail(this.data, this.nWords - 1);
1020
}
1021
return this.cmp(big5pow(p5).leftShift(p2));
1022
}
1023
1024
/**
1025
* Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
1026
* value according to the comparison as:
1027
* <pre>{@code
1028
* -1: this < x + y
1029
* 0: this == x + y
1030
* 1: this > x + y
1031
* }</pre>
1032
* @param x The first addend of the sum to compare.
1033
* @param y The second addend of the sum to compare.
1034
* @return -1, 0, or 1 according to the result of the comparison.
1035
*/
1036
/*@
1037
@ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
1038
@*/
1039
public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
1040
FDBigInteger big;
1041
FDBigInteger small;
1042
int xSize = x.size();
1043
int ySize = y.size();
1044
int bSize;
1045
int sSize;
1046
if (xSize >= ySize) {
1047
big = x;
1048
small = y;
1049
bSize = xSize;
1050
sSize = ySize;
1051
} else {
1052
big = y;
1053
small = x;
1054
bSize = ySize;
1055
sSize = xSize;
1056
}
1057
int thSize = this.size();
1058
if (bSize == 0) {
1059
return thSize == 0 ? 0 : 1;
1060
}
1061
if (sSize == 0) {
1062
return this.cmp(big);
1063
}
1064
if (bSize > thSize) {
1065
return -1;
1066
}
1067
if (bSize + 1 < thSize) {
1068
return 1;
1069
}
1070
long top = (big.data[big.nWords - 1] & LONG_MASK);
1071
if (sSize == bSize) {
1072
top += (small.data[small.nWords - 1] & LONG_MASK);
1073
}
1074
if ((top >>> 32) == 0) {
1075
if (((top + 1) >>> 32) == 0) {
1076
// good case - no carry extension
1077
if (bSize < thSize) {
1078
return 1;
1079
}
1080
// here sum.nWords == this.nWords
1081
long v = (this.data[this.nWords - 1] & LONG_MASK);
1082
if (v < top) {
1083
return -1;
1084
}
1085
if (v > top + 1) {
1086
return 1;
1087
}
1088
}
1089
} else { // (top>>>32)!=0 guaranteed carry extension
1090
if (bSize + 1 > thSize) {
1091
return -1;
1092
}
1093
// here sum.nWords == this.nWords
1094
top >>>= 32;
1095
long v = (this.data[this.nWords - 1] & LONG_MASK);
1096
if (v < top) {
1097
return -1;
1098
}
1099
if (v > top + 1) {
1100
return 1;
1101
}
1102
}
1103
return this.cmp(big.add(small));
1104
}
1105
1106
/**
1107
* Makes this <code>FDBigInteger</code> immutable.
1108
*/
1109
/*@
1110
@ assignable this.isImmutable;
1111
@ ensures this.isImmutable;
1112
@*/
1113
public void makeImmutable() {
1114
this.isImmutable = true;
1115
}
1116
1117
/**
1118
* Multiplies this <code>FDBigInteger</code> by an integer.
1119
*
1120
* @param i The factor by which to multiply this <code>FDBigInteger</code>.
1121
* @return This <code>FDBigInteger</code> multiplied by an integer.
1122
*/
1123
/*@
1124
@ requires this.value() == 0;
1125
@ assignable \nothing;
1126
@ ensures \result == this;
1127
@
1128
@ also
1129
@
1130
@ requires this.value() != 0;
1131
@ assignable \nothing;
1132
@ ensures \result.value() == \old(this.value() * UNSIGNED(i));
1133
@*/
1134
private FDBigInteger mult(int i) {
1135
if (this.nWords == 0) {
1136
return this;
1137
}
1138
int[] r = new int[nWords + 1];
1139
mult(data, nWords, i, r);
1140
return new FDBigInteger(r, offset);
1141
}
1142
1143
/**
1144
* Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
1145
*
1146
* @param other The <code>FDBigInteger</code> factor by which to multiply.
1147
* @return The product of this and the parameter <code>FDBigInteger</code>s.
1148
*/
1149
/*@
1150
@ requires this.value() == 0;
1151
@ assignable \nothing;
1152
@ ensures \result == this;
1153
@
1154
@ also
1155
@
1156
@ requires this.value() != 0 && other.value() == 0;
1157
@ assignable \nothing;
1158
@ ensures \result == other;
1159
@
1160
@ also
1161
@
1162
@ requires this.value() != 0 && other.value() != 0;
1163
@ assignable \nothing;
1164
@ ensures \result.value() == \old(this.value() * other.value());
1165
@*/
1166
private FDBigInteger mult(FDBigInteger other) {
1167
if (this.nWords == 0) {
1168
return this;
1169
}
1170
if (this.size() == 1) {
1171
return other.mult(data[0]);
1172
}
1173
if (other.nWords == 0) {
1174
return other;
1175
}
1176
if (other.size() == 1) {
1177
return this.mult(other.data[0]);
1178
}
1179
int[] r = new int[nWords + other.nWords];
1180
mult(this.data, this.nWords, other.data, other.nWords, r);
1181
return new FDBigInteger(r, this.offset + other.offset);
1182
}
1183
1184
/**
1185
* Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
1186
*
1187
* @param other The <code>FDBigInteger</code> to add.
1188
* @return The sum of the <code>FDBigInteger</code>s.
1189
*/
1190
/*@
1191
@ assignable \nothing;
1192
@ ensures \result.value() == \old(this.value() + other.value());
1193
@*/
1194
private FDBigInteger add(FDBigInteger other) {
1195
FDBigInteger big, small;
1196
int bigLen, smallLen;
1197
int tSize = this.size();
1198
int oSize = other.size();
1199
if (tSize >= oSize) {
1200
big = this;
1201
bigLen = tSize;
1202
small = other;
1203
smallLen = oSize;
1204
} else {
1205
big = other;
1206
bigLen = oSize;
1207
small = this;
1208
smallLen = tSize;
1209
}
1210
int[] r = new int[bigLen + 1];
1211
int i = 0;
1212
long carry = 0L;
1213
for (; i < smallLen; i++) {
1214
carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
1215
+ ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
1216
r[i] = (int) carry;
1217
carry >>= 32; // signed shift.
1218
}
1219
for (; i < bigLen; i++) {
1220
carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
1221
r[i] = (int) carry;
1222
carry >>= 32; // signed shift.
1223
}
1224
r[bigLen] = (int) carry;
1225
return new FDBigInteger(r, 0);
1226
}
1227
1228
1229
/**
1230
* Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
1231
* result is computed in place. This method is intended only to be invoked
1232
* from
1233
* <code>
1234
* FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
1235
* </code>.
1236
*
1237
* @param iv The factor by which to multiply this <code>FDBigInteger</code>.
1238
* @param addend The value to add to the product of this
1239
* <code>FDBigInteger</code> and <code>iv</code>.
1240
*/
1241
/*@
1242
@ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
1243
@ assignable this.data[*];
1244
@ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
1245
@*/
1246
private /*@ helper @*/ void multAddMe(int iv, int addend) {
1247
long v = iv & LONG_MASK;
1248
// unroll 0th iteration, doing addition.
1249
long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
1250
data[0] = (int) p;
1251
p >>>= 32;
1252
for (int i = 1; i < nWords; i++) {
1253
p += v * (data[i] & LONG_MASK);
1254
data[i] = (int) p;
1255
p >>>= 32;
1256
}
1257
if (p != 0L) {
1258
data[nWords++] = (int) p; // will fail noisily if illegal!
1259
}
1260
}
1261
1262
//
1263
// original doc:
1264
//
1265
// do this -=q*S
1266
// returns borrow
1267
//
1268
/**
1269
* Multiplies the parameters and subtracts them from this
1270
* <code>FDBigInteger</code>.
1271
*
1272
* @param q The integer parameter.
1273
* @param S The <code>FDBigInteger</code> parameter.
1274
* @return <code>this - q*S</code>.
1275
*/
1276
/*@
1277
@ ensures nWords == 0 ==> offset == 0;
1278
@ ensures nWords > 0 ==> data[nWords - 1] != 0;
1279
@*/
1280
/*@
1281
@ requires 0 < q && q <= (1L << 31);
1282
@ requires data != null;
1283
@ requires 0 <= nWords && nWords <= data.length && offset >= 0;
1284
@ requires !this.isImmutable;
1285
@ requires this.size() == S.size();
1286
@ requires this != S;
1287
@ assignable this.nWords, this.offset, this.data, this.data[*];
1288
@ ensures -q <= \result && \result <= 0;
1289
@ ensures this.size() == \old(this.size());
1290
@ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
1291
@ ensures this.offset == \old(Math.min(this.offset, S.offset));
1292
@ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
1293
@ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
1294
@ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
1295
@
1296
@ also
1297
@
1298
@ requires q == 0;
1299
@ assignable \nothing;
1300
@ ensures \result == 0;
1301
@*/
1302
private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
1303
long diff = 0L;
1304
if (q != 0) {
1305
int deltaSize = S.offset - this.offset;
1306
if (deltaSize >= 0) {
1307
int[] sd = S.data;
1308
int[] td = this.data;
1309
for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
1310
diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
1311
td[tIndex] = (int) diff;
1312
diff >>= 32; // N.B. SIGNED shift.
1313
}
1314
} else {
1315
deltaSize = -deltaSize;
1316
int[] rd = new int[nWords + deltaSize];
1317
int sIndex = 0;
1318
int rIndex = 0;
1319
int[] sd = S.data;
1320
for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
1321
diff -= q * (sd[sIndex] & LONG_MASK);
1322
rd[rIndex] = (int) diff;
1323
diff >>= 32; // N.B. SIGNED shift.
1324
}
1325
int tIndex = 0;
1326
int[] td = this.data;
1327
for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
1328
diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
1329
rd[rIndex] = (int) diff;
1330
diff >>= 32; // N.B. SIGNED shift.
1331
}
1332
this.nWords += deltaSize;
1333
this.offset -= deltaSize;
1334
this.data = rd;
1335
}
1336
}
1337
return diff;
1338
}
1339
1340
1341
/**
1342
* Multiplies by 10 a big integer represented as an array. The final carry
1343
* is returned.
1344
*
1345
* @param src The array representation of the big integer.
1346
* @param srcLen The number of elements of <code>src</code> to use.
1347
* @param dst The product array.
1348
* @return The final carry of the multiplication.
1349
*/
1350
/*@
1351
@ requires src.length >= srcLen && dst.length >= srcLen;
1352
@ assignable dst[0 .. srcLen - 1];
1353
@ ensures 0 <= \result && \result < 10;
1354
@ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
1355
@*/
1356
private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
1357
long carry = 0;
1358
for (int i = 0; i < srcLen; i++) {
1359
long product = (src[i] & LONG_MASK) * 10L + carry;
1360
dst[i] = (int) product;
1361
carry = product >>> 32;
1362
}
1363
return (int) carry;
1364
}
1365
1366
/**
1367
* Multiplies by a constant value a big integer represented as an array.
1368
* The constant factor is an <code>int</code>.
1369
*
1370
* @param src The array representation of the big integer.
1371
* @param srcLen The number of elements of <code>src</code> to use.
1372
* @param value The constant factor by which to multiply.
1373
* @param dst The product array.
1374
*/
1375
/*@
1376
@ requires src.length >= srcLen && dst.length >= srcLen + 1;
1377
@ assignable dst[0 .. srcLen];
1378
@ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
1379
@*/
1380
private static void mult(int[] src, int srcLen, int value, int[] dst) {
1381
long val = value & LONG_MASK;
1382
long carry = 0;
1383
for (int i = 0; i < srcLen; i++) {
1384
long product = (src[i] & LONG_MASK) * val + carry;
1385
dst[i] = (int) product;
1386
carry = product >>> 32;
1387
}
1388
dst[srcLen] = (int) carry;
1389
}
1390
1391
/**
1392
* Multiplies by a constant value a big integer represented as an array.
1393
* The constant factor is a long represent as two <code>int</code>s.
1394
*
1395
* @param src The array representation of the big integer.
1396
* @param srcLen The number of elements of <code>src</code> to use.
1397
* @param v0 The lower 32 bits of the long factor.
1398
* @param v1 The upper 32 bits of the long factor.
1399
* @param dst The product array.
1400
*/
1401
/*@
1402
@ requires src != dst;
1403
@ requires src.length >= srcLen && dst.length >= srcLen + 2;
1404
@ assignable dst[0 .. srcLen + 1];
1405
@ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
1406
@*/
1407
private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
1408
long v = v0 & LONG_MASK;
1409
long carry = 0;
1410
for (int j = 0; j < srcLen; j++) {
1411
long product = v * (src[j] & LONG_MASK) + carry;
1412
dst[j] = (int) product;
1413
carry = product >>> 32;
1414
}
1415
dst[srcLen] = (int) carry;
1416
v = v1 & LONG_MASK;
1417
carry = 0;
1418
for (int j = 0; j < srcLen; j++) {
1419
long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
1420
dst[j + 1] = (int) product;
1421
carry = product >>> 32;
1422
}
1423
dst[srcLen + 1] = (int) carry;
1424
}
1425
1426
// Fails assertion for negative exponent.
1427
/**
1428
* Computes <code>5</code> raised to a given power.
1429
*
1430
* @param p The exponent of 5.
1431
* @return <code>5<sup>p</sup></code>.
1432
*/
1433
private static FDBigInteger big5pow(int p) {
1434
assert p >= 0 : p; // negative power of 5
1435
if (p < MAX_FIVE_POW) {
1436
return POW_5_CACHE[p];
1437
}
1438
return big5powRec(p);
1439
}
1440
1441
// slow path
1442
/**
1443
* Computes <code>5</code> raised to a given power.
1444
*
1445
* @param p The exponent of 5.
1446
* @return <code>5<sup>p</sup></code>.
1447
*/
1448
private static FDBigInteger big5powRec(int p) {
1449
if (p < MAX_FIVE_POW) {
1450
return POW_5_CACHE[p];
1451
}
1452
// construct the value.
1453
// recursively.
1454
int q, r;
1455
// in order to compute 5^p,
1456
// compute its square root, 5^(p/2) and square.
1457
// or, let q = p / 2, r = p -q, then
1458
// 5^p = 5^(q+r) = 5^q * 5^r
1459
q = p >> 1;
1460
r = p - q;
1461
FDBigInteger bigq = big5powRec(q);
1462
if (r < SMALL_5_POW.length) {
1463
return bigq.mult(SMALL_5_POW[r]);
1464
} else {
1465
return bigq.mult(big5powRec(r));
1466
}
1467
}
1468
1469
// for debugging ...
1470
/**
1471
* Converts this <code>FDBigInteger</code> to a hexadecimal string.
1472
*
1473
* @return The hexadecimal string representation.
1474
*/
1475
public String toHexString(){
1476
if(nWords ==0) {
1477
return "0";
1478
}
1479
StringBuilder sb = new StringBuilder((nWords +offset)*8);
1480
for(int i= nWords -1; i>=0; i--) {
1481
String subStr = Integer.toHexString(data[i]);
1482
for(int j = subStr.length(); j<8; j++) {
1483
sb.append('0');
1484
}
1485
sb.append(subStr);
1486
}
1487
for(int i=offset; i>0; i--) {
1488
sb.append("00000000");
1489
}
1490
return sb.toString();
1491
}
1492
1493
// for debugging ...
1494
/**
1495
* Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
1496
*
1497
* @return The <code>BigInteger</code> representation.
1498
*/
1499
public BigInteger toBigInteger() {
1500
byte[] magnitude = new byte[nWords * 4 + 1];
1501
for (int i = 0; i < nWords; i++) {
1502
int w = data[i];
1503
magnitude[magnitude.length - 4 * i - 1] = (byte) w;
1504
magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
1505
magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
1506
magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
1507
}
1508
return new BigInteger(magnitude).shiftLeft(offset * 32);
1509
}
1510
1511
// for debugging ...
1512
/**
1513
* Converts this <code>FDBigInteger</code> to a string.
1514
*
1515
* @return The string representation.
1516
*/
1517
@Override
1518
public String toString(){
1519
return toBigInteger().toString();
1520
}
1521
}
1522
1523