- Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathInteger.java
369 lines (336 loc) · 11.5 KB
/
Integer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
packageopencrypto.jcmathlib;
importjavacard.framework.JCSystem;
importjavacard.framework.Util;
/**
* @author Vasilios Mavroudis and Petr Svenda
*/
publicclassInteger {
privateResourceManagerrm;
privateBigNatmagnitude;
privatebytesign;
/**
* Allocates integer with provided length and sets to zero.
*
* @param size Integer size
* @param rm ResourceManager with all supporting objects
*/
publicInteger(shortsize, ResourceManagerrm) {
allocate(size, (byte) 0, null, (byte) -1, rm);
}
/**
* Allocates integer from provided buffer and initialize by provided value.
* Sign is expected as first byte of value.
*
* @param value array with initial value
* @param valueOffset start offset within value
* @param length length of array
* @param rm ResourceManager with all supporting objects
*/
publicInteger(byte[] value, shortvalueOffset, shortlength, ResourceManagerrm) {
allocate(length, (value[valueOffset] == (byte) 0x00) ? (byte) 0 : (byte) 1, value, (short) (valueOffset + 1), rm);
}
/**
* Allocates integer from provided array with explicit sign. No sign is expected in provided array.
*
* @param sign sign of integer
* @param value array with initial value
* @param rm ResourceManager with all supporting objects
*/
publicInteger(bytesign, byte[] value, ResourceManagerrm) {
allocate((short) value.length, sign, value, (short) 0, rm);
}
/**
* Copy constructor of integer from other already existing value
*
* @param other integer to copy from
*/
publicInteger(Integerother) {
rm.lock(rm.ARRAY_A);
shortlen = magnitude.copyToByteArray(rm.ARRAY_A, (short) 0);
allocate(len, other.getSign(), rm.ARRAY_A, (short) 0, other.rm);
rm.unlock(rm.ARRAY_A);
}
/**
* Creates integer from existing Bignat and provided sign. If required,
* copy is performed, otherwise BigNat is used as magnitude.
*
* @param sign sign of integer
* @param magnitude initial magnitude
* @param copy if true, magnitude is directly used (no copy). If false, new storage array is allocated.
*/
publicInteger(bytesign, BigNatmagnitude, booleancopy, ResourceManagerrm) {
if (copy) {
// Copy from provided BigNat
rm.lock(rm.ARRAY_A);
shortlen = magnitude.copyToByteArray(rm.ARRAY_A, (short) 0);
allocate(len, sign, rm.ARRAY_A, (short) 0, rm);
rm.unlock(rm.ARRAY_A);
} else {
// Use directly provided BigNat as storage - no allocation
initialize(sign, magnitude, rm);
}
}
/**
* Initialize integer object with provided sign and already allocated Bignat
* as magnitude
*
* @param sign sign of integer
* @param bnStorage magnitude (object is directly used, no copy is performed)
*/
privatevoidinitialize(bytesign, BigNatbnStorage, ResourceManagerrm) {
this.sign = sign;
this.magnitude = bnStorage;
this.rm = rm;
}
/**
* Allocates and initializes Integer.
*
* @param size length of integer
* @param sign sign of integer
* @param fromArray input array with initial value (copy of value is
* performed)
* @param fromArrayOffset start offset within fromArray
*/
privatevoidallocate(shortsize, bytesign, byte[] fromArray, shortfromArrayOffset, ResourceManagerrm) {
this.rm = rm;
BigNatmag = newBigNat(size, JCSystem.MEMORY_TYPE_TRANSIENT_RESET, this.rm);
if (fromArray != null) {
mag.fromByteArray(fromArray, fromArrayOffset, size);
}
initialize(sign, mag, this.rm);
}
/**
* Clone value into this Integer from other Integer. Updates size of integer.
*
* @param other other integer to copy from
*/
publicvoidclone(Integerother) {
this.sign = other.getSign();
this.magnitude.copy(other.getMagnitude());
}
/**
* set this integer to zero
*/
publicvoidzero() {
this.sign = (short) 0;
this.magnitude.zero();
}
/**
* Return sign of this integer
*
* @return current sign
*/
publicbytegetSign() {
returnthis.sign;
}
/**
* Set sign of this integer
*
* @param s new sign
*/
publicvoidsetSign(bytes) {
this.sign = s;
}
/**
* Return length (in bytes) of this integer
*
* @return length of this integer
*/
publicshortgetSize() {
returnthis.magnitude.length();
}
/**
* Set length of this integer
*
* @param newSize new length
*/
publicvoidsetSize(shortnewSize) {
this.magnitude.setSize(newSize);
}
/**
* Compute negation of this integer
*/
publicvoidnegate() {
if (this.isPositive()) {
this.setSign((byte) 1);
} elseif (this.isNegative()) {
this.setSign((byte) 0);
}
}
/**
* Returns magnitude as Bignat. No copy is performed so change of Bignat also changes this integer
*
* @return Bignat representing magnitude
*/
publicBigNatgetMagnitude() {
returnthis.magnitude;
}
/**
* Set magnitude of this integer from other one. Will not change this integer length.
* No sign is copied from other.
*
* @param other other integer to copy from
*/
publicvoidsetMagnitude(Integerother) {
this.magnitude.copy(other.getMagnitude());
}
/**
* Serializes this integer value into array. Sign is serialized as first byte
*
* @param outBuffer output array
* @param outBufferOffset start offset within output array
* @return length of resulting serialized number including sign (number of bytes)
*/
publicshorttoByteArray(byte[] outBuffer, shortoutBufferOffset) {
//Store sign
outBuffer[outBufferOffset] = sign;
//Store magnitude
magnitude.copyToByteArray(outBuffer, (short) (outBufferOffset + 1));
return (short) (this.getSize() + 1);
}
/**
* Deserialize value of this integer from provided array including sign.
* Sign is expected to be as first byte
*
* @param value array with value
* @param valueOffset start offset within value
* @param valueLength length of value
*/
publicvoidfromByteArray(byte[] value, shortvalueOffset, shortvalueLength) {
//Store sign
this.sign = value[valueOffset];
//Store magnitude
this.magnitude.fromByteArray(value, (short) (valueOffset + 1), (short) (valueLength - 1));
}
/**
* Return true if integer is negative.
*
* @return true if integer is negative, false otherwise
*/
publicbooleanisNegative() {
returnthis.sign == 1;
}
/**
* Return true if integer is positive.
*
* @return true if integer is positive, false otherwise
*/
publicbooleanisPositive() {
returnthis.sign == 0;
}
/**
* Compares two integers. Return true, if this is smaller than other.
*
* @param other other integer to compare
* @return true, if this is strictly smaller than other. False otherwise.
*/
publicbooleanlesser(Integerother) {
if (this.sign == 1 && other.sign == 0) {
returntrue;
} elseif (this.sign == 0 && other.sign == 1) {
returnfalse;
} elseif ((this.sign == 0 && other.sign == 0)) {
returnthis.magnitude.isLesser(other.magnitude);
} else { //if ((this.sign == 1 && other.sign==1))
return (!this.magnitude.isLesser(other.magnitude));
}
}
/**
* Add other integer to this and store result into this.
*
* @param other other integer to add
*/
publicvoidadd(Integerother) {
BigNattmp = rm.BN_A;
if (this.isPositive() && other.isPositive()) { //this and other are (+)
this.sign = 0;
this.magnitude.add(other.magnitude);
} elseif (this.isNegative() && other.isNegative()) { //this and other are (-)
this.sign = 1;
this.magnitude.add(other.magnitude);
} else {
if (this.isPositive() && other.getMagnitude().isLesser(this.getMagnitude())) { //this(+) is larger than other(-)
this.sign = 0;
this.magnitude.subtract(other.magnitude);
} elseif (this.isNegative() && other.getMagnitude().isLesser(this.getMagnitude())) { //this(-) has larger magnitude than other(+)
this.sign = 1;
this.magnitude.subtract(other.magnitude);
} elseif (this.isPositive() && this.getMagnitude().isLesser(other.getMagnitude())) { //this(+) has smaller magnitude than other(-)
this.sign = 1;
tmp.lock();
tmp.clone(other.getMagnitude());
tmp.subtract(this.magnitude);
this.magnitude.copy(tmp);
tmp.unlock();
} elseif (this.isNegative() && this.getMagnitude().isLesser(other.getMagnitude())) { //this(-) has larger magnitude than other(+)
this.sign = 0;
tmp.lock();
tmp.clone(other.getMagnitude());
tmp.subtract(this.magnitude);
this.magnitude.copy(tmp);
tmp.unlock();
} elseif (this.getMagnitude().equals(other.getMagnitude())) { //this has opposite sign than other, and the same magnitude
this.sign = 0;
this.zero();
}
}
}
/**
* Substract other integer from this and store result into this.
*
* @param other other integer to substract
*/
publicvoidsubtract(Integerother) {
other.negate(); // Potentially problematic - failure and exception in subsequent function will cause other to stay negated
this.add(other);
// Restore original sign for other
other.negate();
}
/**
* Multiply this and other integer and store result into this.
*
* @param other other integer to multiply
*/
publicvoidmultiply(Integerother) {
BigNattmp = rm.BN_B;
if (this.isPositive() && other.isNegative()) {
this.setSign((byte) 1);
} elseif (this.isNegative() && other.isPositive()) {
this.setSign((byte) 1);
} else {
this.setSign((byte) 0);
}
tmp.lock();
tmp.clone(this.magnitude);
tmp.mult(other.getMagnitude());
this.magnitude.copy(tmp);
tmp.unlock();
}
/**
* Divide this by other integer and store result into this.
*
* @param other divisor
*/
publicvoiddivide(Integerother) {
BigNattmp = rm.BN_A;
if (this.isPositive() && other.isNegative()) {
this.setSign((byte) 1);
} elseif (this.isNegative() && other.isPositive()) {
this.setSign((byte) 1);
} else {
this.setSign((byte) 0);
}
tmp.lock();
tmp.clone(this.magnitude);
tmp.remainderDivide(other.getMagnitude(), this.magnitude);
tmp.unlock();
}
/**
* Computes modulo of this by other integer and store result into this.
*
* @param other modulus
*/
publicvoidmodulo(Integerother) {
this.magnitude.mod(other.getMagnitude());
}
}