@@ -56,9 +56,9 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
56
56
self.isSigned = false
57
57
self.isSecret = false
58
58
typeswitch value {
59
- Int | Uint {
59
+ Int | Uint => {
60
60
if widthof(value) > kMaxBigintWidth {
61
- throw "Integer width too large. Pass in BigintArray instead."
61
+ panic "Integer width too large. Pass in BigintArray instead."
62
62
}
63
63
if width != 0 {
64
64
self.width = width
@@ -76,9 +76,9 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
76
76
self.bigint = runtime.integerToBigint(!<u64>value, self.width,
77
77
self.isSigned, self.isSecret)
78
78
}
79
- runtime.BigintArray {
79
+ runtime.BigintArray => {
80
80
if width != 0 {
81
- throw "Can't change bigint width in Bigint constructor. Use cast instead."
81
+ panic "Can't change bigint width in Bigint constructor. Use cast instead."
82
82
}
83
83
self.isSigned = runtime.bigintSigned(value)
84
84
self.width = runtime.bigintWidth(value)
@@ -103,119 +103,157 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
103
103
return text
104
104
}
105
105
106
+ // Return a string representation of the number Little-Endian.
107
+ func toStringLE(self) {
108
+ s = ""
109
+ runtime.bigintEncodeLittleEndian(s, self.bigint)
110
+ return s
111
+ }
112
+
113
+ // Convert a string Little-Endian representation to a Bigint.
114
+ func fromStringLE(s: string, width: u32, isSigned: bool = false, isSecret: bool = false) {
115
+ bigint = arrayof(u32)
116
+ runtime.bigintDecodeLittleEndian(bigint, s, width, isSigned, isSecret)
117
+ return Bigint(bigint)
118
+ }
119
+
120
+ // Return a string representation of the number Big-Endian.
121
+ func toStringBE(self) {
122
+ s = ""
123
+ runtime.bigintEncodeBigEndian(s, self.bigint)
124
+ return s
125
+ }
126
+
127
+ // Convert a string Big-Endian representation to a Bigint.
128
+ func fromStringBE(s: string, width: u32, isSigned: bool = false, isSecret: bool = false) {
129
+ bigint = arrayof(u32)
130
+ runtime.bigintDecodeBigEndian(bigint, s, width, isSigned, isSecret)
131
+ return Bigint(bigint)
132
+ }
133
+
106
134
// Cast the bigint to a different width, sign, or even secret status.
107
- export func cast(self, newWidth: u32, isSigned: bool, isSecret: bool, truncate: bool) {
135
+ func cast(self, newWidth: u32, isSigned: bool, isSecret: bool, truncate: bool = false) -> Bigint {
108
136
return Bigint(runtime.bigintCast(self.bigint, newWidth, isSigned, isSecret, truncate))
109
137
}
110
138
139
+ // Resize the bigint to a different width.
140
+ func resize(self, newWidth: u32, truncate: bool = false) -> Bigint {
141
+ return self.cast(newWidth, self.isSigned, self.isSecret, truncate)
142
+ }
143
+
144
+ // Set to signed or unsinged.
145
+ func toSigned(self, isSigned: bool = true, truncate: bool = false) -> Bigint {
146
+ return self.cast(self.width, isSigned, self.isSecret, truncate)
147
+ }
148
+
111
149
// Overload the + operator.
112
150
operator + (a: Bigint, b: Bigint) -> Bigint {
113
151
if a.width != b.width || a.isSigned != b.isSigned {
114
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
152
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
115
153
}
116
154
return Bigint(runtime.bigintAdd(a.bigint, b.bigint))
117
155
}
118
156
119
157
// Overload the !+ operator.
120
158
operator !+ (a: Bigint, b: Bigint) -> Bigint {
121
159
if a.width != b.width || a.isSigned != b.isSigned {
122
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
160
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
123
161
}
124
162
return Bigint(runtime.bigintAddTrunc(a.bigint, b.bigint))
125
163
}
126
164
127
165
// Overload the - operator.
128
166
operator - (a: Bigint, b: Bigint) -> Bigint {
129
167
if a.width != b.width || a.isSigned != b.isSigned {
130
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
168
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
131
169
}
132
170
return Bigint(runtime.bigintSub(a.bigint, b.bigint))
133
171
}
134
172
135
173
// Overload the !- operator.
136
174
operator !- (a: Bigint, b: Bigint) -> Bigint {
137
175
if a.width != b.width || a.isSigned != b.isSigned {
138
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
176
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
139
177
}
140
178
return Bigint(runtime.bigintSubTrunc(a.bigint, b.bigint))
141
179
}
142
180
143
181
// Overload the * operator.
144
182
operator * (a: Bigint, b: Bigint) -> Bigint {
145
183
if a.width != b.width || a.isSigned != b.isSigned {
146
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
184
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
147
185
}
148
186
return Bigint(runtime.bigintMul(a.bigint, b.bigint))
149
187
}
150
188
151
189
// Overload the !* operator.
152
190
operator !* (a: Bigint, b: Bigint) -> Bigint {
153
191
if a.width != b.width || a.isSigned != b.isSigned {
154
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
192
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
155
193
}
156
194
return Bigint(runtime.bigintMulTrunc(a.bigint, b.bigint))
157
195
}
158
196
159
197
// Overload the / operator.
160
198
operator / (a: Bigint, b: Bigint) -> Bigint {
161
199
if a.width != b.width || a.isSigned != b.isSigned {
162
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
200
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
163
201
}
164
202
return Bigint(runtime.bigintDiv(a.bigint, b.bigint))
165
203
}
166
204
167
205
// Overload the % operator.
168
206
operator % (a: Bigint, b: Bigint) -> Bigint {
169
207
if a.width != b.width || a.isSigned != b.isSigned {
170
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
208
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
171
209
}
172
210
return Bigint(runtime.bigintMod(a.bigint, b.bigint))
173
211
}
174
212
175
213
// Overload the == operator.
176
214
operator == (a: Bigint, b: Bigint) -> bool {
177
215
if a.width != b.width || a.isSigned != b.isSigned {
178
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
216
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
179
217
}
180
218
return runtime.compareBigints(runtime.ComparisonType.Equal, a.bigint, b.bigint)
181
219
}
182
220
183
221
// Overload the != operator.
184
222
operator != (a: Bigint, b: Bigint) -> bool {
185
223
if a.width != b.width || a.isSigned != b.isSigned {
186
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
224
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
187
225
}
188
226
return runtime.compareBigints(runtime.ComparisonType.NotEqual, a.bigint, b.bigint)
189
227
}
190
228
191
229
// Overload the < operator.
192
230
operator < (a: Bigint, b: Bigint) -> bool {
193
231
if a.width != b.width || a.isSigned != b.isSigned {
194
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
232
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
195
233
}
196
234
return runtime.compareBigints(runtime.ComparisonType.Lt, a.bigint, b.bigint)
197
235
}
198
236
199
237
// Overload the <= operator.
200
238
operator <= (a: Bigint, b: Bigint) -> bool {
201
239
if a.width != b.width || a.isSigned != b.isSigned {
202
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
240
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
203
241
}
204
242
return runtime.compareBigints(runtime.ComparisonType.Le, a.bigint, b.bigint)
205
243
}
206
244
207
245
// Overload the > operator.
208
246
operator > (a: Bigint, b: Bigint) -> bool {
209
247
if a.width != b.width || a.isSigned != b.isSigned {
210
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
248
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
211
249
}
212
250
return runtime.compareBigints(runtime.ComparisonType.Gt, a.bigint, b.bigint)
213
251
}
214
252
215
253
// Overload the >= operator.
216
254
operator >= (a: Bigint, b: Bigint) -> bool {
217
255
if a.width != b.width || a.isSigned != b.isSigned {
218
- throw "Integers have different types: ", a.toString(), " and ", b.toString()
256
+ panic "Integers have different types: ", a.toString(), " and ", b.toString()
219
257
}
220
258
return runtime.compareBigints(runtime.ComparisonType.Ge, a.bigint, b.bigint)
221
259
}
@@ -274,6 +312,34 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
274
312
operator ^ (a: Bigint, b: Bigint) -> Bigint {
275
313
return Bigint(runtime.bigintBitwiseXor(a.bigint, b.bigint))
276
314
}
315
+
316
+ // Overload the cast operator.
317
+ operator <> (a: Bigint | Int | Uint, b: Bigint | Int | Uint) -> Bigint | Int | Uint {
318
+ typeswitch a {
319
+ Bigint => {
320
+ typeswitch b {
321
+ Int | Uint => return Bigint(b, a.width)
322
+ Bigint => return b.cast(a.width, a.isSigned, b.isSecret, false)
323
+ }
324
+ }
325
+ Int | Uint => {
326
+ // b must be a Bigint
327
+ val = b.resize(widthof(a), true)
328
+ if val.resize(b.width) != b {
329
+ panic "Bigint does not fit in ", widthof(a), " bits"
330
+ }
331
+ typeswitch a {
332
+ Uint => {
333
+ }
334
+ Int => {
335
+ val = val.toSigned()
336
+ }
337
+ }
338
+ s = val.toStringLE()
339
+ return s.toUintLE(typeof(a))
340
+ }
341
+ }
342
+ }
277
343
}
278
344
279
345
// Test printing and addition.
@@ -299,6 +365,12 @@ unittest testCasting {
299
365
c = b + Bigint(1i32, 256u32)
300
366
assert c.width == 256u32
301
367
println c
368
+ d = <c>123
369
+ println "d = ", d
370
+ e = <typeof(null(d))>0u32 // This dangerous cast converts 0 to null(Bigint).
371
+ assert isnull(e)
372
+ f = <b>a + b
373
+ println "f = ", f
302
374
}
303
375
304
376
// Test comparison operators.
@@ -386,3 +458,33 @@ unittest testBitwiseOperators {
386
458
assert a | b == Bigint(0xffffu16)
387
459
assert a ^ (b >> 1u32) == Bigint(0x7f7fu16)
388
460
}
461
+
462
+ unittest testResize {
463
+ a = Bigint(123)
464
+ a.resize(32u32)
465
+ println a
466
+ }
467
+
468
+ unittest testToFromEncodedStrings {
469
+ m1 = Bigint(2, 256u32) ** 255u32 - Bigint(19, 256u32)
470
+ println "m1 = ", m1
471
+ mStr = m1.toStringLE()
472
+ m2 = Bigint.fromStringLE(mStr, 256u32, false)
473
+ println "m2 = ", m2
474
+ assert m1 == m2
475
+ m3 = Bigint(-123i100)
476
+ println "m3 = ", m3
477
+ mStr = m3.toStringBE()
478
+ m4 = Bigint.fromStringBE(mStr, 100u32, true)
479
+ println "m4 = ", m4
480
+ assert m3 == m4
481
+ }
482
+
483
+ unittest testToSigned {
484
+ val = Bigint(1, 2u32)
485
+ println val
486
+ signedVal = val.toSigned()
487
+ signedVal = -signedVal
488
+ println signedVal
489
+ assert (-signedVal).toSigned(false) == val
490
+ }
0 commit comments