1const std = @import("../../std.zig");
2const mem = std.mem;
3const testing = std.testing;
4const Managed = std.math.big.int.Managed;
5const Mutable = std.math.big.int.Mutable;
6const Limb = std.math.big.Limb;
7const SignedLimb = std.math.big.SignedLimb;
8const DoubleLimb = std.math.big.DoubleLimb;
9const SignedDoubleLimb = std.math.big.SignedDoubleLimb;
10const calcTwosCompLimbCount = std.math.big.int.calcTwosCompLimbCount;
11const maxInt = std.math.maxInt;
12const minInt = std.math.minInt;
13
14// NOTE: All the following tests assume the max machine-word will be 64-bit.
15//
16// They will still run on larger than this and should pass, but the multi-limb code-paths
17// may be untested in some cases.
18
19fn expectNormalized(expected: comptime_int, actual: std.math.big.int.Const) !void {
20 try testing.expectEqual(expected >= 0, actual.positive);
21 try testing.expectEqual(std.math.big.int.calcLimbLen(expected), actual.limbs.len);
22 try testing.expect(actual.orderAgainstScalar(expected).compare(.eq));
23}
24
25test "comptime_int set" {
26 comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;
27 var a = try Managed.initSet(testing.allocator, s);
28 defer a.deinit();
29
30 const s_limb_count = 128 / @typeInfo(Limb).int.bits;
31
32 comptime var i: usize = 0;
33 inline while (i < s_limb_count) : (i += 1) {
34 const result = @as(Limb, s & maxInt(Limb));
35 s >>= @typeInfo(Limb).int.bits / 2;
36 s >>= @typeInfo(Limb).int.bits / 2;
37 try testing.expectEqual(result, a.limbs[i]);
38 }
39}
40
41test "comptime_int set negative" {
42 var a = try Managed.initSet(testing.allocator, -10);
43 defer a.deinit();
44
45 try testing.expectEqual(10, a.limbs[0]);
46 try testing.expectEqual(false, a.isPositive());
47}
48
49test "int set unaligned small" {
50 var a = try Managed.initSet(testing.allocator, @as(u7, 45));
51 defer a.deinit();
52
53 try testing.expectEqual(45, a.limbs[0]);
54 try testing.expectEqual(true, a.isPositive());
55}
56
57test "comptime_int to" {
58 var a = try Managed.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
59 defer a.deinit();
60
61 try testing.expectEqual(0xefffffff00000001eeeeeeefaaaaaaab, try a.toInt(u128));
62}
63
64test "sub-limb to" {
65 var a = try Managed.initSet(testing.allocator, 10);
66 defer a.deinit();
67
68 try testing.expectEqual(10, try a.toInt(u8));
69}
70
71test "set negative minimum" {
72 var a = try Managed.initSet(testing.allocator, @as(i64, minInt(i64)));
73 defer a.deinit();
74
75 try testing.expectEqual(minInt(i64), try a.toInt(i64));
76}
77
78test "set double-width maximum then zero" {
79 var a = try Managed.initSet(testing.allocator, maxInt(DoubleLimb));
80 defer a.deinit();
81 try a.set(@as(DoubleLimb, 0));
82
83 try testing.expectEqual(@as(DoubleLimb, 0), try a.toInt(DoubleLimb));
84}
85
86test "to target too small error" {
87 var a = try Managed.initSet(testing.allocator, 0xffffffff);
88 defer a.deinit();
89
90 try testing.expectError(error.TargetTooSmall, a.toInt(u8));
91}
92
93fn setFloat(comptime Float: type) !void {
94 var res_limbs: [std.math.big.int.calcNonZeroTwosCompLimbCount(11)]Limb = undefined;
95 var res: Mutable = .{
96 .limbs = &res_limbs,
97 .len = undefined,
98 .positive = undefined,
99 };
100
101 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0x1p10), .nearest_even));
102 try expectNormalized(-1 << 10, res.toConst());
103 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0x1p10), .away));
104 try expectNormalized(-1 << 10, res.toConst());
105 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0x1p10), .trunc));
106 try expectNormalized(-1 << 10, res.toConst());
107 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0x1p10), .floor));
108 try expectNormalized(-1 << 10, res.toConst());
109 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0x1p10), .ceil));
110 try expectNormalized(-1 << 10, res.toConst());
111
112 try testing.expectEqual(.exact, res.setFloat(@as(Float, -2.0), .nearest_even));
113 try expectNormalized(-2, res.toConst());
114 try testing.expectEqual(.exact, res.setFloat(@as(Float, -2.0), .away));
115 try expectNormalized(-2, res.toConst());
116 try testing.expectEqual(.exact, res.setFloat(@as(Float, -2.0), .trunc));
117 try expectNormalized(-2, res.toConst());
118 try testing.expectEqual(.exact, res.setFloat(@as(Float, -2.0), .floor));
119 try expectNormalized(-2, res.toConst());
120 try testing.expectEqual(.exact, res.setFloat(@as(Float, -2.0), .ceil));
121 try expectNormalized(-2, res.toConst());
122
123 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -1.5), .nearest_even));
124 try expectNormalized(-2, res.toConst());
125 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -1.5), .away));
126 try expectNormalized(-2, res.toConst());
127 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -1.5), .trunc));
128 try expectNormalized(-1, res.toConst());
129 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -1.5), .floor));
130 try expectNormalized(-2, res.toConst());
131 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -1.5), .ceil));
132 try expectNormalized(-1, res.toConst());
133
134 try testing.expectEqual(.exact, res.setFloat(@as(Float, -1.0), .nearest_even));
135 try expectNormalized(-1, res.toConst());
136 try testing.expectEqual(.exact, res.setFloat(@as(Float, -1.0), .away));
137 try expectNormalized(-1, res.toConst());
138 try testing.expectEqual(.exact, res.setFloat(@as(Float, -1.0), .trunc));
139 try expectNormalized(-1, res.toConst());
140 try testing.expectEqual(.exact, res.setFloat(@as(Float, -1.0), .floor));
141 try expectNormalized(-1, res.toConst());
142 try testing.expectEqual(.exact, res.setFloat(@as(Float, -1.0), .ceil));
143 try expectNormalized(-1, res.toConst());
144
145 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.75), .nearest_even));
146 try expectNormalized(-1, res.toConst());
147 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.75), .away));
148 try expectNormalized(-1, res.toConst());
149 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.75), .trunc));
150 try expectNormalized(0, res.toConst());
151 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.75), .floor));
152 try expectNormalized(-1, res.toConst());
153 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.75), .ceil));
154 try expectNormalized(0, res.toConst());
155
156 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.5), .nearest_even));
157 try expectNormalized(0, res.toConst());
158 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.5), .away));
159 try expectNormalized(-1, res.toConst());
160 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.5), .trunc));
161 try expectNormalized(0, res.toConst());
162 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.5), .floor));
163 try expectNormalized(-1, res.toConst());
164 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.5), .ceil));
165 try expectNormalized(0, res.toConst());
166
167 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.25), .nearest_even));
168 try expectNormalized(0, res.toConst());
169 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.25), .away));
170 try expectNormalized(-1, res.toConst());
171 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.25), .trunc));
172 try expectNormalized(0, res.toConst());
173 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.25), .floor));
174 try expectNormalized(-1, res.toConst());
175 try testing.expectEqual(.inexact, res.setFloat(@as(Float, -0.25), .ceil));
176 try expectNormalized(0, res.toConst());
177
178 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0.0), .nearest_even));
179 try expectNormalized(0, res.toConst());
180 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0.0), .away));
181 try expectNormalized(0, res.toConst());
182 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0.0), .trunc));
183 try expectNormalized(0, res.toConst());
184 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0.0), .floor));
185 try expectNormalized(0, res.toConst());
186 try testing.expectEqual(.exact, res.setFloat(@as(Float, -0.0), .ceil));
187 try expectNormalized(0, res.toConst());
188
189 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0.0), .nearest_even));
190 try expectNormalized(0, res.toConst());
191 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0.0), .away));
192 try expectNormalized(0, res.toConst());
193 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0.0), .trunc));
194 try expectNormalized(0, res.toConst());
195 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0.0), .floor));
196 try expectNormalized(0, res.toConst());
197 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0.0), .ceil));
198 try expectNormalized(0, res.toConst());
199
200 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.25), .nearest_even));
201 try expectNormalized(0, res.toConst());
202 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.25), .away));
203 try expectNormalized(1, res.toConst());
204 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.25), .trunc));
205 try expectNormalized(0, res.toConst());
206 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.25), .floor));
207 try expectNormalized(0, res.toConst());
208 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.25), .ceil));
209 try expectNormalized(1, res.toConst());
210
211 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.5), .nearest_even));
212 try expectNormalized(0, res.toConst());
213 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.5), .away));
214 try expectNormalized(1, res.toConst());
215 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.5), .trunc));
216 try expectNormalized(0, res.toConst());
217 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.5), .floor));
218 try expectNormalized(0, res.toConst());
219 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.5), .ceil));
220 try expectNormalized(1, res.toConst());
221
222 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.75), .nearest_even));
223 try expectNormalized(1, res.toConst());
224 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.75), .away));
225 try expectNormalized(1, res.toConst());
226 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.75), .trunc));
227 try expectNormalized(0, res.toConst());
228 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.75), .floor));
229 try expectNormalized(0, res.toConst());
230 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 0.75), .ceil));
231 try expectNormalized(1, res.toConst());
232
233 try testing.expectEqual(.exact, res.setFloat(@as(Float, 1.0), .nearest_even));
234 try expectNormalized(1, res.toConst());
235 try testing.expectEqual(.exact, res.setFloat(@as(Float, 1.0), .away));
236 try expectNormalized(1, res.toConst());
237 try testing.expectEqual(.exact, res.setFloat(@as(Float, 1.0), .trunc));
238 try expectNormalized(1, res.toConst());
239 try testing.expectEqual(.exact, res.setFloat(@as(Float, 1.0), .floor));
240 try expectNormalized(1, res.toConst());
241 try testing.expectEqual(.exact, res.setFloat(@as(Float, 1.0), .ceil));
242 try expectNormalized(1, res.toConst());
243
244 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 1.5), .nearest_even));
245 try expectNormalized(2, res.toConst());
246 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 1.5), .away));
247 try expectNormalized(2, res.toConst());
248 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 1.5), .trunc));
249 try expectNormalized(1, res.toConst());
250 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 1.5), .floor));
251 try expectNormalized(1, res.toConst());
252 try testing.expectEqual(.inexact, res.setFloat(@as(Float, 1.5), .ceil));
253 try expectNormalized(2, res.toConst());
254
255 try testing.expectEqual(.exact, res.setFloat(@as(Float, 2.0), .nearest_even));
256 try expectNormalized(2, res.toConst());
257 try testing.expectEqual(.exact, res.setFloat(@as(Float, 2.0), .away));
258 try expectNormalized(2, res.toConst());
259 try testing.expectEqual(.exact, res.setFloat(@as(Float, 2.0), .trunc));
260 try expectNormalized(2, res.toConst());
261 try testing.expectEqual(.exact, res.setFloat(@as(Float, 2.0), .floor));
262 try expectNormalized(2, res.toConst());
263 try testing.expectEqual(.exact, res.setFloat(@as(Float, 2.0), .ceil));
264 try expectNormalized(2, res.toConst());
265
266 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0x1p10), .nearest_even));
267 try expectNormalized(1 << 10, res.toConst());
268 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0x1p10), .away));
269 try expectNormalized(1 << 10, res.toConst());
270 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0x1p10), .trunc));
271 try expectNormalized(1 << 10, res.toConst());
272 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0x1p10), .floor));
273 try expectNormalized(1 << 10, res.toConst());
274 try testing.expectEqual(.exact, res.setFloat(@as(Float, 0x1p10), .ceil));
275 try expectNormalized(1 << 10, res.toConst());
276}
277test setFloat {
278 try setFloat(f16);
279 try setFloat(f32);
280 try setFloat(f64);
281 try setFloat(f80);
282 try setFloat(f128);
283 try setFloat(c_longdouble);
284 try setFloat(comptime_float);
285}
286
287fn toFloat(comptime Float: type) !void {
288 const Result = struct { Float, std.math.big.int.Exactness };
289 const fractional_bits = std.math.floatFractionalBits(Float);
290
291 var int_limbs: [
292 std.math.big.int.calcNonZeroTwosCompLimbCount(2 + fractional_bits)
293 ]Limb = undefined;
294 var int: Mutable = .{
295 .limbs = &int_limbs,
296 .len = undefined,
297 .positive = undefined,
298 };
299
300 int.set(-(1 << (fractional_bits + 1)) - 1);
301 try testing.expectEqual(
302 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
303 int.toFloat(Float, .nearest_even),
304 );
305 try testing.expectEqual(
306 Result{ comptime std.math.nextAfter(
307 Float,
308 -std.math.ldexp(@as(Float, 1), fractional_bits + 1),
309 -std.math.inf(Float),
310 ), .inexact },
311 int.toFloat(Float, .away),
312 );
313 try testing.expectEqual(
314 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
315 int.toFloat(Float, .trunc),
316 );
317 try testing.expectEqual(
318 Result{ comptime std.math.nextAfter(
319 Float,
320 -std.math.ldexp(@as(Float, 1), fractional_bits + 1),
321 -std.math.inf(Float),
322 ), .inexact },
323 int.toFloat(Float, .floor),
324 );
325 try testing.expectEqual(
326 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
327 int.toFloat(Float, .ceil),
328 );
329
330 int.set(-1 << (fractional_bits + 1));
331 try testing.expectEqual(
332 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
333 int.toFloat(Float, .nearest_even),
334 );
335 try testing.expectEqual(
336 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
337 int.toFloat(Float, .away),
338 );
339 try testing.expectEqual(
340 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
341 int.toFloat(Float, .trunc),
342 );
343 try testing.expectEqual(
344 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
345 int.toFloat(Float, .floor),
346 );
347 try testing.expectEqual(
348 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
349 int.toFloat(Float, .ceil),
350 );
351
352 int.set(-(1 << (fractional_bits + 1)) + 1);
353 try testing.expectEqual(
354 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1) + 1.0, .exact },
355 int.toFloat(Float, .nearest_even),
356 );
357 try testing.expectEqual(
358 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1) + 1.0, .exact },
359 int.toFloat(Float, .away),
360 );
361 try testing.expectEqual(
362 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1) + 1.0, .exact },
363 int.toFloat(Float, .trunc),
364 );
365 try testing.expectEqual(
366 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1) + 1.0, .exact },
367 int.toFloat(Float, .floor),
368 );
369 try testing.expectEqual(
370 Result{ comptime -std.math.ldexp(@as(Float, 1), fractional_bits + 1) + 1.0, .exact },
371 int.toFloat(Float, .ceil),
372 );
373
374 int.set(-1 << 10);
375 try testing.expectEqual(Result{ -0x1p10, .exact }, int.toFloat(Float, .nearest_even));
376 try testing.expectEqual(Result{ -0x1p10, .exact }, int.toFloat(Float, .away));
377 try testing.expectEqual(Result{ -0x1p10, .exact }, int.toFloat(Float, .trunc));
378 try testing.expectEqual(Result{ -0x1p10, .exact }, int.toFloat(Float, .floor));
379 try testing.expectEqual(Result{ -0x1p10, .exact }, int.toFloat(Float, .ceil));
380
381 int.set(-1);
382 try testing.expectEqual(Result{ -1.0, .exact }, int.toFloat(Float, .nearest_even));
383 try testing.expectEqual(Result{ -1.0, .exact }, int.toFloat(Float, .away));
384 try testing.expectEqual(Result{ -1.0, .exact }, int.toFloat(Float, .trunc));
385 try testing.expectEqual(Result{ -1.0, .exact }, int.toFloat(Float, .floor));
386 try testing.expectEqual(Result{ -1.0, .exact }, int.toFloat(Float, .ceil));
387
388 int.set(0);
389 try testing.expectEqual(Result{ 0.0, .exact }, int.toFloat(Float, .nearest_even));
390 try testing.expectEqual(Result{ 0.0, .exact }, int.toFloat(Float, .away));
391 try testing.expectEqual(Result{ 0.0, .exact }, int.toFloat(Float, .trunc));
392 try testing.expectEqual(Result{ 0.0, .exact }, int.toFloat(Float, .floor));
393 try testing.expectEqual(Result{ 0.0, .exact }, int.toFloat(Float, .ceil));
394
395 int.set(1);
396 try testing.expectEqual(Result{ 1.0, .exact }, int.toFloat(Float, .nearest_even));
397 try testing.expectEqual(Result{ 1.0, .exact }, int.toFloat(Float, .away));
398 try testing.expectEqual(Result{ 1.0, .exact }, int.toFloat(Float, .trunc));
399 try testing.expectEqual(Result{ 1.0, .exact }, int.toFloat(Float, .floor));
400 try testing.expectEqual(Result{ 1.0, .exact }, int.toFloat(Float, .ceil));
401
402 int.set(1 << 10);
403 try testing.expectEqual(Result{ 0x1p10, .exact }, int.toFloat(Float, .nearest_even));
404 try testing.expectEqual(Result{ 0x1p10, .exact }, int.toFloat(Float, .away));
405 try testing.expectEqual(Result{ 0x1p10, .exact }, int.toFloat(Float, .trunc));
406 try testing.expectEqual(Result{ 0x1p10, .exact }, int.toFloat(Float, .floor));
407 try testing.expectEqual(Result{ 0x1p10, .exact }, int.toFloat(Float, .ceil));
408
409 int.set((1 << (fractional_bits + 1)) - 1);
410 try testing.expectEqual(
411 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1) - 1.0, .exact },
412 int.toFloat(Float, .nearest_even),
413 );
414 try testing.expectEqual(
415 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1) - 1.0, .exact },
416 int.toFloat(Float, .away),
417 );
418 try testing.expectEqual(
419 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1) - 1.0, .exact },
420 int.toFloat(Float, .trunc),
421 );
422 try testing.expectEqual(
423 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1) - 1.0, .exact },
424 int.toFloat(Float, .floor),
425 );
426 try testing.expectEqual(
427 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1) - 1.0, .exact },
428 int.toFloat(Float, .ceil),
429 );
430
431 int.set(1 << (fractional_bits + 1));
432 try testing.expectEqual(
433 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
434 int.toFloat(Float, .nearest_even),
435 );
436 try testing.expectEqual(
437 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
438 int.toFloat(Float, .away),
439 );
440 try testing.expectEqual(
441 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
442 int.toFloat(Float, .trunc),
443 );
444 try testing.expectEqual(
445 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
446 int.toFloat(Float, .floor),
447 );
448 try testing.expectEqual(
449 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .exact },
450 int.toFloat(Float, .ceil),
451 );
452
453 int.set((1 << (fractional_bits + 1)) + 1);
454 try testing.expectEqual(
455 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
456 int.toFloat(Float, .nearest_even),
457 );
458 try testing.expectEqual(
459 Result{ comptime std.math.nextAfter(
460 Float,
461 std.math.ldexp(@as(Float, 1), fractional_bits + 1),
462 std.math.inf(Float),
463 ), .inexact },
464 int.toFloat(Float, .away),
465 );
466 try testing.expectEqual(
467 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
468 int.toFloat(Float, .trunc),
469 );
470 try testing.expectEqual(
471 Result{ comptime std.math.ldexp(@as(Float, 1), fractional_bits + 1), .inexact },
472 int.toFloat(Float, .floor),
473 );
474 try testing.expectEqual(
475 Result{ comptime std.math.nextAfter(
476 Float,
477 std.math.ldexp(@as(Float, 1), fractional_bits + 1),
478 std.math.inf(Float),
479 ), .inexact },
480 int.toFloat(Float, .ceil),
481 );
482}
483test toFloat {
484 try toFloat(f16);
485 try toFloat(f32);
486 try toFloat(f64);
487 try toFloat(f80);
488 try toFloat(f128);
489 try toFloat(c_longdouble);
490}
491
492test "normalize" {
493 var a = try Managed.init(testing.allocator);
494 defer a.deinit();
495 try a.ensureCapacity(8);
496
497 a.limbs[0] = 1;
498 a.limbs[1] = 2;
499 a.limbs[2] = 3;
500 a.limbs[3] = 0;
501 a.normalize(4);
502 try testing.expectEqual(3, a.len());
503
504 a.limbs[0] = 1;
505 a.limbs[1] = 2;
506 a.limbs[2] = 3;
507 a.normalize(3);
508 try testing.expectEqual(3, a.len());
509
510 a.limbs[0] = 0;
511 a.limbs[1] = 0;
512 a.normalize(2);
513 try testing.expectEqual(1, a.len());
514
515 a.limbs[0] = 0;
516 a.normalize(1);
517 try testing.expectEqual(1, a.len());
518}
519
520test "normalize multi" {
521 var a = try Managed.init(testing.allocator);
522 defer a.deinit();
523 try a.ensureCapacity(8);
524
525 a.limbs[0] = 1;
526 a.limbs[1] = 2;
527 a.limbs[2] = 0;
528 a.limbs[3] = 0;
529 a.normalize(4);
530 try testing.expectEqual(2, a.len());
531
532 a.limbs[0] = 1;
533 a.limbs[1] = 2;
534 a.limbs[2] = 3;
535 a.normalize(3);
536 try testing.expectEqual(3, a.len());
537
538 a.limbs[0] = 0;
539 a.limbs[1] = 0;
540 a.limbs[2] = 0;
541 a.limbs[3] = 0;
542 a.normalize(4);
543 try testing.expectEqual(1, a.len());
544
545 a.limbs[0] = 0;
546 a.normalize(1);
547 try testing.expectEqual(1, a.len());
548}
549
550test "parity" {
551 var a = try Managed.init(testing.allocator);
552 defer a.deinit();
553
554 try a.set(0);
555 try testing.expect(a.isEven());
556 try testing.expect(!a.isOdd());
557
558 try a.set(7);
559 try testing.expect(!a.isEven());
560 try testing.expect(a.isOdd());
561}
562
563test "bitcount + sizeInBaseUpperBound" {
564 var a = try Managed.init(testing.allocator);
565 defer a.deinit();
566
567 try a.set(0b100);
568 try testing.expectEqual(3, a.bitCountAbs());
569 try testing.expect(a.sizeInBaseUpperBound(2) >= 3);
570 try testing.expect(a.sizeInBaseUpperBound(10) >= 1);
571
572 a.negate();
573 try testing.expectEqual(3, a.bitCountAbs());
574 try testing.expect(a.sizeInBaseUpperBound(2) >= 4);
575 try testing.expect(a.sizeInBaseUpperBound(10) >= 2);
576
577 try a.set(0xffffffff);
578 try testing.expectEqual(32, a.bitCountAbs());
579 try testing.expect(a.sizeInBaseUpperBound(2) >= 32);
580 try testing.expect(a.sizeInBaseUpperBound(10) >= 10);
581
582 const shift = 5000;
583 try a.ensureCapacity(a.len() + (shift / @bitSizeOf(Limb)) + 1);
584 try a.shiftLeft(&a, shift);
585 try testing.expectEqual(5032, a.bitCountAbs());
586 try testing.expect(a.sizeInBaseUpperBound(2) >= 5032);
587 a.setSign(false);
588
589 try testing.expectEqual(5032, a.bitCountAbs());
590 try testing.expect(a.sizeInBaseUpperBound(2) >= 5033);
591}
592
593test "bitcount/to" {
594 var a = try Managed.init(testing.allocator);
595 defer a.deinit();
596
597 try a.set(0);
598 try testing.expectEqual(0, a.bitCountTwosComp());
599
600 try testing.expectEqual(0, try a.toInt(u0));
601
602 try a.set(-1);
603 try testing.expectEqual(1, a.bitCountTwosComp());
604 try testing.expectEqual(-1, try a.toInt(i1));
605
606 try a.set(-8);
607 try testing.expectEqual(4, a.bitCountTwosComp());
608 try testing.expectEqual(-8, try a.toInt(i4));
609
610 try a.set(127);
611 try testing.expectEqual(7, a.bitCountTwosComp());
612 try testing.expectEqual(127, try a.toInt(u7));
613
614 try a.set(-128);
615 try testing.expectEqual(8, a.bitCountTwosComp());
616 try testing.expectEqual(-128, try a.toInt(i8));
617
618 try a.set(-129);
619 try testing.expectEqual(9, a.bitCountTwosComp());
620 try testing.expectEqual(-129, try a.toInt(i9));
621}
622
623test "fits" {
624 var a = try Managed.init(testing.allocator);
625 defer a.deinit();
626
627 try a.set(0);
628 try testing.expect(a.fits(u0));
629
630 try a.set(255);
631 try testing.expect(!a.fits(u0));
632 try testing.expect(!a.fits(u1));
633 try testing.expect(!a.fits(i8));
634 try testing.expect(a.fits(u8));
635 try testing.expect(a.fits(u9));
636 try testing.expect(a.fits(i9));
637
638 try a.set(-128);
639 try testing.expect(!a.fits(i7));
640 try testing.expect(a.fits(i8));
641 try testing.expect(a.fits(i9));
642 try testing.expect(!a.fits(u9));
643
644 try a.set(0x1ffffffffeeeeeeee);
645 try testing.expect(!a.fits(u32));
646 try testing.expect(!a.fits(u64));
647 try testing.expect(a.fits(u65));
648}
649
650test "string set" {
651 var a = try Managed.init(testing.allocator);
652 defer a.deinit();
653
654 try a.setString(10, "120317241209124781241290847124");
655 try testing.expectEqual(120317241209124781241290847124, try a.toInt(u128));
656}
657
658test "string negative" {
659 var a = try Managed.init(testing.allocator);
660 defer a.deinit();
661
662 try a.setString(10, "-1023");
663 try testing.expectEqual(-1023, try a.toInt(i32));
664}
665
666test "string set number with underscores" {
667 var a = try Managed.init(testing.allocator);
668 defer a.deinit();
669
670 try a.setString(10, "__1_2_0_3_1_7_2_4_1_2_0_____9_1__2__4_7_8_1_2_4_1_2_9_0_8_4_7_1_2_4___");
671 try testing.expectEqual(120317241209124781241290847124, try a.toInt(u128));
672}
673
674test "string set case insensitive number" {
675 var a = try Managed.init(testing.allocator);
676 defer a.deinit();
677
678 try a.setString(16, "aB_cD_eF");
679 try testing.expectEqual(0xabcdef, try a.toInt(u32));
680}
681
682test "string set base 36" {
683 var a = try Managed.init(testing.allocator);
684 defer a.deinit();
685
686 try a.setString(36, "fifvthrv1mzt79ez9");
687 try testing.expectEqual(123456789123456789123456789, try a.toInt(u128));
688}
689
690test "string set bad char error" {
691 var a = try Managed.init(testing.allocator);
692 defer a.deinit();
693 try testing.expectError(error.InvalidCharacter, a.setString(10, "x"));
694}
695
696test "string set bad base error" {
697 var a = try Managed.init(testing.allocator);
698 defer a.deinit();
699 try testing.expectError(error.InvalidBase, a.setString(45, "10"));
700}
701
702test "twos complement limit set" {
703 try testTwosComplementLimit(u64);
704 try testTwosComplementLimit(i64);
705 try testTwosComplementLimit(u1);
706 try testTwosComplementLimit(i1);
707 try testTwosComplementLimit(u0);
708 try testTwosComplementLimit(u65);
709 try testTwosComplementLimit(i65);
710}
711
712fn testTwosComplementLimit(comptime T: type) !void {
713 const int_info = @typeInfo(T).int;
714
715 var a = try Managed.init(testing.allocator);
716 defer a.deinit();
717
718 try a.setTwosCompIntLimit(.max, int_info.signedness, int_info.bits);
719 const max: T = maxInt(T);
720 try testing.expectEqual(max, try a.toInt(T));
721
722 try a.setTwosCompIntLimit(.min, int_info.signedness, int_info.bits);
723 const min: T = minInt(T);
724 try testing.expectEqual(min, try a.toInt(T));
725}
726
727test "string to" {
728 var a = try Managed.initSet(testing.allocator, 120317241209124781241290847124);
729 defer a.deinit();
730
731 const as = try a.toString(testing.allocator, 10, .lower);
732 defer testing.allocator.free(as);
733 const es = "120317241209124781241290847124";
734
735 try testing.expectEqualSlices(u8, es, as);
736}
737
738test "string to base base error" {
739 var a = try Managed.initSet(testing.allocator, 0xffffffff);
740 defer a.deinit();
741
742 try testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45, .lower));
743}
744
745test "string to base 2" {
746 var a = try Managed.initSet(testing.allocator, -0b1011);
747 defer a.deinit();
748
749 const as = try a.toString(testing.allocator, 2, .lower);
750 defer testing.allocator.free(as);
751 const es = "-1011";
752
753 try testing.expectEqualSlices(u8, es, as);
754}
755
756test "string to base 16" {
757 var a = try Managed.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
758 defer a.deinit();
759
760 const as = try a.toString(testing.allocator, 16, .lower);
761 defer testing.allocator.free(as);
762 const es = "efffffff00000001eeeeeeefaaaaaaab";
763
764 try testing.expectEqualSlices(u8, es, as);
765}
766
767test "string to base 36" {
768 var a = try Managed.initSet(testing.allocator, 123456789123456789123456789);
769 defer a.deinit();
770
771 const as = try a.toString(testing.allocator, 36, .lower);
772 defer testing.allocator.free(as);
773 const es = "fifvthrv1mzt79ez9";
774
775 try testing.expectEqualSlices(u8, es, as);
776}
777
778test "neg string to" {
779 var a = try Managed.initSet(testing.allocator, -123907434);
780 defer a.deinit();
781
782 const as = try a.toString(testing.allocator, 10, .lower);
783 defer testing.allocator.free(as);
784 const es = "-123907434";
785
786 try testing.expectEqualSlices(u8, es, as);
787}
788
789test "zero string to" {
790 var a = try Managed.initSet(testing.allocator, 0);
791 defer a.deinit();
792
793 const as = try a.toString(testing.allocator, 10, .lower);
794 defer testing.allocator.free(as);
795 const es = "0";
796
797 try testing.expectEqualSlices(u8, es, as);
798}
799
800test "clone" {
801 var a = try Managed.initSet(testing.allocator, 1234);
802 defer a.deinit();
803 var b = try a.clone();
804 defer b.deinit();
805
806 try testing.expectEqual(1234, try a.toInt(u32));
807 try testing.expectEqual(1234, try b.toInt(u32));
808
809 try a.set(77);
810 try testing.expectEqual(77, try a.toInt(u32));
811 try testing.expectEqual(1234, try b.toInt(u32));
812}
813
814test "swap" {
815 var a = try Managed.initSet(testing.allocator, 1234);
816 defer a.deinit();
817 var b = try Managed.initSet(testing.allocator, 5678);
818 defer b.deinit();
819
820 try testing.expectEqual(1234, try a.toInt(u32));
821 try testing.expectEqual(5678, try b.toInt(u32));
822
823 a.swap(&b);
824
825 try testing.expectEqual(5678, try a.toInt(u32));
826 try testing.expectEqual(1234, try b.toInt(u32));
827}
828
829test "to negative" {
830 var a = try Managed.initSet(testing.allocator, -10);
831 defer a.deinit();
832
833 try testing.expectEqual(-10, try a.toInt(i32));
834}
835
836test "compare" {
837 var a = try Managed.initSet(testing.allocator, -11);
838 defer a.deinit();
839 var b = try Managed.initSet(testing.allocator, 10);
840 defer b.deinit();
841
842 try testing.expectEqual(.gt, a.orderAbs(b));
843 try testing.expectEqual(.lt, a.order(b));
844}
845
846test "compare similar" {
847 var a = try Managed.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeee);
848 defer a.deinit();
849 var b = try Managed.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeef);
850 defer b.deinit();
851
852 try testing.expectEqual(.lt, a.orderAbs(b));
853 try testing.expectEqual(.gt, b.orderAbs(a));
854}
855
856test "compare different limb size" {
857 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
858 defer a.deinit();
859 var b = try Managed.initSet(testing.allocator, 1);
860 defer b.deinit();
861
862 try testing.expectEqual(.gt, a.orderAbs(b));
863 try testing.expectEqual(.lt, b.orderAbs(a));
864}
865
866test "compare multi-limb" {
867 var a = try Managed.initSet(testing.allocator, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);
868 defer a.deinit();
869 var b = try Managed.initSet(testing.allocator, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);
870 defer b.deinit();
871
872 try testing.expectEqual(.gt, a.orderAbs(b));
873 try testing.expectEqual(.lt, a.order(b));
874}
875
876test "equality" {
877 var a = try Managed.initSet(testing.allocator, 0xffffffff1);
878 defer a.deinit();
879 var b = try Managed.initSet(testing.allocator, -0xffffffff1);
880 defer b.deinit();
881
882 try testing.expect(a.eqlAbs(b));
883 try testing.expect(!a.eql(b));
884}
885
886test "abs" {
887 var a = try Managed.initSet(testing.allocator, -5);
888 defer a.deinit();
889
890 a.abs();
891 try testing.expectEqual(5, try a.toInt(u32));
892
893 a.abs();
894 try testing.expectEqual(5, try a.toInt(u32));
895}
896
897test "negate" {
898 var a = try Managed.initSet(testing.allocator, 5);
899 defer a.deinit();
900
901 a.negate();
902 try testing.expectEqual(-5, try a.toInt(i32));
903
904 a.negate();
905 try testing.expectEqual(5, try a.toInt(i32));
906}
907
908test "add single-single" {
909 var a = try Managed.initSet(testing.allocator, 50);
910 defer a.deinit();
911 var b = try Managed.initSet(testing.allocator, 5);
912 defer b.deinit();
913
914 var c = try Managed.init(testing.allocator);
915 defer c.deinit();
916 try c.add(&a, &b);
917
918 try testing.expectEqual(55, try c.toInt(u32));
919}
920
921test "add multi-single" {
922 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
923 defer a.deinit();
924 var b = try Managed.initSet(testing.allocator, 1);
925 defer b.deinit();
926
927 var c = try Managed.init(testing.allocator);
928 defer c.deinit();
929
930 try c.add(&a, &b);
931 try testing.expectEqual(maxInt(Limb) + 2, try c.toInt(DoubleLimb));
932
933 try c.add(&b, &a);
934 try testing.expectEqual(maxInt(Limb) + 2, try c.toInt(DoubleLimb));
935}
936
937test "add multi-multi" {
938 var op1: u128 = 0xefefefef7f7f7f7f;
939 var op2: u128 = 0xfefefefe9f9f9f9f;
940 // These must be runtime-known to prevent this comparison being tautological, as the
941 // compiler uses `std.math.big.int` internally to add these values at comptime.
942 _ = .{ &op1, &op2 };
943 var a = try Managed.initSet(testing.allocator, op1);
944 defer a.deinit();
945 var b = try Managed.initSet(testing.allocator, op2);
946 defer b.deinit();
947
948 var c = try Managed.init(testing.allocator);
949 defer c.deinit();
950 try c.add(&a, &b);
951
952 try testing.expectEqual(op1 + op2, try c.toInt(u128));
953}
954
955test "add zero-zero" {
956 var a = try Managed.initSet(testing.allocator, 0);
957 defer a.deinit();
958 var b = try Managed.initSet(testing.allocator, 0);
959 defer b.deinit();
960
961 var c = try Managed.init(testing.allocator);
962 defer c.deinit();
963 try c.add(&a, &b);
964
965 try testing.expectEqual(0, try c.toInt(u32));
966}
967
968test "add alias multi-limb nonzero-zero" {
969 const op1 = 0xffffffff777777771;
970 var a = try Managed.initSet(testing.allocator, op1);
971 defer a.deinit();
972 var b = try Managed.initSet(testing.allocator, 0);
973 defer b.deinit();
974
975 try a.add(&a, &b);
976
977 try testing.expectEqual(op1, try a.toInt(u128));
978}
979
980test "add sign" {
981 var a = try Managed.init(testing.allocator);
982 defer a.deinit();
983
984 var one = try Managed.initSet(testing.allocator, 1);
985 defer one.deinit();
986 var two = try Managed.initSet(testing.allocator, 2);
987 defer two.deinit();
988 var neg_one = try Managed.initSet(testing.allocator, -1);
989 defer neg_one.deinit();
990 var neg_two = try Managed.initSet(testing.allocator, -2);
991 defer neg_two.deinit();
992
993 try a.add(&one, &two);
994 try testing.expectEqual(3, try a.toInt(i32));
995
996 try a.add(&neg_one, &two);
997 try testing.expectEqual(1, try a.toInt(i32));
998
999 try a.add(&one, &neg_two);
1000 try testing.expectEqual(-1, try a.toInt(i32));
1001
1002 try a.add(&neg_one, &neg_two);
1003 try testing.expectEqual(-3, try a.toInt(i32));
1004}
1005
1006test "add comptime scalar" {
1007 var a = try Managed.initSet(testing.allocator, 50);
1008 defer a.deinit();
1009
1010 var b = try Managed.init(testing.allocator);
1011 defer b.deinit();
1012 try b.addScalar(&a, 5);
1013
1014 try testing.expectEqual(55, try b.toInt(u32));
1015}
1016
1017test "add scalar" {
1018 var a = try Managed.initSet(testing.allocator, 123);
1019 defer a.deinit();
1020
1021 var b = try Managed.init(testing.allocator);
1022 defer b.deinit();
1023 try b.addScalar(&a, @as(u32, 31));
1024
1025 try testing.expectEqual(154, try b.toInt(u32));
1026}
1027
1028test "addWrap single-single, unsigned" {
1029 var a = try Managed.initSet(testing.allocator, maxInt(u17));
1030 defer a.deinit();
1031
1032 var b = try Managed.initSet(testing.allocator, 10);
1033 defer b.deinit();
1034
1035 const wrapped = try a.addWrap(&a, &b, .unsigned, 17);
1036
1037 try testing.expect(wrapped);
1038 try testing.expectEqual(9, try a.toInt(u17));
1039}
1040
1041test "subWrap single-single, unsigned" {
1042 var a = try Managed.initSet(testing.allocator, 0);
1043 defer a.deinit();
1044
1045 var b = try Managed.initSet(testing.allocator, maxInt(u17));
1046 defer b.deinit();
1047
1048 const wrapped = try a.subWrap(&a, &b, .unsigned, 17);
1049
1050 try testing.expect(wrapped);
1051 try testing.expectEqual(1, try a.toInt(u17));
1052}
1053
1054test "addWrap multi-multi, unsigned, limb aligned" {
1055 var a = try Managed.initSet(testing.allocator, maxInt(DoubleLimb));
1056 defer a.deinit();
1057
1058 var b = try Managed.initSet(testing.allocator, maxInt(DoubleLimb));
1059 defer b.deinit();
1060
1061 const wrapped = try a.addWrap(&a, &b, .unsigned, @bitSizeOf(DoubleLimb));
1062
1063 try testing.expect(wrapped);
1064 try testing.expectEqual(maxInt(DoubleLimb) - 1, try a.toInt(DoubleLimb));
1065}
1066
1067test "subWrap single-multi, unsigned, limb aligned" {
1068 var a = try Managed.initSet(testing.allocator, 10);
1069 defer a.deinit();
1070
1071 var b = try Managed.initSet(testing.allocator, maxInt(DoubleLimb) + 100);
1072 defer b.deinit();
1073
1074 const wrapped = try a.subWrap(&a, &b, .unsigned, @bitSizeOf(DoubleLimb));
1075
1076 try testing.expect(wrapped);
1077 try testing.expectEqual(maxInt(DoubleLimb) - 88, try a.toInt(DoubleLimb));
1078}
1079
1080test "addWrap single-single, signed" {
1081 var a = try Managed.initSet(testing.allocator, maxInt(i21));
1082 defer a.deinit();
1083
1084 var b = try Managed.initSet(testing.allocator, 1 + 1 + maxInt(u21));
1085 defer b.deinit();
1086
1087 const wrapped = try a.addWrap(&a, &b, .signed, @bitSizeOf(i21));
1088
1089 try testing.expect(wrapped);
1090 try testing.expectEqual(minInt(i21), try a.toInt(i21));
1091}
1092
1093test "subWrap single-single, signed" {
1094 var a = try Managed.initSet(testing.allocator, minInt(i21));
1095 defer a.deinit();
1096
1097 var b = try Managed.initSet(testing.allocator, 1);
1098 defer b.deinit();
1099
1100 const wrapped = try a.subWrap(&a, &b, .signed, @bitSizeOf(i21));
1101
1102 try testing.expect(wrapped);
1103 try testing.expectEqual(maxInt(i21), try a.toInt(i21));
1104}
1105
1106test "addWrap multi-multi, signed, limb aligned" {
1107 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
1108 defer a.deinit();
1109
1110 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
1111 defer b.deinit();
1112
1113 const wrapped = try a.addWrap(&a, &b, .signed, @bitSizeOf(SignedDoubleLimb));
1114
1115 try testing.expect(wrapped);
1116 try testing.expectEqual(-2, try a.toInt(SignedDoubleLimb));
1117}
1118
1119test "subWrap single-multi, signed, limb aligned" {
1120 var a = try Managed.initSet(testing.allocator, minInt(SignedDoubleLimb));
1121 defer a.deinit();
1122
1123 var b = try Managed.initSet(testing.allocator, 1);
1124 defer b.deinit();
1125
1126 const wrapped = try a.subWrap(&a, &b, .signed, @bitSizeOf(SignedDoubleLimb));
1127
1128 try testing.expect(wrapped);
1129 try testing.expectEqual(maxInt(SignedDoubleLimb), try a.toInt(SignedDoubleLimb));
1130}
1131
1132test "addWrap returns normalized result" {
1133 var x = try Managed.initSet(testing.allocator, 0);
1134 defer x.deinit();
1135 var y = try Managed.initSet(testing.allocator, 0);
1136 defer y.deinit();
1137
1138 // make them both non normalized "-0"
1139 x.setMetadata(false, 1);
1140 y.setMetadata(false, 1);
1141
1142 var r = try Managed.init(testing.allocator);
1143 defer r.deinit();
1144 try testing.expect(!(try r.addWrap(&x, &y, .unsigned, 64)));
1145 try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0);
1146}
1147
1148test "subWrap returns normalized result" {
1149 var x = try Managed.initSet(testing.allocator, 0);
1150 defer x.deinit();
1151 var y = try Managed.initSet(testing.allocator, 0);
1152 defer y.deinit();
1153
1154 var r = try Managed.init(testing.allocator);
1155 defer r.deinit();
1156 try testing.expect(!(try r.subWrap(&x, &y, .unsigned, 64)));
1157 try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0);
1158}
1159
1160test "addSat single-single, unsigned" {
1161 var a = try Managed.initSet(testing.allocator, maxInt(u17) - 5);
1162 defer a.deinit();
1163
1164 var b = try Managed.initSet(testing.allocator, 10);
1165 defer b.deinit();
1166
1167 try a.addSat(&a, &b, .unsigned, 17);
1168
1169 try testing.expectEqual(maxInt(u17), try a.toInt(u17));
1170}
1171
1172test "subSat single-single, unsigned" {
1173 var a = try Managed.initSet(testing.allocator, 123);
1174 defer a.deinit();
1175
1176 var b = try Managed.initSet(testing.allocator, 4000);
1177 defer b.deinit();
1178
1179 try a.subSat(&a, &b, .unsigned, 17);
1180
1181 try testing.expectEqual(0, try a.toInt(u17));
1182}
1183
1184test "addSat multi-multi, unsigned, limb aligned" {
1185 var a = try Managed.initSet(testing.allocator, maxInt(DoubleLimb));
1186 defer a.deinit();
1187
1188 var b = try Managed.initSet(testing.allocator, maxInt(DoubleLimb));
1189 defer b.deinit();
1190
1191 try a.addSat(&a, &b, .unsigned, @bitSizeOf(DoubleLimb));
1192
1193 try testing.expectEqual(maxInt(DoubleLimb), try a.toInt(DoubleLimb));
1194}
1195
1196test "subSat single-multi, unsigned, limb aligned" {
1197 var a = try Managed.initSet(testing.allocator, 10);
1198 defer a.deinit();
1199
1200 var b = try Managed.initSet(testing.allocator, maxInt(DoubleLimb) + 100);
1201 defer b.deinit();
1202
1203 try a.subSat(&a, &b, .unsigned, @bitSizeOf(DoubleLimb));
1204
1205 try testing.expectEqual(0, try a.toInt(DoubleLimb));
1206}
1207
1208test "addSat single-single, signed" {
1209 var a = try Managed.initSet(testing.allocator, maxInt(i14));
1210 defer a.deinit();
1211
1212 var b = try Managed.initSet(testing.allocator, 1);
1213 defer b.deinit();
1214
1215 try a.addSat(&a, &b, .signed, @bitSizeOf(i14));
1216
1217 try testing.expectEqual(maxInt(i14), try a.toInt(i14));
1218}
1219
1220test "subSat single-single, signed" {
1221 var a = try Managed.initSet(testing.allocator, minInt(i21));
1222 defer a.deinit();
1223
1224 var b = try Managed.initSet(testing.allocator, 1);
1225 defer b.deinit();
1226
1227 try a.subSat(&a, &b, .signed, @bitSizeOf(i21));
1228
1229 try testing.expectEqual(minInt(i21), try a.toInt(i21));
1230}
1231
1232test "addSat multi-multi, signed, limb aligned" {
1233 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
1234 defer a.deinit();
1235
1236 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
1237 defer b.deinit();
1238
1239 try a.addSat(&a, &b, .signed, @bitSizeOf(SignedDoubleLimb));
1240
1241 try testing.expectEqual(maxInt(SignedDoubleLimb), try a.toInt(SignedDoubleLimb));
1242}
1243
1244test "subSat single-multi, signed, limb aligned" {
1245 var a = try Managed.initSet(testing.allocator, minInt(SignedDoubleLimb));
1246 defer a.deinit();
1247
1248 var b = try Managed.initSet(testing.allocator, 1);
1249 defer b.deinit();
1250
1251 try a.subSat(&a, &b, .signed, @bitSizeOf(SignedDoubleLimb));
1252
1253 try testing.expectEqual(minInt(SignedDoubleLimb), try a.toInt(SignedDoubleLimb));
1254}
1255
1256test "addSat multi-multi, signed, unused limb" {
1257 var a = try Managed.initSet(testing.allocator, 1 << (@bitSizeOf(Limb) - 1));
1258 defer a.deinit();
1259
1260 try a.ensureTwosCompCapacity(3 * @bitSizeOf(Limb));
1261 try a.addSat(&a, &a, .signed, 3 * @bitSizeOf(Limb));
1262
1263 try testing.expectEqual(1 << @bitSizeOf(Limb), try a.toInt(SignedDoubleLimb));
1264}
1265
1266test "subSat multi-multi, signed, unused limb" {
1267 var a = try Managed.initSet(testing.allocator, -1 << (@bitSizeOf(Limb) - 1));
1268 defer a.deinit();
1269
1270 var b = try Managed.initSet(testing.allocator, 1 << (@bitSizeOf(Limb) - 1));
1271 defer b.deinit();
1272
1273 try a.subSat(&a, &b, .signed, 3 * @bitSizeOf(Limb));
1274
1275 try testing.expectEqual(-1 << @bitSizeOf(Limb), try a.toInt(SignedDoubleLimb));
1276}
1277
1278test "sub single-single" {
1279 var a = try Managed.initSet(testing.allocator, 50);
1280 defer a.deinit();
1281 var b = try Managed.initSet(testing.allocator, 5);
1282 defer b.deinit();
1283
1284 var c = try Managed.init(testing.allocator);
1285 defer c.deinit();
1286 try c.sub(&a, &b);
1287
1288 try testing.expectEqual(45, try c.toInt(u32));
1289}
1290
1291test "sub multi-single" {
1292 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
1293 defer a.deinit();
1294 var b = try Managed.initSet(testing.allocator, 1);
1295 defer b.deinit();
1296
1297 var c = try Managed.init(testing.allocator);
1298 defer c.deinit();
1299 try c.sub(&a, &b);
1300
1301 try testing.expectEqual(maxInt(Limb), try c.toInt(Limb));
1302}
1303
1304test "sub multi-multi" {
1305 var op1: u128 = 0xefefefefefefefefefefefef;
1306 var op2: u128 = 0xabababababababababababab;
1307 _ = .{ &op1, &op2 };
1308
1309 var a = try Managed.initSet(testing.allocator, op1);
1310 defer a.deinit();
1311 var b = try Managed.initSet(testing.allocator, op2);
1312 defer b.deinit();
1313
1314 var c = try Managed.init(testing.allocator);
1315 defer c.deinit();
1316 try c.sub(&a, &b);
1317
1318 try testing.expectEqual(op1 - op2, try c.toInt(u128));
1319}
1320
1321test "sub equal" {
1322 var a = try Managed.initSet(testing.allocator, 0x11efefefefefefefefefefefef);
1323 defer a.deinit();
1324 var b = try Managed.initSet(testing.allocator, 0x11efefefefefefefefefefefef);
1325 defer b.deinit();
1326
1327 var c = try Managed.init(testing.allocator);
1328 defer c.deinit();
1329 try c.sub(&a, &b);
1330
1331 try testing.expectEqual(0, try c.toInt(u32));
1332}
1333
1334test "sub sign" {
1335 var a = try Managed.init(testing.allocator);
1336 defer a.deinit();
1337
1338 var one = try Managed.initSet(testing.allocator, 1);
1339 defer one.deinit();
1340 var two = try Managed.initSet(testing.allocator, 2);
1341 defer two.deinit();
1342 var neg_one = try Managed.initSet(testing.allocator, -1);
1343 defer neg_one.deinit();
1344 var neg_two = try Managed.initSet(testing.allocator, -2);
1345 defer neg_two.deinit();
1346
1347 try a.sub(&one, &two);
1348 try testing.expectEqual(-1, try a.toInt(i32));
1349
1350 try a.sub(&neg_one, &two);
1351 try testing.expectEqual(-3, try a.toInt(i32));
1352
1353 try a.sub(&one, &neg_two);
1354 try testing.expectEqual(3, try a.toInt(i32));
1355
1356 try a.sub(&neg_one, &neg_two);
1357 try testing.expectEqual(1, try a.toInt(i32));
1358
1359 try a.sub(&neg_two, &neg_one);
1360 try testing.expectEqual(-1, try a.toInt(i32));
1361}
1362
1363test "mul single-single" {
1364 var a = try Managed.initSet(testing.allocator, 50);
1365 defer a.deinit();
1366 var b = try Managed.initSet(testing.allocator, 5);
1367 defer b.deinit();
1368
1369 var c = try Managed.init(testing.allocator);
1370 defer c.deinit();
1371 try c.mul(&a, &b);
1372
1373 try testing.expectEqual(250, try c.toInt(u64));
1374}
1375
1376test "mul multi-single" {
1377 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
1378 defer a.deinit();
1379 var b = try Managed.initSet(testing.allocator, 2);
1380 defer b.deinit();
1381
1382 var c = try Managed.init(testing.allocator);
1383 defer c.deinit();
1384 try c.mul(&a, &b);
1385
1386 try testing.expectEqual(2 * maxInt(Limb), try c.toInt(DoubleLimb));
1387}
1388
1389test "mul multi-multi" {
1390 var op1: u256 = 0x998888efefefefefefefef;
1391 var op2: u256 = 0x333000abababababababab;
1392 _ = .{ &op1, &op2 };
1393
1394 var a = try Managed.initSet(testing.allocator, op1);
1395 defer a.deinit();
1396 var b = try Managed.initSet(testing.allocator, op2);
1397 defer b.deinit();
1398
1399 var c = try Managed.init(testing.allocator);
1400 defer c.deinit();
1401 try c.mul(&a, &b);
1402
1403 try testing.expectEqual(op1 * op2, try c.toInt(u256));
1404}
1405
1406test "mul alias r with a" {
1407 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
1408 defer a.deinit();
1409 var b = try Managed.initSet(testing.allocator, 2);
1410 defer b.deinit();
1411
1412 try a.mul(&a, &b);
1413
1414 try testing.expectEqual(2 * maxInt(Limb), try a.toInt(DoubleLimb));
1415}
1416
1417test "mul alias r with b" {
1418 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
1419 defer a.deinit();
1420 var b = try Managed.initSet(testing.allocator, 2);
1421 defer b.deinit();
1422
1423 try a.mul(&b, &a);
1424
1425 try testing.expectEqual(2 * maxInt(Limb), try a.toInt(DoubleLimb));
1426}
1427
1428test "mul alias r with a and b" {
1429 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
1430 defer a.deinit();
1431
1432 try a.mul(&a, &a);
1433
1434 try testing.expectEqual(maxInt(Limb) * maxInt(Limb), try a.toInt(DoubleLimb));
1435}
1436
1437test "mul a*0" {
1438 var a = try Managed.initSet(testing.allocator, 0xefefefefefefefef);
1439 defer a.deinit();
1440 var b = try Managed.initSet(testing.allocator, 0);
1441 defer b.deinit();
1442
1443 var c = try Managed.init(testing.allocator);
1444 defer c.deinit();
1445 try c.mul(&a, &b);
1446
1447 try testing.expectEqual(0, try c.toInt(u32));
1448}
1449
1450test "mul 0*0" {
1451 var a = try Managed.initSet(testing.allocator, 0);
1452 defer a.deinit();
1453 var b = try Managed.initSet(testing.allocator, 0);
1454 defer b.deinit();
1455
1456 var c = try Managed.init(testing.allocator);
1457 defer c.deinit();
1458 try c.mul(&a, &b);
1459
1460 try testing.expectEqual(0, try c.toInt(u32));
1461}
1462
1463test "mul large" {
1464 var a = try Managed.initCapacity(testing.allocator, 50);
1465 defer a.deinit();
1466 var b = try Managed.initCapacity(testing.allocator, 100);
1467 defer b.deinit();
1468 var c = try Managed.initCapacity(testing.allocator, 100);
1469 defer c.deinit();
1470
1471 // Generate a number that's large enough to cross the thresholds for the use
1472 // of subquadratic algorithms
1473 for (a.limbs) |*p| {
1474 p.* = maxInt(Limb);
1475 }
1476 a.setMetadata(true, 50);
1477
1478 try b.mul(&a, &a);
1479 try c.sqr(&a);
1480
1481 try testing.expect(b.eql(c));
1482}
1483
1484test "mulWrap single-single unsigned" {
1485 var a = try Managed.initSet(testing.allocator, 1234);
1486 defer a.deinit();
1487 var b = try Managed.initSet(testing.allocator, 5678);
1488 defer b.deinit();
1489
1490 var c = try Managed.init(testing.allocator);
1491 defer c.deinit();
1492 try c.mulWrap(&a, &b, .unsigned, 17);
1493
1494 try testing.expectEqual(59836, try c.toInt(u17));
1495}
1496
1497test "mulWrap single-single signed" {
1498 var a = try Managed.initSet(testing.allocator, 1234);
1499 defer a.deinit();
1500 var b = try Managed.initSet(testing.allocator, -5678);
1501 defer b.deinit();
1502
1503 var c = try Managed.init(testing.allocator);
1504 defer c.deinit();
1505 try c.mulWrap(&a, &b, .signed, 17);
1506
1507 try testing.expectEqual(-59836, try c.toInt(i17));
1508}
1509
1510test "mulWrap multi-multi unsigned" {
1511 var op1: u256 = 0x998888efefefefefefefef;
1512 var op2: u256 = 0x333000abababababababab;
1513 _ = .{ &op1, &op2 };
1514
1515 var a = try Managed.initSet(testing.allocator, op1);
1516 defer a.deinit();
1517 var b = try Managed.initSet(testing.allocator, op2);
1518 defer b.deinit();
1519
1520 var c = try Managed.init(testing.allocator);
1521 defer c.deinit();
1522 try c.mulWrap(&a, &b, .unsigned, 65);
1523
1524 try testing.expectEqual((op1 * op2) & ((1 << 65) - 1), try c.toInt(u256));
1525}
1526
1527test "mulWrap multi-multi signed" {
1528 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1);
1529 defer a.deinit();
1530 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
1531 defer b.deinit();
1532
1533 var c = try Managed.init(testing.allocator);
1534 defer c.deinit();
1535 try c.mulWrap(&a, &b, .signed, @bitSizeOf(SignedDoubleLimb));
1536
1537 try testing.expectEqual(minInt(SignedDoubleLimb) + 2, try c.toInt(SignedDoubleLimb));
1538}
1539
1540test "mulWrap large" {
1541 var a = try Managed.initCapacity(testing.allocator, 50);
1542 defer a.deinit();
1543 var b = try Managed.initCapacity(testing.allocator, 100);
1544 defer b.deinit();
1545 var c = try Managed.initCapacity(testing.allocator, 100);
1546 defer c.deinit();
1547
1548 // Generate a number that's large enough to cross the thresholds for the use
1549 // of subquadratic algorithms
1550 for (a.limbs) |*p| {
1551 p.* = maxInt(Limb);
1552 }
1553 a.setMetadata(true, 50);
1554
1555 const testbits = @bitSizeOf(Limb) * 64 + 45;
1556
1557 try b.mulWrap(&a, &a, .signed, testbits);
1558 try c.sqr(&a);
1559 try c.truncate(&c, .signed, testbits);
1560
1561 try testing.expect(b.eql(c));
1562}
1563
1564test "div single-half no rem" {
1565 var a = try Managed.initSet(testing.allocator, 50);
1566 defer a.deinit();
1567 var b = try Managed.initSet(testing.allocator, 5);
1568 defer b.deinit();
1569
1570 var q = try Managed.init(testing.allocator);
1571 defer q.deinit();
1572 var r = try Managed.init(testing.allocator);
1573 defer r.deinit();
1574 try Managed.divTrunc(&q, &r, &a, &b);
1575
1576 try testing.expectEqual(10, try q.toInt(u32));
1577 try testing.expectEqual(0, try r.toInt(u32));
1578}
1579
1580test "div single-half with rem" {
1581 var a = try Managed.initSet(testing.allocator, 49);
1582 defer a.deinit();
1583 var b = try Managed.initSet(testing.allocator, 5);
1584 defer b.deinit();
1585
1586 var q = try Managed.init(testing.allocator);
1587 defer q.deinit();
1588 var r = try Managed.init(testing.allocator);
1589 defer r.deinit();
1590 try Managed.divTrunc(&q, &r, &a, &b);
1591
1592 try testing.expectEqual(9, try q.toInt(u32));
1593 try testing.expectEqual(4, try r.toInt(u32));
1594}
1595
1596test "div single-single no rem" {
1597 // assumes usize is <= 64 bits.
1598 var a = try Managed.initSet(testing.allocator, 1 << 52);
1599 defer a.deinit();
1600 var b = try Managed.initSet(testing.allocator, 1 << 35);
1601 defer b.deinit();
1602
1603 var q = try Managed.init(testing.allocator);
1604 defer q.deinit();
1605 var r = try Managed.init(testing.allocator);
1606 defer r.deinit();
1607 try Managed.divTrunc(&q, &r, &a, &b);
1608
1609 try testing.expectEqual(131072, try q.toInt(u32));
1610 try testing.expectEqual(0, try r.toInt(u32));
1611}
1612
1613test "div single-single with rem" {
1614 var a = try Managed.initSet(testing.allocator, (1 << 52) | (1 << 33));
1615 defer a.deinit();
1616 var b = try Managed.initSet(testing.allocator, (1 << 35));
1617 defer b.deinit();
1618
1619 var q = try Managed.init(testing.allocator);
1620 defer q.deinit();
1621 var r = try Managed.init(testing.allocator);
1622 defer r.deinit();
1623 try Managed.divTrunc(&q, &r, &a, &b);
1624
1625 try testing.expectEqual(131072, try q.toInt(u64));
1626 try testing.expectEqual(8589934592, try r.toInt(u64));
1627}
1628
1629test "div multi-single no rem" {
1630 var op1: u128 = 0xffffeeeeddddcccc;
1631 var op2: u128 = 34;
1632 _ = .{ &op1, &op2 };
1633
1634 var a = try Managed.initSet(testing.allocator, op1);
1635 defer a.deinit();
1636 var b = try Managed.initSet(testing.allocator, op2);
1637 defer b.deinit();
1638
1639 var q = try Managed.init(testing.allocator);
1640 defer q.deinit();
1641 var r = try Managed.init(testing.allocator);
1642 defer r.deinit();
1643 try Managed.divTrunc(&q, &r, &a, &b);
1644
1645 try testing.expectEqual(op1 / op2, try q.toInt(u64));
1646 try testing.expectEqual(0, try r.toInt(u64));
1647}
1648
1649test "div multi-single with rem" {
1650 var op1: u128 = 0xffffeeeeddddcccf;
1651 var op2: u128 = 34;
1652 _ = .{ &op1, &op2 };
1653
1654 var a = try Managed.initSet(testing.allocator, op1);
1655 defer a.deinit();
1656 var b = try Managed.initSet(testing.allocator, op2);
1657 defer b.deinit();
1658
1659 var q = try Managed.init(testing.allocator);
1660 defer q.deinit();
1661 var r = try Managed.init(testing.allocator);
1662 defer r.deinit();
1663 try Managed.divTrunc(&q, &r, &a, &b);
1664
1665 try testing.expectEqual(op1 / op2, try q.toInt(u64));
1666 try testing.expectEqual(3, try r.toInt(u64));
1667}
1668
1669test "div multi>2-single" {
1670 var op1: u128 = 0xfefefefefefefefefefefefefefefefe;
1671 var op2: u128 = 0xefab8;
1672 _ = .{ &op1, &op2 };
1673
1674 var a = try Managed.initSet(testing.allocator, op1);
1675 defer a.deinit();
1676 var b = try Managed.initSet(testing.allocator, op2);
1677 defer b.deinit();
1678
1679 var q = try Managed.init(testing.allocator);
1680 defer q.deinit();
1681 var r = try Managed.init(testing.allocator);
1682 defer r.deinit();
1683 try Managed.divTrunc(&q, &r, &a, &b);
1684
1685 try testing.expectEqual(op1 / op2, try q.toInt(u128));
1686 try testing.expectEqual(0x3e4e, try r.toInt(u32));
1687}
1688
1689test "div single-single q < r" {
1690 var a = try Managed.initSet(testing.allocator, 0x0078f432);
1691 defer a.deinit();
1692 var b = try Managed.initSet(testing.allocator, 0x01000000);
1693 defer b.deinit();
1694
1695 var q = try Managed.init(testing.allocator);
1696 defer q.deinit();
1697 var r = try Managed.init(testing.allocator);
1698 defer r.deinit();
1699 try Managed.divTrunc(&q, &r, &a, &b);
1700
1701 try testing.expectEqual(0, try q.toInt(u64));
1702 try testing.expectEqual(0x0078f432, try r.toInt(u64));
1703}
1704
1705test "div single-single q == r" {
1706 var a = try Managed.initSet(testing.allocator, 10);
1707 defer a.deinit();
1708 var b = try Managed.initSet(testing.allocator, 10);
1709 defer b.deinit();
1710
1711 var q = try Managed.init(testing.allocator);
1712 defer q.deinit();
1713 var r = try Managed.init(testing.allocator);
1714 defer r.deinit();
1715 try Managed.divTrunc(&q, &r, &a, &b);
1716
1717 try testing.expectEqual(1, try q.toInt(u64));
1718 try testing.expectEqual(0, try r.toInt(u64));
1719}
1720
1721test "div q=0 alias" {
1722 var a = try Managed.initSet(testing.allocator, 3);
1723 defer a.deinit();
1724 var b = try Managed.initSet(testing.allocator, 10);
1725 defer b.deinit();
1726
1727 try Managed.divTrunc(&a, &b, &a, &b);
1728
1729 try testing.expectEqual(0, try a.toInt(u64));
1730 try testing.expectEqual(3, try b.toInt(u64));
1731}
1732
1733test "div multi-multi q < r" {
1734 const op1 = 0x1ffffffff0078f432;
1735 const op2 = 0x1ffffffff01000000;
1736 var a = try Managed.initSet(testing.allocator, op1);
1737 defer a.deinit();
1738 var b = try Managed.initSet(testing.allocator, op2);
1739 defer b.deinit();
1740
1741 var q = try Managed.init(testing.allocator);
1742 defer q.deinit();
1743 var r = try Managed.init(testing.allocator);
1744 defer r.deinit();
1745 try Managed.divTrunc(&q, &r, &a, &b);
1746
1747 try testing.expectEqual(0, try q.toInt(u128));
1748 try testing.expectEqual(op1, try r.toInt(u128));
1749}
1750
1751test "div trunc single-single +/+" {
1752 const u: i32 = 5;
1753 const v: i32 = 3;
1754
1755 var a = try Managed.initSet(testing.allocator, u);
1756 defer a.deinit();
1757 var b = try Managed.initSet(testing.allocator, v);
1758 defer b.deinit();
1759
1760 var q = try Managed.init(testing.allocator);
1761 defer q.deinit();
1762 var r = try Managed.init(testing.allocator);
1763 defer r.deinit();
1764 try Managed.divTrunc(&q, &r, &a, &b);
1765
1766 // n = q * d + r
1767 // 5 = 1 * 3 + 2
1768 const eq = @divTrunc(u, v);
1769 const er = @mod(u, v);
1770
1771 try testing.expectEqual(eq, try q.toInt(i32));
1772 try testing.expectEqual(er, try r.toInt(i32));
1773}
1774
1775test "div trunc single-single -/+" {
1776 const u: i32 = -5;
1777 const v: i32 = 3;
1778
1779 var a = try Managed.initSet(testing.allocator, u);
1780 defer a.deinit();
1781 var b = try Managed.initSet(testing.allocator, v);
1782 defer b.deinit();
1783
1784 var q = try Managed.init(testing.allocator);
1785 defer q.deinit();
1786 var r = try Managed.init(testing.allocator);
1787 defer r.deinit();
1788 try Managed.divTrunc(&q, &r, &a, &b);
1789
1790 // n = q * d + r
1791 // -5 = 1 * -3 - 2
1792 const eq = -1;
1793 const er = -2;
1794
1795 try testing.expectEqual(eq, try q.toInt(i32));
1796 try testing.expectEqual(er, try r.toInt(i32));
1797}
1798
1799test "div trunc single-single +/-" {
1800 const u: i32 = 5;
1801 const v: i32 = -3;
1802
1803 var a = try Managed.initSet(testing.allocator, u);
1804 defer a.deinit();
1805 var b = try Managed.initSet(testing.allocator, v);
1806 defer b.deinit();
1807
1808 var q = try Managed.init(testing.allocator);
1809 defer q.deinit();
1810 var r = try Managed.init(testing.allocator);
1811 defer r.deinit();
1812 try Managed.divTrunc(&q, &r, &a, &b);
1813
1814 // n = q * d + r
1815 // 5 = -1 * -3 + 2
1816 const eq = -1;
1817 const er = 2;
1818
1819 try testing.expectEqual(eq, try q.toInt(i32));
1820 try testing.expectEqual(er, try r.toInt(i32));
1821}
1822
1823test "div trunc single-single -/-" {
1824 const u: i32 = -5;
1825 const v: i32 = -3;
1826
1827 var a = try Managed.initSet(testing.allocator, u);
1828 defer a.deinit();
1829 var b = try Managed.initSet(testing.allocator, v);
1830 defer b.deinit();
1831
1832 var q = try Managed.init(testing.allocator);
1833 defer q.deinit();
1834 var r = try Managed.init(testing.allocator);
1835 defer r.deinit();
1836 try Managed.divTrunc(&q, &r, &a, &b);
1837
1838 // n = q * d + r
1839 // -5 = 1 * -3 - 2
1840 const eq = 1;
1841 const er = -2;
1842
1843 try testing.expectEqual(eq, try q.toInt(i32));
1844 try testing.expectEqual(er, try r.toInt(i32));
1845}
1846
1847test "divTrunc #15535" {
1848 var one = try Managed.initSet(testing.allocator, 1);
1849 defer one.deinit();
1850 var x = try Managed.initSet(testing.allocator, std.math.pow(u128, 2, 64));
1851 defer x.deinit();
1852 var r = try Managed.init(testing.allocator);
1853 defer r.deinit();
1854 var q = try Managed.init(testing.allocator);
1855 defer q.deinit();
1856 try q.divTrunc(&r, &x, &x);
1857 try testing.expectEqual(std.math.Order.lt, r.order(one));
1858}
1859
1860test "divFloor #10932" {
1861 var a = try Managed.init(testing.allocator);
1862 defer a.deinit();
1863
1864 var b = try Managed.init(testing.allocator);
1865 defer b.deinit();
1866
1867 var res = try Managed.init(testing.allocator);
1868 defer res.deinit();
1869
1870 try a.setString(10, "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1871 try b.setString(10, "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1872
1873 var mod = try Managed.init(testing.allocator);
1874 defer mod.deinit();
1875
1876 try res.divFloor(&mod, &a, &b);
1877
1878 const ress = try res.toString(testing.allocator, 16, .lower);
1879 defer testing.allocator.free(ress);
1880 try testing.expectEqualStrings("194bd136316c046d070b763396297bf8869a605030216b52597015902a172b2a752f62af1568dcd431602f03725bfa62b0be71ae86616210972c0126e173503011ca48c5747ff066d159c95e46b69cbb14c8fc0bd2bf0919f921be96463200000000000000000000000000000000000000000000000000000000000000000000000000000000", ress);
1881 try testing.expectEqual(0, try mod.toInt(i32));
1882}
1883
1884test "divFloor #11166" {
1885 var a = try Managed.init(testing.allocator);
1886 defer a.deinit();
1887
1888 var b = try Managed.init(testing.allocator);
1889 defer b.deinit();
1890
1891 var res = try Managed.init(testing.allocator);
1892 defer res.deinit();
1893
1894 try a.setString(10, "10000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1895 try b.setString(10, "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1896
1897 var mod = try Managed.init(testing.allocator);
1898 defer mod.deinit();
1899
1900 try res.divFloor(&mod, &a, &b);
1901
1902 const ress = try res.toString(testing.allocator, 10, .lower);
1903 defer testing.allocator.free(ress);
1904 try testing.expectEqualStrings("1000000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", ress);
1905
1906 const mods = try mod.toString(testing.allocator, 10, .lower);
1907 defer testing.allocator.free(mods);
1908 try testing.expectEqualStrings("870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", mods);
1909}
1910
1911test "gcd #10932" {
1912 var a = try Managed.init(testing.allocator);
1913 defer a.deinit();
1914
1915 var b = try Managed.init(testing.allocator);
1916 defer b.deinit();
1917
1918 var res = try Managed.init(testing.allocator);
1919 defer res.deinit();
1920
1921 try a.setString(10, "3000000000000000000000000000000000000000000000000000000000000000000000001461501637330902918203684832716283019655932542975000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1922 try b.setString(10, "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200001001500000000000000000100000000040000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000003000000000000000000000000000000000000000000000000000058715661000000000000000000000000000000000000023553252000000000180000000000000000000000000000000000000000000000000250000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001005000002000000000000000000000000000000000000000021000000001000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000200000000000000000000004000000000000000000000000000000000000000000000301000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1923
1924 try res.gcd(&a, &b);
1925
1926 const ress = try res.toString(testing.allocator, 16, .lower);
1927 defer testing.allocator.free(ress);
1928 try testing.expectEqualStrings("1a974a5c9734476ff5a3604bcc678a756beacfc21b4427d1f2c1f56f5d4e411a162c56136e20000000000000000000000000000000", ress);
1929}
1930
1931test "bitAnd #10932" {
1932 var a = try Managed.init(testing.allocator);
1933 defer a.deinit();
1934
1935 var b = try Managed.init(testing.allocator);
1936 defer b.deinit();
1937
1938 var res = try Managed.init(testing.allocator);
1939 defer res.deinit();
1940
1941 try a.setString(10, "154954885951624787839743960731760616696");
1942 try b.setString(10, "55000000000915215865915724129619485917228346934191537590366734850266784978214506142389798064826139649163838075568111457203909393174933092857416500785632012953993352521899237655507306575657169267399324107627651067352600878339870446048204062696260567762088867991835386857942106708741836433444432529637331429212430394179472179237695833247299409249810963487516399177133175950185719220422442438098353430605822151595560743492661038899294517012784306863064670126197566982968906306814338148792888550378533207318063660581924736840687332023636827401670268933229183389040490792300121030647791095178823932734160000000000000000000000000000000000000555555550000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
1943
1944 try res.bitAnd(&a, &b);
1945
1946 try testing.expectEqual(0, try res.toInt(i32));
1947}
1948
1949test "bit And #19235" {
1950 var a = try Managed.initSet(testing.allocator, -0xffffffffffffffff);
1951 defer a.deinit();
1952 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
1953 defer b.deinit();
1954 var r = try Managed.init(testing.allocator);
1955 defer r.deinit();
1956
1957 try r.bitAnd(&a, &b);
1958
1959 try testing.expectEqual(0x10000000000000000, try r.toInt(i128));
1960}
1961
1962test "div floor single-single +/+" {
1963 const u: i32 = 5;
1964 const v: i32 = 3;
1965
1966 var a = try Managed.initSet(testing.allocator, u);
1967 defer a.deinit();
1968 var b = try Managed.initSet(testing.allocator, v);
1969 defer b.deinit();
1970
1971 var q = try Managed.init(testing.allocator);
1972 defer q.deinit();
1973 var r = try Managed.init(testing.allocator);
1974 defer r.deinit();
1975 try Managed.divFloor(&q, &r, &a, &b);
1976
1977 // n = q * d + r
1978 // 5 = 1 * 3 + 2
1979 const eq = 1;
1980 const er = 2;
1981
1982 try testing.expectEqual(eq, try q.toInt(i32));
1983 try testing.expectEqual(er, try r.toInt(i32));
1984}
1985
1986test "div floor single-single -/+" {
1987 const u: i32 = -5;
1988 const v: i32 = 3;
1989
1990 var a = try Managed.initSet(testing.allocator, u);
1991 defer a.deinit();
1992 var b = try Managed.initSet(testing.allocator, v);
1993 defer b.deinit();
1994
1995 var q = try Managed.init(testing.allocator);
1996 defer q.deinit();
1997 var r = try Managed.init(testing.allocator);
1998 defer r.deinit();
1999 try Managed.divFloor(&q, &r, &a, &b);
2000
2001 // n = q * d + r
2002 // -5 = -2 * 3 + 1
2003 const eq = -2;
2004 const er = 1;
2005
2006 try testing.expectEqual(eq, try q.toInt(i32));
2007 try testing.expectEqual(er, try r.toInt(i32));
2008}
2009
2010test "div floor single-single +/-" {
2011 const u: i32 = 5;
2012 const v: i32 = -3;
2013
2014 var a = try Managed.initSet(testing.allocator, u);
2015 defer a.deinit();
2016 var b = try Managed.initSet(testing.allocator, v);
2017 defer b.deinit();
2018
2019 var q = try Managed.init(testing.allocator);
2020 defer q.deinit();
2021 var r = try Managed.init(testing.allocator);
2022 defer r.deinit();
2023 try Managed.divFloor(&q, &r, &a, &b);
2024
2025 // n = q * d + r
2026 // 5 = -2 * -3 - 1
2027 const eq = -2;
2028 const er = -1;
2029
2030 try testing.expectEqual(eq, try q.toInt(i32));
2031 try testing.expectEqual(er, try r.toInt(i32));
2032}
2033
2034test "div floor single-single -/-" {
2035 const u: i32 = -5;
2036 const v: i32 = -3;
2037
2038 var a = try Managed.initSet(testing.allocator, u);
2039 defer a.deinit();
2040 var b = try Managed.initSet(testing.allocator, v);
2041 defer b.deinit();
2042
2043 var q = try Managed.init(testing.allocator);
2044 defer q.deinit();
2045 var r = try Managed.init(testing.allocator);
2046 defer r.deinit();
2047 try Managed.divFloor(&q, &r, &a, &b);
2048
2049 // n = q * d + r
2050 // -5 = 2 * -3 + 1
2051 const eq = 1;
2052 const er = -2;
2053
2054 try testing.expectEqual(eq, try q.toInt(i32));
2055 try testing.expectEqual(er, try r.toInt(i32));
2056}
2057
2058test "div floor no remainder negative quotient" {
2059 const u: i32 = -0x80000000;
2060 const v: i32 = 1;
2061
2062 var a = try Managed.initSet(testing.allocator, u);
2063 defer a.deinit();
2064 var b = try Managed.initSet(testing.allocator, v);
2065 defer b.deinit();
2066
2067 var q = try Managed.init(testing.allocator);
2068 defer q.deinit();
2069 var r = try Managed.init(testing.allocator);
2070 defer r.deinit();
2071 try Managed.divFloor(&q, &r, &a, &b);
2072
2073 try testing.expectEqual(-0x80000000, try q.toInt(i32));
2074 try testing.expectEqual(0, try r.toInt(i32));
2075}
2076
2077test "div floor negative close to zero" {
2078 const u: i32 = -2;
2079 const v: i32 = 12;
2080
2081 var a = try Managed.initSet(testing.allocator, u);
2082 defer a.deinit();
2083 var b = try Managed.initSet(testing.allocator, v);
2084 defer b.deinit();
2085
2086 var q = try Managed.init(testing.allocator);
2087 defer q.deinit();
2088 var r = try Managed.init(testing.allocator);
2089 defer r.deinit();
2090 try Managed.divFloor(&q, &r, &a, &b);
2091
2092 try testing.expectEqual(-1, try q.toInt(i32));
2093 try testing.expectEqual(10, try r.toInt(i32));
2094}
2095
2096test "div floor positive close to zero" {
2097 const u: i32 = 10;
2098 const v: i32 = 12;
2099
2100 var a = try Managed.initSet(testing.allocator, u);
2101 defer a.deinit();
2102 var b = try Managed.initSet(testing.allocator, v);
2103 defer b.deinit();
2104
2105 var q = try Managed.init(testing.allocator);
2106 defer q.deinit();
2107 var r = try Managed.init(testing.allocator);
2108 defer r.deinit();
2109 try Managed.divFloor(&q, &r, &a, &b);
2110
2111 try testing.expectEqual(0, try q.toInt(i32));
2112 try testing.expectEqual(10, try r.toInt(i32));
2113}
2114
2115fn testDivCeil(comptime T: type, u: T, v: T, eq: T, er: T) !void {
2116 var a = try Managed.initSet(testing.allocator, u);
2117 defer a.deinit();
2118 var b = try Managed.initSet(testing.allocator, v);
2119 defer b.deinit();
2120
2121 var q = try Managed.init(testing.allocator);
2122 defer q.deinit();
2123 var r = try Managed.init(testing.allocator);
2124 defer r.deinit();
2125
2126 try Managed.divCeil(&q, &r, &a, &b);
2127
2128 try testing.expectEqual(eq, try q.toInt(T));
2129 try testing.expectEqual(er, try r.toInt(T));
2130}
2131
2132test "div ceil small" {
2133 try testDivCeil(i32, 5, 3, 2, -1);
2134 try testDivCeil(i32, -5, 3, -1, -2);
2135 try testDivCeil(i32, 5, -3, -1, 2);
2136 try testDivCeil(i32, -5, -3, 2, 1);
2137 try testDivCeil(i32, -0x80000000, 1, -0x80000000, 0);
2138}
2139
2140test "div ceil multi-limb" {
2141 {
2142 const a = (@as(i128, 1) << 100) + 3;
2143 const b: i128 = 4;
2144 try testDivCeil(i128, a, b, (1 << 98) + 1, -1);
2145 }
2146 {
2147 const a = -((@as(i128, 1) << 100) + 3);
2148 const b: i128 = 4;
2149 try testDivCeil(i128, a, b, -(1 << 98), -3);
2150 }
2151}
2152
2153test "div multi-multi with rem" {
2154 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);
2155 defer a.deinit();
2156 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
2157 defer b.deinit();
2158
2159 var q = try Managed.init(testing.allocator);
2160 defer q.deinit();
2161 var r = try Managed.init(testing.allocator);
2162 defer r.deinit();
2163 try Managed.divTrunc(&q, &r, &a, &b);
2164
2165 try testing.expectEqual(0xe38f38e39161aaabd03f0f1b, try q.toInt(u128));
2166 try testing.expectEqual(0x28de0acacd806823638, try r.toInt(u128));
2167}
2168
2169test "div multi-multi no rem" {
2170 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);
2171 defer a.deinit();
2172 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
2173 defer b.deinit();
2174
2175 var q = try Managed.init(testing.allocator);
2176 defer q.deinit();
2177 var r = try Managed.init(testing.allocator);
2178 defer r.deinit();
2179 try Managed.divTrunc(&q, &r, &a, &b);
2180
2181 try testing.expectEqual(0xe38f38e39161aaabd03f0f1b, try q.toInt(u128));
2182 try testing.expectEqual(0, try r.toInt(u128));
2183}
2184
2185test "div multi-multi (2 branch)" {
2186 var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);
2187 defer a.deinit();
2188 var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);
2189 defer b.deinit();
2190
2191 var q = try Managed.init(testing.allocator);
2192 defer q.deinit();
2193 var r = try Managed.init(testing.allocator);
2194 defer r.deinit();
2195 try Managed.divTrunc(&q, &r, &a, &b);
2196
2197 try testing.expectEqual(0x10000000000000000, try q.toInt(u128));
2198 try testing.expectEqual(0x44444443444444431111111111111111, try r.toInt(u128));
2199}
2200
2201test "div multi-multi (3.1/3.3 branch)" {
2202 var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);
2203 defer a.deinit();
2204 var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);
2205 defer b.deinit();
2206
2207 var q = try Managed.init(testing.allocator);
2208 defer q.deinit();
2209 var r = try Managed.init(testing.allocator);
2210 defer r.deinit();
2211 try Managed.divTrunc(&q, &r, &a, &b);
2212
2213 try testing.expectEqual(0xfffffffffffffffffff, try q.toInt(u128));
2214 try testing.expectEqual(0x1111111111111111111110b12222222222222222282, try r.toInt(u256));
2215}
2216
2217test "div multi-single zero-limb trailing" {
2218 var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);
2219 defer a.deinit();
2220 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
2221 defer b.deinit();
2222
2223 var q = try Managed.init(testing.allocator);
2224 defer q.deinit();
2225 var r = try Managed.init(testing.allocator);
2226 defer r.deinit();
2227 try Managed.divTrunc(&q, &r, &a, &b);
2228
2229 var expected = try Managed.initSet(testing.allocator, 0x6000000000000000000000000000000000000000000000000);
2230 defer expected.deinit();
2231 try testing.expect(q.eql(expected));
2232 try testing.expect(r.eqlZero());
2233}
2234
2235test "div multi-multi zero-limb trailing (with rem)" {
2236 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2237 defer a.deinit();
2238 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
2239 defer b.deinit();
2240
2241 var q = try Managed.init(testing.allocator);
2242 defer q.deinit();
2243 var r = try Managed.init(testing.allocator);
2244 defer r.deinit();
2245 try Managed.divTrunc(&q, &r, &a, &b);
2246
2247 try testing.expectEqual(0x10000000000000000, try q.toInt(u128));
2248
2249 const rs = try r.toString(testing.allocator, 16, .lower);
2250 defer testing.allocator.free(rs);
2251 try testing.expectEqualStrings("4444444344444443111111111111111100000000000000000000000000000000", rs);
2252}
2253
2254test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
2255 var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);
2256 defer a.deinit();
2257 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
2258 defer b.deinit();
2259
2260 var q = try Managed.init(testing.allocator);
2261 defer q.deinit();
2262 var r = try Managed.init(testing.allocator);
2263 defer r.deinit();
2264 try Managed.divTrunc(&q, &r, &a, &b);
2265
2266 try testing.expectEqual(0x1, try q.toInt(u128));
2267
2268 const rs = try r.toString(testing.allocator, 16, .lower);
2269 defer testing.allocator.free(rs);
2270 try testing.expectEqualStrings("444444434444444311111111111111110000000000000000", rs);
2271}
2272
2273test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
2274 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2275 defer a.deinit();
2276 var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);
2277 defer b.deinit();
2278
2279 var q = try Managed.init(testing.allocator);
2280 defer q.deinit();
2281 var r = try Managed.init(testing.allocator);
2282 defer r.deinit();
2283 try Managed.divTrunc(&q, &r, &a, &b);
2284
2285 const qs = try q.toString(testing.allocator, 16, .lower);
2286 defer testing.allocator.free(qs);
2287 try testing.expectEqualStrings("10000000000000000820820803105186f", qs);
2288
2289 const rs = try r.toString(testing.allocator, 16, .lower);
2290 defer testing.allocator.free(rs);
2291 try testing.expectEqualStrings("4e11f2baa5896a321d463b543d0104e30000000000000000", rs);
2292}
2293
2294test "div multi-multi fuzz case #1" {
2295 var a = try Managed.init(testing.allocator);
2296 defer a.deinit();
2297 var b = try Managed.init(testing.allocator);
2298 defer b.deinit();
2299
2300 try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2301 try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff");
2302
2303 var q = try Managed.init(testing.allocator);
2304 defer q.deinit();
2305 var r = try Managed.init(testing.allocator);
2306 defer r.deinit();
2307 try Managed.divTrunc(&q, &r, &a, &b);
2308
2309 const qs = try q.toString(testing.allocator, 16, .lower);
2310 defer testing.allocator.free(qs);
2311 try testing.expectEqualStrings("3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1", qs);
2312
2313 const rs = try r.toString(testing.allocator, 16, .lower);
2314 defer testing.allocator.free(rs);
2315 try testing.expectEqualStrings("310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1", rs);
2316}
2317
2318test "div multi-multi fuzz case #2" {
2319 var a = try Managed.init(testing.allocator);
2320 defer a.deinit();
2321 var b = try Managed.init(testing.allocator);
2322 defer b.deinit();
2323
2324 try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000");
2325 try b.setString(16, "ffc0000000000000000000000000000000000000000000000000");
2326
2327 var q = try Managed.init(testing.allocator);
2328 defer q.deinit();
2329 var r = try Managed.init(testing.allocator);
2330 defer r.deinit();
2331 try Managed.divTrunc(&q, &r, &a, &b);
2332
2333 const qs = try q.toString(testing.allocator, 16, .lower);
2334 defer testing.allocator.free(qs);
2335 try testing.expectEqualStrings("40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4", qs);
2336
2337 const rs = try r.toString(testing.allocator, 16, .lower);
2338 defer testing.allocator.free(rs);
2339 try testing.expectEqualStrings("a900000000000000000000000000000000000000000000000000", rs);
2340}
2341
2342test "truncate single unsigned" {
2343 var a = try Managed.initSet(testing.allocator, maxInt(u47));
2344 defer a.deinit();
2345
2346 try a.truncate(&a, .unsigned, 17);
2347
2348 try testing.expectEqual(maxInt(u17), try a.toInt(u17));
2349}
2350
2351test "truncate single signed" {
2352 var a = try Managed.initSet(testing.allocator, 0x1_0000);
2353 defer a.deinit();
2354
2355 try a.truncate(&a, .signed, 17);
2356
2357 try testing.expectEqual(minInt(i17), try a.toInt(i17));
2358}
2359
2360test "truncate multi to single unsigned" {
2361 var a = try Managed.initSet(testing.allocator, (maxInt(Limb) + 1) | 0x1234_5678_9ABC_DEF0);
2362 defer a.deinit();
2363
2364 try a.truncate(&a, .unsigned, 27);
2365
2366 try testing.expectEqual(0x2BC_DEF0, try a.toInt(u27));
2367}
2368
2369test "truncate multi to single signed" {
2370 var a = try Managed.initSet(testing.allocator, maxInt(Limb) << 10);
2371 defer a.deinit();
2372
2373 try a.truncate(&a, .signed, @bitSizeOf(i11));
2374
2375 try testing.expectEqual(minInt(i11), try a.toInt(i11));
2376}
2377
2378test "truncate multi to multi unsigned" {
2379 const bits = @typeInfo(SignedDoubleLimb).int.bits;
2380 const Int = @Int(.unsigned, bits - 1);
2381
2382 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
2383 defer a.deinit();
2384
2385 try a.truncate(&a, .unsigned, bits - 1);
2386
2387 try testing.expectEqual(maxInt(Int), try a.toInt(Int));
2388}
2389
2390test "truncate multi to multi signed" {
2391 var a = try Managed.initSet(testing.allocator, 3 << @bitSizeOf(Limb));
2392 defer a.deinit();
2393
2394 try a.truncate(&a, .signed, @bitSizeOf(Limb) + 1);
2395
2396 try testing.expectEqual(-1 << @bitSizeOf(Limb), try a.toInt(@Int(.signed, @bitSizeOf(Limb) + 1)));
2397}
2398
2399test "truncate negative multi to single" {
2400 var a = try Managed.initSet(testing.allocator, -@as(SignedDoubleLimb, maxInt(Limb) + 1));
2401 defer a.deinit();
2402
2403 try a.truncate(&a, .signed, @bitSizeOf(i17));
2404
2405 try testing.expectEqual(0, try a.toInt(i17));
2406}
2407
2408test "truncate multi unsigned many" {
2409 var a = try Managed.initSet(testing.allocator, 1);
2410 defer a.deinit();
2411 const shift = 1023;
2412 try a.ensureCapacity(a.len() + (shift / @bitSizeOf(Limb)) + 1);
2413 try a.shiftLeft(&a, shift);
2414
2415 var b = try Managed.init(testing.allocator);
2416 defer b.deinit();
2417 try b.truncate(&a, .signed, @bitSizeOf(i1));
2418
2419 try testing.expectEqual(0, try b.toInt(i1));
2420}
2421
2422test "truncate to mutable with fewer limbs" {
2423 var res_limbs: [1]Limb = undefined;
2424 var res: Mutable = .{
2425 .limbs = &res_limbs,
2426 .len = undefined,
2427 .positive = undefined,
2428 };
2429 res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
2430 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2431 res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
2432 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2433 res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
2434 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2435 res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
2436 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2437 res.truncate(.{ .positive = true, .limbs = &.{ maxInt(Limb), 1 } }, .unsigned, @bitSizeOf(Limb));
2438 try testing.expect(res.toConst().orderAgainstScalar(maxInt(Limb)).compare(.eq));
2439 res.truncate(.{ .positive = true, .limbs = &.{ maxInt(Limb), 1 } }, .signed, @bitSizeOf(Limb));
2440 try testing.expect(res.toConst().orderAgainstScalar(-1).compare(.eq));
2441 res.truncate(.{ .positive = false, .limbs = &.{ maxInt(Limb), 1 } }, .unsigned, @bitSizeOf(Limb));
2442 try testing.expect(res.toConst().orderAgainstScalar(1).compare(.eq));
2443 res.truncate(.{ .positive = false, .limbs = &.{ maxInt(Limb), 1 } }, .signed, @bitSizeOf(Limb));
2444 try testing.expect(res.toConst().orderAgainstScalar(1).compare(.eq));
2445}
2446
2447test "truncate value that normalizes after being masked" {
2448 var res_limbs: [2]Limb = undefined;
2449 var res: Mutable = .{
2450 .limbs = &res_limbs,
2451 .len = undefined,
2452 .positive = undefined,
2453 };
2454 res.truncate(.{ .positive = true, .limbs = &.{ 0, 2 } }, .signed, 1 + @bitSizeOf(Limb));
2455 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2456 res.truncate(.{ .positive = true, .limbs = &.{ 1, 2 } }, .signed, 1 + @bitSizeOf(Limb));
2457 try testing.expect(res.toConst().orderAgainstScalar(1).compare(.eq));
2458}
2459
2460test "truncate to zero" {
2461 var res_limbs: [1]Limb = undefined;
2462 var res: Mutable = .{
2463 .limbs = &res_limbs,
2464 .len = undefined,
2465 .positive = undefined,
2466 };
2467 res.truncate(.{ .positive = true, .limbs = &.{0} }, .signed, @bitSizeOf(Limb));
2468 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2469 res.truncate(.{ .positive = false, .limbs = &.{0} }, .signed, @bitSizeOf(Limb));
2470 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2471 res.truncate(.{ .positive = true, .limbs = &.{0} }, .unsigned, @bitSizeOf(Limb));
2472 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2473 res.truncate(.{ .positive = false, .limbs = &.{0} }, .unsigned, @bitSizeOf(Limb));
2474 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2475 res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
2476 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2477 res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
2478 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2479 res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
2480 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2481 res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
2482 try testing.expect(res.positive and res.len == 1 and res.limbs[0] == 0);
2483}
2484
2485test "truncate to minimum signed integer" {
2486 var res_limbs: [1]Limb = undefined;
2487 var res: Mutable = .{
2488 .limbs = &res_limbs,
2489 .len = undefined,
2490 .positive = undefined,
2491 };
2492 res.truncate(.{ .positive = true, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .signed, @bitSizeOf(Limb));
2493 try testing.expect(res.toConst().orderAgainstScalar(-1 << @bitSizeOf(Limb) - 1).compare(.eq));
2494 res.truncate(.{ .positive = false, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .signed, @bitSizeOf(Limb));
2495 try testing.expect(res.toConst().orderAgainstScalar(-1 << @bitSizeOf(Limb) - 1).compare(.eq));
2496 res.truncate(.{ .positive = true, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .unsigned, @bitSizeOf(Limb));
2497 try testing.expect(res.toConst().orderAgainstScalar(1 << @bitSizeOf(Limb) - 1).compare(.eq));
2498 res.truncate(.{ .positive = false, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .unsigned, @bitSizeOf(Limb));
2499 try testing.expect(res.toConst().orderAgainstScalar(1 << @bitSizeOf(Limb) - 1).compare(.eq));
2500}
2501
2502test "saturate single signed positive" {
2503 var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
2504 defer a.deinit();
2505
2506 try a.saturate(&a, .signed, 17);
2507
2508 try testing.expectEqual(maxInt(i17), try a.toInt(i17));
2509}
2510
2511test "saturate single signed negative" {
2512 var a = try Managed.initSet(testing.allocator, -1_234_567);
2513 defer a.deinit();
2514
2515 try a.saturate(&a, .signed, 17);
2516
2517 try testing.expectEqual(minInt(i17), try a.toInt(i17));
2518}
2519
2520test "saturate single signed" {
2521 var a = try Managed.initSet(testing.allocator, maxInt(i17) - 1);
2522 defer a.deinit();
2523
2524 try a.saturate(&a, .signed, 17);
2525
2526 try testing.expectEqual(maxInt(i17) - 1, try a.toInt(i17));
2527}
2528
2529test "saturate multi signed" {
2530 var a = try Managed.initSet(testing.allocator, maxInt(Limb) << @bitSizeOf(SignedDoubleLimb));
2531 defer a.deinit();
2532
2533 try a.saturate(&a, .signed, @bitSizeOf(SignedDoubleLimb));
2534
2535 try testing.expectEqual(maxInt(SignedDoubleLimb), try a.toInt(SignedDoubleLimb));
2536}
2537
2538test "saturate single unsigned" {
2539 var a = try Managed.initSet(testing.allocator, 0xFEFE_FEFE);
2540 defer a.deinit();
2541
2542 try a.saturate(&a, .unsigned, 23);
2543
2544 try testing.expectEqual(maxInt(u23), try a.toInt(u23));
2545}
2546
2547test "saturate multi unsigned zero" {
2548 var a = try Managed.initSet(testing.allocator, -1);
2549 defer a.deinit();
2550
2551 try a.saturate(&a, .unsigned, @bitSizeOf(DoubleLimb));
2552
2553 try testing.expect(a.eqlZero());
2554}
2555
2556test "saturate multi unsigned" {
2557 var a = try Managed.initSet(testing.allocator, maxInt(Limb) << @bitSizeOf(DoubleLimb));
2558 defer a.deinit();
2559
2560 try a.saturate(&a, .unsigned, @bitSizeOf(DoubleLimb));
2561
2562 try testing.expectEqual(maxInt(DoubleLimb), try a.toInt(DoubleLimb));
2563}
2564
2565test "shift-right single" {
2566 var a = try Managed.initSet(testing.allocator, 0xffff0000);
2567 defer a.deinit();
2568 try a.shiftRight(&a, 16);
2569
2570 try testing.expectEqual(0xffff, try a.toInt(u32));
2571}
2572
2573test "shift-right multi" {
2574 var a = try Managed.initSet(testing.allocator, 0xffff0000eeee1111dddd2222cccc3333);
2575 defer a.deinit();
2576 try a.shiftRight(&a, 67);
2577
2578 try testing.expectEqual(0x1fffe0001dddc222, try a.toInt(u64));
2579
2580 try a.set(0xffff0000eeee1111dddd2222cccc3333);
2581 try a.shiftRight(&a, 63);
2582 try a.shiftRight(&a, 63);
2583 try a.shiftRight(&a, 2);
2584 try testing.expect(a.eqlZero());
2585
2586 try a.set(0xffff0000eeee1111dddd2222cccc3333000000000000000000000);
2587 try a.shiftRight(&a, 84);
2588 const string = try a.toString(
2589 testing.allocator,
2590 16,
2591 .lower,
2592 );
2593 defer testing.allocator.free(string);
2594 try std.testing.expectEqualStrings(
2595 "ffff0000eeee1111dddd2222cccc3333",
2596 string,
2597 );
2598}
2599
2600test "shift-left single" {
2601 var a = try Managed.initSet(testing.allocator, 0xffff);
2602 defer a.deinit();
2603 try a.shiftLeft(&a, 16);
2604
2605 try testing.expectEqual(0xffff0000, try a.toInt(u64));
2606}
2607
2608test "shift-left multi" {
2609 var a = try Managed.initSet(testing.allocator, 0x1fffe0001dddc222);
2610 defer a.deinit();
2611 try a.shiftLeft(&a, 67);
2612
2613 try testing.expectEqual(0xffff0000eeee11100000000000000000, try a.toInt(u128));
2614}
2615
2616test "shift-right negative" {
2617 var a = try Managed.init(testing.allocator);
2618 defer a.deinit();
2619
2620 var arg = try Managed.initSet(testing.allocator, -20);
2621 defer arg.deinit();
2622 try a.shiftRight(&arg, 2);
2623 try testing.expectEqual(-5, try a.toInt(i32)); // -20 >> 2 == -5
2624
2625 var arg2 = try Managed.initSet(testing.allocator, -5);
2626 defer arg2.deinit();
2627 try a.shiftRight(&arg2, 10);
2628 try testing.expectEqual(-1, try a.toInt(i32)); // -5 >> 10 == -1
2629
2630 var arg3 = try Managed.initSet(testing.allocator, -10);
2631 defer arg3.deinit();
2632 try a.shiftRight(&arg3, 1232);
2633 try testing.expectEqual(-1, try a.toInt(i32)); // -10 >> 1232 == -1
2634
2635 var arg4 = try Managed.initSet(testing.allocator, -5);
2636 defer arg4.deinit();
2637 try a.shiftRight(&arg4, 2);
2638 try testing.expectEqual(-2, try a.toInt(i32)); // -5 >> 2 == -2
2639
2640 var arg5 = try Managed.initSet(testing.allocator, -0xffff0000eeee1111dddd2222cccc3333);
2641 defer arg5.deinit();
2642 try a.shiftRight(&arg5, 67);
2643 try testing.expectEqual(-0x1fffe0001dddc223, try a.toInt(i64));
2644
2645 var arg6 = try Managed.initSet(testing.allocator, -0x1ffffffffffffffff);
2646 defer arg6.deinit();
2647 try a.shiftRight(&arg6, 1);
2648 try a.shiftRight(&a, 1);
2649 a.setSign(true);
2650 try testing.expectEqual(0x8000000000000000, try a.toInt(u64));
2651
2652 var arg7 = try Managed.initSet(testing.allocator, -32767);
2653 defer arg7.deinit();
2654 a.setSign(false);
2655 try a.shiftRight(&arg7, 4);
2656 try testing.expectEqual(-2048, try a.toInt(i16));
2657 a.setSign(true);
2658 try a.shiftRight(&arg7, 4);
2659 try testing.expectEqual(-2048, try a.toInt(i16));
2660
2661 var arg8_limbs: [1]Limb = undefined;
2662 var arg8: Mutable = .{
2663 .limbs = &arg8_limbs,
2664 .len = undefined,
2665 .positive = undefined,
2666 };
2667 arg8.shiftRight(.{ .limbs = &.{ 1, 1 }, .positive = false }, @bitSizeOf(Limb));
2668 try testing.expect(arg8.toConst().orderAgainstScalar(-2).compare(.eq));
2669}
2670
2671test "sat shift-left simple unsigned" {
2672 var a = try Managed.initSet(testing.allocator, 0xffff);
2673 defer a.deinit();
2674 try a.shiftLeftSat(&a, 16, .unsigned, 21);
2675
2676 try testing.expectEqual(0x1fffff, try a.toInt(u64));
2677}
2678
2679test "sat shift-left simple unsigned no sat" {
2680 var a = try Managed.initSet(testing.allocator, 1);
2681 defer a.deinit();
2682 try a.shiftLeftSat(&a, 16, .unsigned, 21);
2683
2684 try testing.expectEqual(0x10000, try a.toInt(u64));
2685}
2686
2687test "sat shift-left multi unsigned" {
2688 var a = try Managed.initSet(testing.allocator, 16);
2689 defer a.deinit();
2690 try a.shiftLeftSat(&a, @bitSizeOf(DoubleLimb) - 3, .unsigned, @bitSizeOf(DoubleLimb) - 1);
2691
2692 try testing.expectEqual(maxInt(DoubleLimb) >> 1, try a.toInt(DoubleLimb));
2693}
2694
2695test "sat shift-left unsigned shift > bitcount" {
2696 var a = try Managed.initSet(testing.allocator, 1);
2697 defer a.deinit();
2698 try a.shiftLeftSat(&a, 10, .unsigned, 10);
2699
2700 try testing.expectEqual(maxInt(u10), try a.toInt(u10));
2701}
2702
2703test "sat shift-left unsigned zero" {
2704 var a = try Managed.initSet(testing.allocator, 0);
2705 defer a.deinit();
2706 try a.shiftLeftSat(&a, 1, .unsigned, 0);
2707
2708 try testing.expectEqual(0, try a.toInt(u64));
2709}
2710
2711test "sat shift-left unsigned negative" {
2712 var a = try Managed.initSet(testing.allocator, -100);
2713 defer a.deinit();
2714 try a.shiftLeftSat(&a, 0, .unsigned, 0);
2715
2716 try testing.expectEqual(0, try a.toInt(u64));
2717}
2718
2719test "sat shift-left signed simple negative" {
2720 var a = try Managed.initSet(testing.allocator, -100);
2721 defer a.deinit();
2722 try a.shiftLeftSat(&a, 3, .signed, 10);
2723
2724 try testing.expectEqual(minInt(i10), try a.toInt(i10));
2725}
2726
2727test "sat shift-left signed simple positive" {
2728 var a = try Managed.initSet(testing.allocator, 100);
2729 defer a.deinit();
2730 try a.shiftLeftSat(&a, 3, .signed, 10);
2731
2732 try testing.expectEqual(maxInt(i10), try a.toInt(i10));
2733}
2734
2735test "sat shift-left signed multi positive" {
2736 var x: SignedDoubleLimb = 1;
2737 _ = &x;
2738
2739 const shift = @bitSizeOf(SignedDoubleLimb) - 1;
2740
2741 var a = try Managed.initSet(testing.allocator, x);
2742 defer a.deinit();
2743 try a.shiftLeftSat(&a, shift, .signed, @bitSizeOf(SignedDoubleLimb));
2744
2745 try testing.expectEqual(x <<| shift, try a.toInt(SignedDoubleLimb));
2746}
2747
2748test "sat shift-left signed multi negative" {
2749 var x: SignedDoubleLimb = -1;
2750 _ = &x;
2751
2752 const shift = @bitSizeOf(SignedDoubleLimb) - 1;
2753
2754 var a = try Managed.initSet(testing.allocator, x);
2755 defer a.deinit();
2756 try a.shiftLeftSat(&a, shift, .signed, @bitSizeOf(SignedDoubleLimb));
2757
2758 try testing.expectEqual(x <<| shift, try a.toInt(SignedDoubleLimb));
2759}
2760
2761test "bitNotWrap unsigned simple" {
2762 var x: u10 = 123;
2763 _ = &x;
2764
2765 var a = try Managed.initSet(testing.allocator, x);
2766 defer a.deinit();
2767
2768 try a.bitNotWrap(&a, .unsigned, 10);
2769
2770 try testing.expectEqual(~x, try a.toInt(u10));
2771}
2772
2773test "bitNotWrap unsigned multi" {
2774 var a = try Managed.initSet(testing.allocator, 0);
2775 defer a.deinit();
2776
2777 try a.bitNotWrap(&a, .unsigned, @bitSizeOf(DoubleLimb));
2778
2779 try testing.expectEqual(maxInt(DoubleLimb), try a.toInt(DoubleLimb));
2780}
2781
2782test "bitNotWrap signed simple" {
2783 var x: i11 = -456;
2784 _ = &x;
2785
2786 var a = try Managed.initSet(testing.allocator, -456);
2787 defer a.deinit();
2788
2789 try a.bitNotWrap(&a, .signed, 11);
2790
2791 try testing.expectEqual(~x, try a.toInt(i11));
2792}
2793
2794test "bitNotWrap signed multi" {
2795 var a = try Managed.initSet(testing.allocator, 0);
2796 defer a.deinit();
2797
2798 try a.bitNotWrap(&a, .signed, @bitSizeOf(SignedDoubleLimb));
2799
2800 try testing.expectEqual(-1, try a.toInt(SignedDoubleLimb));
2801}
2802
2803test "bitNotWrap more than two limbs" {
2804 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
2805 defer a.deinit();
2806
2807 var res = try Managed.init(testing.allocator);
2808 defer res.deinit();
2809
2810 const bits = @bitSizeOf(Limb) * 4 + 2;
2811
2812 try res.bitNotWrap(&a, .unsigned, bits);
2813 const Unsigned = @Int(.unsigned, bits);
2814 try testing.expectEqual((try res.toInt(Unsigned)), ~@as(Unsigned, maxInt(Limb)));
2815
2816 try res.bitNotWrap(&a, .signed, bits);
2817 const Signed = @Int(.signed, bits);
2818 try testing.expectEqual((try res.toInt(Signed)), ~@as(Signed, maxInt(Limb)));
2819}
2820
2821test "bitwise and simple" {
2822 var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
2823 defer a.deinit();
2824 var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
2825 defer b.deinit();
2826
2827 try a.bitAnd(&a, &b);
2828
2829 try testing.expectEqual(0xeeeeeeee00000000, try a.toInt(u64));
2830}
2831
2832test "bitwise and multi-limb" {
2833 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
2834 defer a.deinit();
2835 var b = try Managed.initSet(testing.allocator, maxInt(Limb));
2836 defer b.deinit();
2837
2838 try a.bitAnd(&a, &b);
2839
2840 try testing.expectEqual(0, try a.toInt(u128));
2841}
2842
2843test "bitwise and negative-positive simple" {
2844 var a = try Managed.initSet(testing.allocator, -0xffffffff11111111);
2845 defer a.deinit();
2846 var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
2847 defer b.deinit();
2848
2849 try a.bitAnd(&a, &b);
2850
2851 try testing.expectEqual(0x22222222, try a.toInt(u64));
2852}
2853
2854test "bitwise and negative-positive multi-limb" {
2855 var a = try Managed.initSet(testing.allocator, -maxInt(Limb) - 1);
2856 defer a.deinit();
2857 var b = try Managed.initSet(testing.allocator, maxInt(Limb));
2858 defer b.deinit();
2859
2860 try a.bitAnd(&a, &b);
2861
2862 try testing.expect(a.eqlZero());
2863}
2864
2865test "bitwise and positive-negative simple" {
2866 var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
2867 defer a.deinit();
2868 var b = try Managed.initSet(testing.allocator, -0xeeeeeeee22222222);
2869 defer b.deinit();
2870
2871 try a.bitAnd(&a, &b);
2872
2873 try testing.expectEqual(0x1111111111111110, try a.toInt(u64));
2874}
2875
2876test "bitwise and positive-negative multi-limb" {
2877 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
2878 defer a.deinit();
2879 var b = try Managed.initSet(testing.allocator, -maxInt(Limb) - 1);
2880 defer b.deinit();
2881
2882 try a.bitAnd(&a, &b);
2883
2884 try testing.expect(a.eqlZero());
2885}
2886
2887test "bitwise and negative-negative simple" {
2888 var a = try Managed.initSet(testing.allocator, -0xffffffff11111111);
2889 defer a.deinit();
2890 var b = try Managed.initSet(testing.allocator, -0xeeeeeeee22222222);
2891 defer b.deinit();
2892
2893 try a.bitAnd(&a, &b);
2894
2895 try testing.expectEqual(-0xffffffff33333332, try a.toInt(i128));
2896}
2897
2898test "bitwise and negative-negative multi-limb" {
2899 var a = try Managed.initSet(testing.allocator, -maxInt(Limb) - 1);
2900 defer a.deinit();
2901 var b = try Managed.initSet(testing.allocator, -maxInt(Limb) - 2);
2902 defer b.deinit();
2903
2904 try a.bitAnd(&a, &b);
2905
2906 try testing.expectEqual(-maxInt(Limb) * 2 - 2, try a.toInt(i128));
2907}
2908
2909test "bitwise and negative overflow" {
2910 var a = try Managed.initSet(testing.allocator, -maxInt(Limb));
2911 defer a.deinit();
2912 var b = try Managed.initSet(testing.allocator, -2);
2913 defer b.deinit();
2914
2915 try a.bitAnd(&a, &b);
2916
2917 try testing.expectEqual(-maxInt(Limb) - 1, try a.toInt(SignedDoubleLimb));
2918}
2919
2920test "bitwise xor simple" {
2921 var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
2922 defer a.deinit();
2923 var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
2924 defer b.deinit();
2925
2926 try a.bitXor(&a, &b);
2927
2928 try testing.expectEqual(0x1111111133333333, try a.toInt(u64));
2929}
2930
2931test "bitwise xor multi-limb" {
2932 var x: DoubleLimb = maxInt(Limb) + 1;
2933 var y: DoubleLimb = maxInt(Limb);
2934 _ = .{ &x, &y };
2935
2936 var a = try Managed.initSet(testing.allocator, x);
2937 defer a.deinit();
2938 var b = try Managed.initSet(testing.allocator, y);
2939 defer b.deinit();
2940
2941 try a.bitXor(&a, &b);
2942
2943 try testing.expectEqual(x ^ y, try a.toInt(DoubleLimb));
2944}
2945
2946test "bitwise xor single negative simple" {
2947 var a = try Managed.initSet(testing.allocator, 0x6b03e381328a3154);
2948 defer a.deinit();
2949 var b = try Managed.initSet(testing.allocator, -0x45fd3acef9191fad);
2950 defer b.deinit();
2951
2952 try a.bitXor(&a, &b);
2953
2954 try testing.expectEqual(-0x2efed94fcb932ef9, try a.toInt(i64));
2955}
2956
2957test "bitwise xor single negative multi-limb" {
2958 var a = try Managed.initSet(testing.allocator, -0x9849c6e7a10d66d0e4260d4846254c32);
2959 defer a.deinit();
2960 var b = try Managed.initSet(testing.allocator, 0xf2194e7d1c855272a997fcde16f6d5a8);
2961 defer b.deinit();
2962
2963 try a.bitXor(&a, &b);
2964
2965 try testing.expectEqual(-0x6a50889abd8834a24db1f19650d3999a, try a.toInt(i128));
2966}
2967
2968test "bitwise xor single negative overflow" {
2969 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
2970 defer a.deinit();
2971 var b = try Managed.initSet(testing.allocator, -1);
2972 defer b.deinit();
2973
2974 try a.bitXor(&a, &b);
2975
2976 try testing.expectEqual(-(maxInt(Limb) + 1), try a.toInt(SignedDoubleLimb));
2977}
2978
2979test "bitwise xor double negative simple" {
2980 var a = try Managed.initSet(testing.allocator, -0x8e48bd5f755ef1f3);
2981 defer a.deinit();
2982 var b = try Managed.initSet(testing.allocator, -0x4dd4fa576f3046ac);
2983 defer b.deinit();
2984
2985 try a.bitXor(&a, &b);
2986
2987 try testing.expectEqual(0xc39c47081a6eb759, try a.toInt(u64));
2988}
2989
2990test "bitwise xor double negative multi-limb" {
2991 var a = try Managed.initSet(testing.allocator, -0x684e5da8f500ec8ca7204c33ccc51c9c);
2992 defer a.deinit();
2993 var b = try Managed.initSet(testing.allocator, -0xcb07736a7b62289c78d967c3985eebeb);
2994 defer b.deinit();
2995
2996 try a.bitXor(&a, &b);
2997
2998 try testing.expectEqual(0xa3492ec28e62c410dff92bf0549bf771, try a.toInt(u128));
2999}
3000
3001test "bitwise or simple" {
3002 var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
3003 defer a.deinit();
3004 var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
3005 defer b.deinit();
3006
3007 try a.bitOr(&a, &b);
3008
3009 try testing.expectEqual(0xffffffff33333333, try a.toInt(u64));
3010}
3011
3012test "bitwise or multi-limb" {
3013 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
3014 defer a.deinit();
3015 var b = try Managed.initSet(testing.allocator, maxInt(Limb));
3016 defer b.deinit();
3017
3018 try a.bitOr(&a, &b);
3019
3020 try testing.expectEqual((maxInt(Limb) + 1) + maxInt(Limb), try a.toInt(DoubleLimb));
3021}
3022
3023test "bitwise or negative-positive simple" {
3024 var a = try Managed.initSet(testing.allocator, -0xffffffff11111111);
3025 defer a.deinit();
3026 var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
3027 defer b.deinit();
3028
3029 try a.bitOr(&a, &b);
3030
3031 try testing.expectEqual(-0x1111111111111111, try a.toInt(i64));
3032}
3033
3034test "bitwise or negative-positive multi-limb" {
3035 var a = try Managed.initSet(testing.allocator, -maxInt(Limb) - 1);
3036 defer a.deinit();
3037 var b = try Managed.initSet(testing.allocator, 1);
3038 defer b.deinit();
3039
3040 try a.bitOr(&a, &b);
3041
3042 try testing.expectEqual(-maxInt(Limb), try a.toInt(SignedDoubleLimb));
3043}
3044
3045test "bitwise or positive-negative simple" {
3046 var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
3047 defer a.deinit();
3048 var b = try Managed.initSet(testing.allocator, -0xeeeeeeee22222222);
3049 defer b.deinit();
3050
3051 try a.bitOr(&a, &b);
3052
3053 try testing.expectEqual(-0x22222221, try a.toInt(i64));
3054}
3055
3056test "bitwise or positive-negative multi-limb" {
3057 var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
3058 defer a.deinit();
3059 var b = try Managed.initSet(testing.allocator, -1);
3060 defer b.deinit();
3061
3062 try a.bitOr(&a, &b);
3063
3064 try testing.expectEqual(-1, try a.toInt(SignedDoubleLimb));
3065}
3066
3067test "bitwise or negative-negative simple" {
3068 var a = try Managed.initSet(testing.allocator, -0xffffffff11111111);
3069 defer a.deinit();
3070 var b = try Managed.initSet(testing.allocator, -0xeeeeeeee22222222);
3071 defer b.deinit();
3072
3073 try a.bitOr(&a, &b);
3074
3075 try testing.expectEqual(-0xeeeeeeee00000001, try a.toInt(i128));
3076}
3077
3078test "bitwise or negative-negative multi-limb" {
3079 var a = try Managed.initSet(testing.allocator, -maxInt(Limb) - 1);
3080 defer a.deinit();
3081 var b = try Managed.initSet(testing.allocator, -maxInt(Limb));
3082 defer b.deinit();
3083
3084 try a.bitOr(&a, &b);
3085
3086 try testing.expectEqual(-maxInt(Limb), try a.toInt(SignedDoubleLimb));
3087}
3088
3089test "var args" {
3090 var a = try Managed.initSet(testing.allocator, 5);
3091 defer a.deinit();
3092
3093 var b = try Managed.initSet(testing.allocator, 6);
3094 defer b.deinit();
3095 try a.add(&a, &b);
3096 try testing.expectEqual(11, try a.toInt(u64));
3097
3098 var c = try Managed.initSet(testing.allocator, 11);
3099 defer c.deinit();
3100 try testing.expectEqual(.eq, a.order(c));
3101
3102 var d = try Managed.initSet(testing.allocator, 14);
3103 defer d.deinit();
3104 try testing.expect(a.order(d) != .gt);
3105}
3106
3107test "gcd non-one small" {
3108 var a = try Managed.initSet(testing.allocator, 17);
3109 defer a.deinit();
3110 var b = try Managed.initSet(testing.allocator, 97);
3111 defer b.deinit();
3112 var r = try Managed.init(testing.allocator);
3113 defer r.deinit();
3114
3115 try r.gcd(&a, &b);
3116
3117 try testing.expectEqual(1, try r.toInt(u32));
3118}
3119
3120test "gcd non-one medium" {
3121 var a = try Managed.initSet(testing.allocator, 4864);
3122 defer a.deinit();
3123 var b = try Managed.initSet(testing.allocator, 3458);
3124 defer b.deinit();
3125 var r = try Managed.init(testing.allocator);
3126 defer r.deinit();
3127
3128 try r.gcd(&a, &b);
3129
3130 try testing.expectEqual(38, try r.toInt(u32));
3131}
3132
3133test "gcd non-one large" {
3134 var a = try Managed.initSet(testing.allocator, 0xffffffffffffffff);
3135 defer a.deinit();
3136 var b = try Managed.initSet(testing.allocator, 0xffffffffffffffff7777);
3137 defer b.deinit();
3138 var r = try Managed.init(testing.allocator);
3139 defer r.deinit();
3140
3141 try r.gcd(&a, &b);
3142
3143 try testing.expectEqual(4369, try r.toInt(u32));
3144}
3145
3146test "gcd large multi-limb result" {
3147 var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);
3148 defer a.deinit();
3149 var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);
3150 defer b.deinit();
3151 var r = try Managed.init(testing.allocator);
3152 defer r.deinit();
3153
3154 try r.gcd(&a, &b);
3155
3156 const answer = (try r.toInt(u256));
3157 try testing.expectEqual(0xf000000ff00000fff0000ffff000fffff00ffffff1, answer);
3158}
3159
3160test "gcd one large" {
3161 var a = try Managed.initSet(testing.allocator, 1897056385327307);
3162 defer a.deinit();
3163 var b = try Managed.initSet(testing.allocator, 2251799813685248);
3164 defer b.deinit();
3165 var r = try Managed.init(testing.allocator);
3166 defer r.deinit();
3167
3168 try r.gcd(&a, &b);
3169
3170 try testing.expectEqual(1, try r.toInt(u64));
3171}
3172
3173test "mutable to managed" {
3174 const allocator = testing.allocator;
3175 const limbs_buf = try allocator.alloc(Limb, 8);
3176 defer allocator.free(limbs_buf);
3177
3178 var a = Mutable.init(limbs_buf, 0xdeadbeef);
3179 var a_managed = a.toManaged(allocator);
3180
3181 try testing.expect(a.toConst().eql(a_managed.toConst()));
3182}
3183
3184test "const to managed" {
3185 var a = try Managed.initSet(testing.allocator, 123423453456);
3186 defer a.deinit();
3187
3188 var b = try a.toConst().toManaged(testing.allocator);
3189 defer b.deinit();
3190
3191 try testing.expect(a.toConst().eql(b.toConst()));
3192}
3193
3194test "pow" {
3195 {
3196 var a = try Managed.initSet(testing.allocator, -3);
3197 defer a.deinit();
3198
3199 try a.pow(&a, 3);
3200 try testing.expectEqual(@as(i32, -27), try a.toInt(i32));
3201
3202 try a.pow(&a, 4);
3203 try testing.expectEqual(@as(i32, 531441), try a.toInt(i32));
3204 }
3205 {
3206 var a = try Managed.initSet(testing.allocator, 10);
3207 defer a.deinit();
3208
3209 var y = try Managed.init(testing.allocator);
3210 defer y.deinit();
3211
3212 // y and a are not aliased
3213 try y.pow(&a, 123);
3214 // y and a are aliased
3215 try a.pow(&a, 123);
3216
3217 try testing.expect(a.eql(y));
3218
3219 const ys = try y.toString(testing.allocator, 16, .lower);
3220 defer testing.allocator.free(ys);
3221 try testing.expectEqualSlices(
3222 u8,
3223 "183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++
3224 "4933f60e8000000000000000000000000000000",
3225 ys,
3226 );
3227 }
3228 // Special cases
3229 {
3230 var a = try Managed.initSet(testing.allocator, 0);
3231 defer a.deinit();
3232
3233 try a.pow(&a, 100);
3234 try testing.expectEqual(@as(i32, 0), try a.toInt(i32));
3235
3236 try a.set(1);
3237 try a.pow(&a, 0);
3238 try testing.expectEqual(@as(i32, 1), try a.toInt(i32));
3239 try a.pow(&a, 100);
3240 try testing.expectEqual(@as(i32, 1), try a.toInt(i32));
3241 try a.set(-1);
3242 try a.pow(&a, 15);
3243 try testing.expectEqual(@as(i32, -1), try a.toInt(i32));
3244 try a.pow(&a, 16);
3245 try testing.expectEqual(@as(i32, 1), try a.toInt(i32));
3246 }
3247}
3248
3249test "sqrt" {
3250 var r = try Managed.init(testing.allocator);
3251 defer r.deinit();
3252 var a = try Managed.init(testing.allocator);
3253 defer a.deinit();
3254
3255 // not aliased
3256 try r.set(0);
3257 try a.set(25);
3258 try r.sqrt(&a);
3259 try testing.expectEqual(@as(i32, 5), try r.toInt(i32));
3260
3261 // aliased
3262 try a.set(25);
3263 try a.sqrt(&a);
3264 try testing.expectEqual(@as(i32, 5), try a.toInt(i32));
3265
3266 // bottom
3267 try r.set(0);
3268 try a.set(24);
3269 try r.sqrt(&a);
3270 try testing.expectEqual(@as(i32, 4), try r.toInt(i32));
3271
3272 // large number
3273 try r.set(0);
3274 try a.set(0x1_0000_0000_0000);
3275 try r.sqrt(&a);
3276 try testing.expectEqual(@as(i32, 0x100_0000), try r.toInt(i32));
3277}
3278
3279test "regression test for 1 limb overflow with alias" {
3280 // Note these happen to be two consecutive Fibonacci sequence numbers, the
3281 // first two whose sum exceeds 2**64.
3282 var a = try Managed.initSet(testing.allocator, 7540113804746346429);
3283 defer a.deinit();
3284 var b = try Managed.initSet(testing.allocator, 12200160415121876738);
3285 defer b.deinit();
3286
3287 try a.ensureAddCapacity(&a, &b);
3288 try a.add(&a, &b);
3289
3290 try testing.expectEqual(.eq, a.toConst().orderAgainstScalar(19740274219868223167));
3291}
3292
3293test "regression test for realloc with alias" {
3294 // Note these happen to be two consecutive Fibonacci sequence numbers, the
3295 // second of which is the first such number to exceed 2**192.
3296 var a = try Managed.initSet(testing.allocator, 5611500259351924431073312796924978741056961814867751431689);
3297 defer a.deinit();
3298 var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146);
3299 defer b.deinit();
3300
3301 try a.ensureAddCapacity(&a, &b);
3302 try a.add(&a, &b);
3303
3304 try testing.expectEqual(.eq, a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835));
3305}
3306
3307test "big int popcount" {
3308 var a = try Managed.init(testing.allocator);
3309 defer a.deinit();
3310
3311 try a.set(0);
3312 try popCountTest(&a, 0, 0);
3313 try popCountTest(&a, 567, 0);
3314
3315 try a.set(1);
3316 try popCountTest(&a, 1, 1);
3317 try popCountTest(&a, 13, 1);
3318 try popCountTest(&a, 432, 1);
3319
3320 try a.set(255);
3321 try popCountTest(&a, 8, 8);
3322 try a.set(-128);
3323 try popCountTest(&a, 8, 1);
3324
3325 try a.set(-2);
3326 try popCountTest(&a, 16, 15);
3327 try popCountTest(&a, 15, 14);
3328
3329 try a.set(-2047);
3330 try popCountTest(&a, 12, 2);
3331 try popCountTest(&a, 24, 14);
3332
3333 try a.set(maxInt(u5000));
3334 try popCountTest(&a, 5000, 5000);
3335 try a.set(minInt(i5000));
3336 try popCountTest(&a, 5000, 1);
3337
3338 // Check -1 at various bit counts that cross Limb size multiples.
3339 const limb_bits = @bitSizeOf(Limb);
3340 try a.set(-1);
3341 try popCountTest(&a, 1, 1); // i1
3342 try popCountTest(&a, 2, 2);
3343 try popCountTest(&a, 16, 16);
3344 try popCountTest(&a, 543, 543);
3345 try popCountTest(&a, 544, 544);
3346 try popCountTest(&a, limb_bits - 1, limb_bits - 1);
3347 try popCountTest(&a, limb_bits, limb_bits);
3348 try popCountTest(&a, limb_bits + 1, limb_bits + 1);
3349 try popCountTest(&a, limb_bits * 2 - 1, limb_bits * 2 - 1);
3350 try popCountTest(&a, limb_bits * 2, limb_bits * 2);
3351 try popCountTest(&a, limb_bits * 2 + 1, limb_bits * 2 + 1);
3352
3353 // Check very large numbers.
3354 try a.setString(16, "ff00000100000100" ++ &@as([16 * 62]u8, @splat('0')));
3355 try popCountTest(&a, 4032, 10);
3356 try popCountTest(&a, 6000, 10);
3357 a.negate();
3358 try popCountTest(&a, 4033, 48);
3359 try popCountTest(&a, 4133, 148);
3360
3361 // Check when most significant limb is full of 1s.
3362 const limb_size = @bitSizeOf(Limb);
3363 try a.set(maxInt(Limb));
3364 try popCountTest(&a, limb_size, limb_size);
3365 try popCountTest(&a, limb_size + 1, limb_size);
3366 try popCountTest(&a, limb_size * 10 + 2, limb_size);
3367 a.negate();
3368 try popCountTest(&a, limb_size * 2 - 2, limb_size - 1);
3369 try popCountTest(&a, limb_size * 2 - 1, limb_size);
3370 try popCountTest(&a, limb_size * 2, limb_size + 1);
3371 try popCountTest(&a, limb_size * 2 + 1, limb_size + 2);
3372 try popCountTest(&a, limb_size * 2 + 2, limb_size + 3);
3373 try popCountTest(&a, limb_size * 2 + 3, limb_size + 4);
3374 try popCountTest(&a, limb_size * 2 + 4, limb_size + 5);
3375 try popCountTest(&a, limb_size * 4 + 2, limb_size * 3 + 3);
3376}
3377
3378fn popCountTest(val: *const Managed, bit_count: usize, expected: usize) !void {
3379 var b = try Managed.init(testing.allocator);
3380 defer b.deinit();
3381 try b.popCount(val, bit_count);
3382
3383 try testing.expectEqual(std.math.Order.eq, b.toConst().orderAgainstScalar(expected));
3384 try testing.expectEqual(expected, val.toConst().popCount(bit_count));
3385}
3386
3387test "big int conversion read/write twos complement" {
3388 var a = try Managed.initSet(testing.allocator, (1 << 493) - 1);
3389 defer a.deinit();
3390 var b = try Managed.initSet(testing.allocator, (1 << 493) - 1);
3391 defer b.deinit();
3392 var m = b.toMutable();
3393
3394 var buffer1 = try testing.allocator.alloc(u8, 64);
3395 defer testing.allocator.free(buffer1);
3396
3397 const endians = [_]std.lang.Endian{ .little, .big };
3398 const abi_size = 64;
3399
3400 for (endians) |endian| {
3401 // Writing to buffer and back should not change anything
3402 a.toConst().writeTwosComplement(buffer1[0..abi_size], endian);
3403 m.readTwosComplement(buffer1[0..abi_size], 493, endian, .unsigned);
3404 try testing.expectEqual(.eq, m.toConst().order(a.toConst()));
3405
3406 // Equivalent to @bitCast(i493, @as(u493, intMax(u493))
3407 a.toConst().writeTwosComplement(buffer1[0..abi_size], endian);
3408 m.readTwosComplement(buffer1[0..abi_size], 493, endian, .signed);
3409 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(-1));
3410 }
3411}
3412
3413test "big int conversion read twos complement with padding" {
3414 var a = try Managed.initSet(testing.allocator, 0x01_02030405_06070809_0a0b0c0d);
3415 defer a.deinit();
3416
3417 var buffer1 = try testing.allocator.alloc(u8, 16);
3418 defer testing.allocator.free(buffer1);
3419 @memset(buffer1, 0xaa);
3420
3421 // writeTwosComplement:
3422 // (1) should not write beyond buffer[0..abi_size]
3423 // (2) should correctly order bytes based on the provided endianness
3424 // (3) should sign-extend any bits from bit_count to 8 * abi_size
3425
3426 var bit_count: usize = 12 * 8 + 1;
3427 a.toConst().writeTwosComplement(buffer1[0..13], .little);
3428 try testing.expectEqualSlices(u8, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xaa, 0xaa, 0xaa }, buffer1);
3429 a.toConst().writeTwosComplement(buffer1[0..13], .big);
3430 try testing.expectEqualSlices(u8, &[_]u8{ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xaa, 0xaa, 0xaa }, buffer1);
3431 a.toConst().writeTwosComplement(buffer1[0..16], .little);
3432 try testing.expectEqualSlices(u8, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0 }, buffer1);
3433 a.toConst().writeTwosComplement(buffer1[0..16], .big);
3434 try testing.expectEqualSlices(u8, &[_]u8{ 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd }, buffer1);
3435
3436 @memset(buffer1, 0xaa);
3437 try a.set(-0x01_02030405_06070809_0a0b0c0d);
3438 bit_count = 12 * 8 + 2;
3439
3440 a.toConst().writeTwosComplement(buffer1[0..13], .little);
3441 try testing.expectEqualSlices(u8, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xaa, 0xaa, 0xaa }, buffer1);
3442 a.toConst().writeTwosComplement(buffer1[0..13], .big);
3443 try testing.expectEqualSlices(u8, &[_]u8{ 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3, 0xaa, 0xaa, 0xaa }, buffer1);
3444 a.toConst().writeTwosComplement(buffer1[0..16], .little);
3445 try testing.expectEqualSlices(u8, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff }, buffer1);
3446 a.toConst().writeTwosComplement(buffer1[0..16], .big);
3447 try testing.expectEqualSlices(u8, &[_]u8{ 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 }, buffer1);
3448}
3449
3450test "big int write twos complement +/- zero" {
3451 var a = try Managed.initSet(testing.allocator, 0x0);
3452 defer a.deinit();
3453 var m = a.toMutable();
3454
3455 var buffer1 = try testing.allocator.alloc(u8, 16);
3456 defer testing.allocator.free(buffer1);
3457 @memset(buffer1, 0xaa);
3458
3459 // Test zero
3460
3461 m.toConst().writeTwosComplement(buffer1[0..13], .little);
3462 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xAA, 0xAA }, buffer1);
3463 m.toConst().writeTwosComplement(buffer1[0..13], .big);
3464 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xAA, 0xAA }, buffer1);
3465 m.toConst().writeTwosComplement(buffer1[0..16], .little);
3466 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, buffer1);
3467 m.toConst().writeTwosComplement(buffer1[0..16], .big);
3468 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, buffer1);
3469
3470 @memset(buffer1, 0xaa);
3471 m.positive = false;
3472
3473 // Test negative zero
3474
3475 m.toConst().writeTwosComplement(buffer1[0..13], .little);
3476 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xAA, 0xAA }, buffer1);
3477 m.toConst().writeTwosComplement(buffer1[0..13], .big);
3478 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xAA, 0xAA }, buffer1);
3479 m.toConst().writeTwosComplement(buffer1[0..16], .little);
3480 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, buffer1);
3481 m.toConst().writeTwosComplement(buffer1[0..16], .big);
3482 try testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, buffer1);
3483}
3484
3485test "big int conversion write twos complement with padding" {
3486 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
3487 defer a.deinit();
3488
3489 var m = a.toMutable();
3490
3491 // readTwosComplement:
3492 // (1) should not read beyond buffer[0..abi_size]
3493 // (2) should correctly interpret bytes based on the provided endianness
3494 // (3) should ignore any bits from bit_count to 8 * abi_size
3495
3496 var bit_count: usize = 12 * 8 + 1;
3497 var buffer: []const u8 = undefined;
3498
3499 // Test 0x01_02030405_06070809_0a0b0c0d
3500
3501 buffer = &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0xb };
3502 m.readTwosComplement(buffer[0..13], bit_count, .little, .unsigned);
3503 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x01_02030405_06070809_0a0b0c0d));
3504
3505 buffer = &[_]u8{ 0xb, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd };
3506 m.readTwosComplement(buffer[0..13], bit_count, .big, .unsigned);
3507 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x01_02030405_06070809_0a0b0c0d));
3508
3509 buffer = &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0xab, 0xaa, 0xaa, 0xaa };
3510 m.readTwosComplement(buffer[0..16], bit_count, .little, .unsigned);
3511 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x01_02030405_06070809_0a0b0c0d));
3512
3513 buffer = &[_]u8{ 0xaa, 0xaa, 0xaa, 0xab, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd };
3514 m.readTwosComplement(buffer[0..16], bit_count, .big, .unsigned);
3515 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x01_02030405_06070809_0a0b0c0d));
3516
3517 bit_count = @sizeOf(Limb) * 8;
3518
3519 // Test 0x0a0a0a0a_02030405_06070809_0a0b0c0d
3520
3521 buffer = &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0xaa };
3522 m.readTwosComplement(buffer[0..13], bit_count, .little, .unsigned);
3523 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(@as(Limb, @truncate(0xaa_02030405_06070809_0a0b0c0d))));
3524
3525 buffer = &[_]u8{ 0xaa, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd };
3526 m.readTwosComplement(buffer[0..13], bit_count, .big, .unsigned);
3527 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(@as(Limb, @truncate(0xaa_02030405_06070809_0a0b0c0d))));
3528
3529 buffer = &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0xaa, 0xaa, 0xaa, 0xaa };
3530 m.readTwosComplement(buffer[0..16], bit_count, .little, .unsigned);
3531 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(@as(Limb, @truncate(0xaaaaaaaa_02030405_06070809_0a0b0c0d))));
3532
3533 buffer = &[_]u8{ 0xaa, 0xaa, 0xaa, 0xaa, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd };
3534 m.readTwosComplement(buffer[0..16], bit_count, .big, .unsigned);
3535 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(@as(Limb, @truncate(0xaaaaaaaa_02030405_06070809_0a0b0c0d))));
3536
3537 bit_count = 12 * 8 + 2;
3538
3539 // Test -0x01_02030405_06070809_0a0b0c0d
3540
3541 buffer = &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x02 };
3542 m.readTwosComplement(buffer[0..13], bit_count, .little, .signed);
3543 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d));
3544
3545 buffer = &[_]u8{ 0x02, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 };
3546 m.readTwosComplement(buffer[0..13], bit_count, .big, .signed);
3547 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d));
3548
3549 buffer = &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x02, 0xaa, 0xaa, 0xaa };
3550 m.readTwosComplement(buffer[0..16], bit_count, .little, .signed);
3551 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d));
3552
3553 buffer = &[_]u8{ 0xaa, 0xaa, 0xaa, 0x02, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 };
3554 m.readTwosComplement(buffer[0..16], bit_count, .big, .signed);
3555 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d));
3556
3557 // Test 0
3558
3559 buffer = &@as([16]u8, @splat(0));
3560 m.readTwosComplement(buffer[0..13], bit_count, .little, .unsigned);
3561 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3562 m.readTwosComplement(buffer[0..13], bit_count, .big, .unsigned);
3563 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3564 m.readTwosComplement(buffer[0..16], bit_count, .little, .unsigned);
3565 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3566 m.readTwosComplement(buffer[0..16], bit_count, .big, .unsigned);
3567 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3568
3569 bit_count = 0;
3570 buffer = &@as([16]u8, @splat(0xaa));
3571 m.readTwosComplement(buffer[0..13], bit_count, .little, .unsigned);
3572 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3573 m.readTwosComplement(buffer[0..13], bit_count, .big, .unsigned);
3574 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3575 m.readTwosComplement(buffer[0..16], bit_count, .little, .unsigned);
3576 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3577 m.readTwosComplement(buffer[0..16], bit_count, .big, .unsigned);
3578 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3579}
3580
3581test "big int conversion write twos complement zero" {
3582 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
3583 defer a.deinit();
3584
3585 var m = a.toMutable();
3586
3587 // readTwosComplement:
3588 // (1) should not read beyond buffer[0..abi_size]
3589 // (2) should correctly interpret bytes based on the provided endianness
3590 // (3) should ignore any bits from bit_count to 8 * abi_size
3591
3592 const bit_count: usize = 12 * 8 + 1;
3593 var buffer: []const u8 = undefined;
3594
3595 buffer = &@as([13]u8, @splat(0));
3596 m.readTwosComplement(buffer[0..13], bit_count, .little, .unsigned);
3597 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3598 m.readTwosComplement(buffer[0..13], bit_count, .big, .unsigned);
3599 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3600
3601 buffer = &@as([16]u8, @splat(0));
3602 m.readTwosComplement(buffer[0..16], bit_count, .little, .unsigned);
3603 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3604 m.readTwosComplement(buffer[0..16], bit_count, .big, .unsigned);
3605 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(0x0));
3606}
3607
3608fn bitReverseTest(comptime T: type, comptime input: comptime_int, comptime expected_output: comptime_int) !void {
3609 const bit_count = @typeInfo(T).int.bits;
3610 const signedness = @typeInfo(T).int.signedness;
3611
3612 var a = try Managed.initSet(testing.allocator, input);
3613 defer a.deinit();
3614
3615 try a.ensureCapacity(calcTwosCompLimbCount(bit_count));
3616 var m = a.toMutable();
3617 m.bitReverse(a.toConst(), signedness, bit_count);
3618 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(expected_output));
3619}
3620
3621test "big int bit reverse" {
3622 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
3623 defer a.deinit();
3624
3625 try bitReverseTest(u0, 0, 0);
3626 try bitReverseTest(u5, 0x12, 0x09);
3627 try bitReverseTest(u8, 0x12, 0x48);
3628 try bitReverseTest(u16, 0x1234, 0x2c48);
3629 try bitReverseTest(u24, 0x123456, 0x6a2c48);
3630 try bitReverseTest(u32, 0x12345678, 0x1e6a2c48);
3631 try bitReverseTest(u40, 0x123456789a, 0x591e6a2c48);
3632 try bitReverseTest(u48, 0x123456789abc, 0x3d591e6a2c48);
3633 try bitReverseTest(u56, 0x123456789abcde, 0x7b3d591e6a2c48);
3634 try bitReverseTest(u64, 0x123456789abcdef1, 0x8f7b3d591e6a2c48);
3635 try bitReverseTest(u95, 0x123456789abcdef111213141, 0x4146424447bd9eac8f351624);
3636 try bitReverseTest(u96, 0x123456789abcdef111213141, 0x828c84888f7b3d591e6a2c48);
3637 try bitReverseTest(u128, 0x123456789abcdef11121314151617181, 0x818e868a828c84888f7b3d591e6a2c48);
3638
3639 try bitReverseTest(i8, @as(i8, @bitCast(@as(u8, 0x92))), @as(i8, @bitCast(@as(u8, 0x49))));
3640 try bitReverseTest(i16, @as(i16, @bitCast(@as(u16, 0x1234))), @as(i16, @bitCast(@as(u16, 0x2c48))));
3641 try bitReverseTest(i24, @as(i24, @bitCast(@as(u24, 0x123456))), @as(i24, @bitCast(@as(u24, 0x6a2c48))));
3642 try bitReverseTest(i24, @as(i24, @bitCast(@as(u24, 0x12345f))), @as(i24, @bitCast(@as(u24, 0xfa2c48))));
3643 try bitReverseTest(i24, @as(i24, @bitCast(@as(u24, 0xf23456))), @as(i24, @bitCast(@as(u24, 0x6a2c4f))));
3644 try bitReverseTest(i32, @as(i32, @bitCast(@as(u32, 0x12345678))), @as(i32, @bitCast(@as(u32, 0x1e6a2c48))));
3645 try bitReverseTest(i32, @as(i32, @bitCast(@as(u32, 0xf2345678))), @as(i32, @bitCast(@as(u32, 0x1e6a2c4f))));
3646 try bitReverseTest(i32, @as(i32, @bitCast(@as(u32, 0x1234567f))), @as(i32, @bitCast(@as(u32, 0xfe6a2c48))));
3647 try bitReverseTest(i40, @as(i40, @bitCast(@as(u40, 0x123456789a))), @as(i40, @bitCast(@as(u40, 0x591e6a2c48))));
3648 try bitReverseTest(i48, @as(i48, @bitCast(@as(u48, 0x123456789abc))), @as(i48, @bitCast(@as(u48, 0x3d591e6a2c48))));
3649 try bitReverseTest(i56, @as(i56, @bitCast(@as(u56, 0x123456789abcde))), @as(i56, @bitCast(@as(u56, 0x7b3d591e6a2c48))));
3650 try bitReverseTest(i64, @as(i64, @bitCast(@as(u64, 0x123456789abcdef1))), @as(i64, @bitCast(@as(u64, 0x8f7b3d591e6a2c48))));
3651 try bitReverseTest(i96, @as(i96, @bitCast(@as(u96, 0x123456789abcdef111213141))), @as(i96, @bitCast(@as(u96, 0x828c84888f7b3d591e6a2c48))));
3652 try bitReverseTest(i128, @as(i128, @bitCast(@as(u128, 0x123456789abcdef11121314151617181))), @as(i128, @bitCast(@as(u128, 0x818e868a828c84888f7b3d591e6a2c48))));
3653}
3654
3655fn byteSwapTest(comptime T: type, comptime input: comptime_int, comptime expected_output: comptime_int) !void {
3656 const byte_count = @typeInfo(T).int.bits / 8;
3657 const signedness = @typeInfo(T).int.signedness;
3658
3659 var a = try Managed.initSet(testing.allocator, input);
3660 defer a.deinit();
3661
3662 try a.ensureCapacity(calcTwosCompLimbCount(8 * byte_count));
3663 var m = a.toMutable();
3664 m.byteSwap(a.toConst(), signedness, byte_count);
3665 try testing.expectEqual(.eq, m.toConst().orderAgainstScalar(expected_output));
3666}
3667
3668test "big int byte swap" {
3669 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
3670 defer a.deinit();
3671
3672 @setEvalBranchQuota(10_000);
3673
3674 try byteSwapTest(u0, 0, 0);
3675 try byteSwapTest(u8, 0x12, 0x12);
3676 try byteSwapTest(u16, 0x1234, 0x3412);
3677 try byteSwapTest(u24, 0x123456, 0x563412);
3678 try byteSwapTest(u32, 0x12345678, 0x78563412);
3679 try byteSwapTest(u40, 0x123456789a, 0x9a78563412);
3680 try byteSwapTest(u48, 0x123456789abc, 0xbc9a78563412);
3681 try byteSwapTest(u56, 0x123456789abcde, 0xdebc9a78563412);
3682 try byteSwapTest(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
3683 try byteSwapTest(u88, 0x123456789abcdef1112131, 0x312111f1debc9a78563412);
3684 try byteSwapTest(u96, 0x123456789abcdef111213141, 0x41312111f1debc9a78563412);
3685 try byteSwapTest(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
3686
3687 try byteSwapTest(i8, -50, -50);
3688 try byteSwapTest(i16, @as(i16, @bitCast(@as(u16, 0x1234))), @as(i16, @bitCast(@as(u16, 0x3412))));
3689 try byteSwapTest(i24, @as(i24, @bitCast(@as(u24, 0x123456))), @as(i24, @bitCast(@as(u24, 0x563412))));
3690 try byteSwapTest(i32, @as(i32, @bitCast(@as(u32, 0x12345678))), @as(i32, @bitCast(@as(u32, 0x78563412))));
3691 try byteSwapTest(i40, @as(i40, @bitCast(@as(u40, 0x123456789a))), @as(i40, @bitCast(@as(u40, 0x9a78563412))));
3692 try byteSwapTest(i48, @as(i48, @bitCast(@as(u48, 0x123456789abc))), @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));
3693 try byteSwapTest(i56, @as(i56, @bitCast(@as(u56, 0x123456789abcde))), @as(i56, @bitCast(@as(u56, 0xdebc9a78563412))));
3694 try byteSwapTest(i64, @as(i64, @bitCast(@as(u64, 0x123456789abcdef1))), @as(i64, @bitCast(@as(u64, 0xf1debc9a78563412))));
3695 try byteSwapTest(i88, @as(i88, @bitCast(@as(u88, 0x123456789abcdef1112131))), @as(i88, @bitCast(@as(u88, 0x312111f1debc9a78563412))));
3696 try byteSwapTest(i96, @as(i96, @bitCast(@as(u96, 0x123456789abcdef111213141))), @as(i96, @bitCast(@as(u96, 0x41312111f1debc9a78563412))));
3697 try byteSwapTest(i128, @as(i128, @bitCast(@as(u128, 0x123456789abcdef11121314151617181))), @as(i128, @bitCast(@as(u128, 0x8171615141312111f1debc9a78563412))));
3698
3699 try byteSwapTest(u512, 0x80, 1 << 511);
3700 try byteSwapTest(i512, 0x80, minInt(i512));
3701 try byteSwapTest(i512, 0x40, 1 << 510);
3702 try byteSwapTest(i512, -0x100, (1 << 504) - 1);
3703 try byteSwapTest(i400, -0x100, (1 << 392) - 1);
3704 try byteSwapTest(i400, -0x2, -(1 << 392) - 1);
3705 try byteSwapTest(i24, @as(i24, @bitCast(@as(u24, 0xf23456))), 0x5634f2);
3706 try byteSwapTest(i24, 0x1234f6, @as(i24, @bitCast(@as(u24, 0xf63412))));
3707 try byteSwapTest(i32, @as(i32, @bitCast(@as(u32, 0xf2345678))), 0x785634f2);
3708 try byteSwapTest(i32, 0x123456f8, @as(i32, @bitCast(@as(u32, 0xf8563412))));
3709 try byteSwapTest(i48, 0x123456789abc, @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));
3710}
3711
3712test "mul multi-multi alias r with a and b" {
3713 var a = try Managed.initSet(testing.allocator, 2 * maxInt(Limb));
3714 defer a.deinit();
3715
3716 try a.ensureMulCapacity(&a, &a);
3717 try a.mul(&a, &a);
3718
3719 var want = try Managed.initSet(testing.allocator, 4 * maxInt(Limb) * maxInt(Limb));
3720 defer want.deinit();
3721
3722 try testing.expect(a.eql(want));
3723
3724 if (@typeInfo(Limb).int.bits == 64) {
3725 try testing.expectEqual(@as(usize, 5), a.limbs.len);
3726 }
3727}
3728
3729test "sqr multi alias r with a" {
3730 var a = try Managed.initSet(testing.allocator, 2 * maxInt(Limb));
3731 defer a.deinit();
3732
3733 try a.sqr(&a);
3734
3735 var want = try Managed.initSet(testing.allocator, 4 * maxInt(Limb) * maxInt(Limb));
3736 defer want.deinit();
3737
3738 try testing.expect(a.eql(want));
3739
3740 if (@typeInfo(Limb).int.bits == 64) {
3741 try testing.expectEqual(@as(usize, 5), a.limbs.len);
3742 }
3743}
3744
3745test "eql zeroes #17296" {
3746 var zero = try Managed.init(testing.allocator);
3747 defer zero.deinit();
3748 try zero.setString(10, "0");
3749 try std.testing.expect(zero.eql(zero));
3750
3751 {
3752 var sum = try Managed.init(testing.allocator);
3753 defer sum.deinit();
3754 try sum.add(&zero, &zero);
3755 try std.testing.expect(zero.eql(sum));
3756 }
3757
3758 {
3759 var diff = try Managed.init(testing.allocator);
3760 defer diff.deinit();
3761 try diff.sub(&zero, &zero);
3762 try std.testing.expect(zero.eql(diff));
3763 }
3764}
3765
3766test "Const.order 0 == -0" {
3767 const a = std.math.big.int.Const{
3768 .limbs = &.{0},
3769 .positive = true,
3770 };
3771 const b = std.math.big.int.Const{
3772 .limbs = &.{0},
3773 .positive = false,
3774 };
3775 try std.testing.expectEqual(std.math.Order.eq, a.order(b));
3776}
3777
3778test "Managed sqrt(0) = 0" {
3779 const allocator = testing.allocator;
3780 var a = try Managed.initSet(allocator, 1);
3781 defer a.deinit();
3782
3783 var res = try Managed.initSet(allocator, 1);
3784 defer res.deinit();
3785
3786 try a.setString(10, "0");
3787
3788 try res.sqrt(&a);
3789 try testing.expectEqual(@as(i32, 0), try res.toInt(i32));
3790}
3791
3792test "Managed sqrt(-1) = error" {
3793 const allocator = testing.allocator;
3794 var a = try Managed.initSet(allocator, 1);
3795 defer a.deinit();
3796
3797 var res = try Managed.initSet(allocator, 1);
3798 defer res.deinit();
3799
3800 try a.setString(10, "-1");
3801
3802 try testing.expectError(error.SqrtOfNegativeNumber, res.sqrt(&a));
3803}
3804
3805test "Managed sqrt(n) succeed with res.bitCountAbs() >= usize bits" {
3806 const allocator = testing.allocator;
3807 var a = try Managed.initSet(allocator, 1);
3808 defer a.deinit();
3809
3810 var res = try Managed.initSet(allocator, 1);
3811 defer res.deinit();
3812
3813 // a.bitCountAbs() = 127 so the first attempt has 64 bits >= usize bits
3814 try a.setString(10, "136036462105870278006290938611834481486");
3815 try res.sqrt(&a);
3816
3817 var expected = try Managed.initSet(allocator, 1);
3818 defer expected.deinit();
3819 try expected.setString(10, "11663466984815033033");
3820 try std.testing.expectEqual(std.math.Order.eq, expected.order(res));
3821}
3822
3823test "(BigInt) positive" {
3824 var a = try Managed.initSet(testing.allocator, 2);
3825 defer a.deinit();
3826
3827 var b = try Managed.init(testing.allocator);
3828 defer b.deinit();
3829
3830 var c = try Managed.initSet(testing.allocator, 1);
3831 defer c.deinit();
3832
3833 // a = pow(2, 64 * @sizeOf(usize) * 8), b = a - 1
3834 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3835 try b.sub(&a, &c);
3836
3837 try testing.expectFmt("(BigInt)", "{d}", .{a});
3838
3839 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b});
3840 defer testing.allocator.free(b_fmt);
3841 try testing.expect(!mem.eql(u8, "(BigInt)", b_fmt));
3842}
3843
3844test "(BigInt) negative" {
3845 var a = try Managed.initSet(testing.allocator, 2);
3846 defer a.deinit();
3847
3848 var b = try Managed.init(testing.allocator);
3849 defer b.deinit();
3850
3851 var c = try Managed.initSet(testing.allocator, 1);
3852 defer c.deinit();
3853
3854 // a = -pow(2, 64 * @sizeOf(usize) * 8), b = a + 1
3855 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3856 a.negate();
3857 try b.add(&a, &c);
3858
3859 const a_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{a});
3860 defer testing.allocator.free(a_fmt);
3861
3862 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b});
3863 defer testing.allocator.free(b_fmt);
3864
3865 try testing.expectEqualSlices(u8, "(BigInt)", a_fmt);
3866 try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)"));
3867}
3868
3869test "clz" {
3870 const neg_limb_max_squared: std.math.big.int.Const = .{
3871 .limbs = &.{ 1, maxInt(Limb) - 1 },
3872 .positive = false,
3873 };
3874 try testing.expectEqual(0, neg_limb_max_squared.clz(@bitSizeOf(Limb) * 2 + 1));
3875
3876 const neg_limb_max_squared_plus_one: std.math.big.int.Const = .{
3877 .limbs = &.{ 0, maxInt(Limb) - 1 },
3878 .positive = false,
3879 };
3880 try testing.expectEqual(0, neg_limb_max_squared_plus_one.clz(@bitSizeOf(Limb) * 2 + 1));
3881
3882 const neg_limb_msb_squared: std.math.big.int.Const = .{
3883 .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 },
3884 .positive = false,
3885 };
3886 try testing.expectEqual(0, neg_limb_msb_squared.clz(@bitSizeOf(Limb) * 2));
3887 try testing.expectEqual(0, neg_limb_msb_squared.clz(@bitSizeOf(Limb) * 2 + 1));
3888
3889 const neg_limb_max: std.math.big.int.Const = .{
3890 .limbs = &.{maxInt(Limb)},
3891 .positive = false,
3892 };
3893 try testing.expectEqual(0, neg_limb_max.clz(@bitSizeOf(Limb) + 1));
3894 try testing.expectEqual(0, neg_limb_max.clz(@bitSizeOf(Limb) * 2 - 1));
3895 try testing.expectEqual(0, neg_limb_max.clz(@bitSizeOf(Limb) * 2));
3896 try testing.expectEqual(0, neg_limb_max.clz(@bitSizeOf(Limb) * 2 + 1));
3897
3898 const neg_limb_msb: std.math.big.int.Const = .{
3899 .limbs = &.{1 << @bitSizeOf(Limb) - 1},
3900 .positive = false,
3901 };
3902 try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb)));
3903 try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb) + 1));
3904 try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb) * 2 - 1));
3905 try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb) * 2));
3906 try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb) * 2 + 1));
3907
3908 const neg_one: std.math.big.int.Const = .{
3909 .limbs = &.{1},
3910 .positive = false,
3911 };
3912 try testing.expectEqual(0, neg_one.clz(@bitSizeOf(Limb)));
3913 try testing.expectEqual(0, neg_one.clz(@bitSizeOf(Limb) + 1));
3914 try testing.expectEqual(0, neg_one.clz(@bitSizeOf(Limb) * 2 - 1));
3915 try testing.expectEqual(0, neg_one.clz(@bitSizeOf(Limb) * 2));
3916 try testing.expectEqual(0, neg_one.clz(@bitSizeOf(Limb) * 2 + 1));
3917
3918 const zero: std.math.big.int.Const = .{
3919 .limbs = &.{0},
3920 .positive = true,
3921 };
3922 try testing.expectEqual(@bitSizeOf(Limb), zero.clz(@bitSizeOf(Limb)));
3923 try testing.expectEqual(@bitSizeOf(Limb) + 1, zero.clz(@bitSizeOf(Limb) + 1));
3924 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 1, zero.clz(@bitSizeOf(Limb) * 2 - 1));
3925 try testing.expectEqual(@bitSizeOf(Limb) * 2, zero.clz(@bitSizeOf(Limb) * 2));
3926 try testing.expectEqual(@bitSizeOf(Limb) * 2 + 1, zero.clz(@bitSizeOf(Limb) * 2 + 1));
3927
3928 const one: std.math.big.int.Const = .{
3929 .limbs = &.{1},
3930 .positive = true,
3931 };
3932 try testing.expectEqual(@bitSizeOf(Limb) - 1, one.clz(@bitSizeOf(Limb)));
3933 try testing.expectEqual(@bitSizeOf(Limb), one.clz(@bitSizeOf(Limb) + 1));
3934 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, one.clz(@bitSizeOf(Limb) * 2 - 1));
3935 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 1, one.clz(@bitSizeOf(Limb) * 2));
3936 try testing.expectEqual(@bitSizeOf(Limb) * 2, one.clz(@bitSizeOf(Limb) * 2 + 1));
3937
3938 const limb_msb: std.math.big.int.Const = .{
3939 .limbs = &.{1 << @bitSizeOf(Limb) - 1},
3940 .positive = true,
3941 };
3942 try testing.expectEqual(0, limb_msb.clz(@bitSizeOf(Limb)));
3943 try testing.expectEqual(1, limb_msb.clz(@bitSizeOf(Limb) + 1));
3944 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.clz(@bitSizeOf(Limb) * 2 - 1));
3945 try testing.expectEqual(@bitSizeOf(Limb), limb_msb.clz(@bitSizeOf(Limb) * 2));
3946 try testing.expectEqual(@bitSizeOf(Limb) + 1, limb_msb.clz(@bitSizeOf(Limb) * 2 + 1));
3947
3948 const limb_max: std.math.big.int.Const = .{
3949 .limbs = &.{maxInt(Limb)},
3950 .positive = true,
3951 };
3952 try testing.expectEqual(0, limb_max.clz(@bitSizeOf(Limb)));
3953 try testing.expectEqual(1, limb_max.clz(@bitSizeOf(Limb) + 1));
3954 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_max.clz(@bitSizeOf(Limb) * 2 - 1));
3955 try testing.expectEqual(@bitSizeOf(Limb), limb_max.clz(@bitSizeOf(Limb) * 2));
3956 try testing.expectEqual(@bitSizeOf(Limb) + 1, limb_max.clz(@bitSizeOf(Limb) * 2 + 1));
3957
3958 const limb_msb_squared: std.math.big.int.Const = .{
3959 .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 },
3960 .positive = true,
3961 };
3962 try testing.expectEqual(0, limb_msb_squared.clz(@bitSizeOf(Limb) * 2 - 1));
3963 try testing.expectEqual(1, limb_msb_squared.clz(@bitSizeOf(Limb) * 2));
3964 try testing.expectEqual(2, limb_msb_squared.clz(@bitSizeOf(Limb) * 2 + 1));
3965
3966 const limb_max_squared_minus_one: std.math.big.int.Const = .{
3967 .limbs = &.{ 0, maxInt(Limb) - 1 },
3968 .positive = true,
3969 };
3970 try testing.expectEqual(0, limb_max_squared_minus_one.clz(@bitSizeOf(Limb) * 2));
3971 try testing.expectEqual(1, limb_max_squared_minus_one.clz(@bitSizeOf(Limb) * 2 + 1));
3972
3973 const limb_max_squared: std.math.big.int.Const = .{
3974 .limbs = &.{ 1, maxInt(Limb) - 1 },
3975 .positive = true,
3976 };
3977 try testing.expectEqual(0, limb_max_squared.clz(@bitSizeOf(Limb) * 2));
3978 try testing.expectEqual(1, limb_max_squared.clz(@bitSizeOf(Limb) * 2 + 1));
3979}
3980
3981test "ctz" {
3982 const neg_limb_max_squared: std.math.big.int.Const = .{
3983 .limbs = &.{ 1, maxInt(Limb) - 1 },
3984 .positive = false,
3985 };
3986 try testing.expectEqual(0, neg_limb_max_squared.ctz(@bitSizeOf(Limb) * 2 + 1));
3987
3988 const neg_limb_max_squared_plus_one: std.math.big.int.Const = .{
3989 .limbs = &.{ 0, maxInt(Limb) - 1 },
3990 .positive = false,
3991 };
3992 try testing.expectEqual(@bitSizeOf(Limb) + 1, neg_limb_max_squared_plus_one.ctz(@bitSizeOf(Limb) * 2 + 1));
3993
3994 const neg_limb_msb_squared: std.math.big.int.Const = .{
3995 .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 },
3996 .positive = false,
3997 };
3998 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, neg_limb_msb_squared.ctz(@bitSizeOf(Limb) * 2));
3999 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, neg_limb_msb_squared.ctz(@bitSizeOf(Limb) * 2 + 1));
4000
4001 const neg_limb_max: std.math.big.int.Const = .{
4002 .limbs = &.{maxInt(Limb)},
4003 .positive = false,
4004 };
4005 try testing.expectEqual(0, neg_limb_max.ctz(@bitSizeOf(Limb) + 1));
4006 try testing.expectEqual(0, neg_limb_max.ctz(@bitSizeOf(Limb) * 2 - 1));
4007 try testing.expectEqual(0, neg_limb_max.ctz(@bitSizeOf(Limb) * 2));
4008 try testing.expectEqual(0, neg_limb_max.ctz(@bitSizeOf(Limb) * 2 + 1));
4009
4010 const neg_limb_msb: std.math.big.int.Const = .{
4011 .limbs = &.{1 << @bitSizeOf(Limb) - 1},
4012 .positive = false,
4013 };
4014 try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb)));
4015 try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb) + 1));
4016 try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb) * 2 - 1));
4017 try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb) * 2));
4018 try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb) * 2 + 1));
4019
4020 const neg_one: std.math.big.int.Const = .{
4021 .limbs = &.{1},
4022 .positive = false,
4023 };
4024 try testing.expectEqual(0, neg_one.ctz(@bitSizeOf(Limb)));
4025 try testing.expectEqual(0, neg_one.ctz(@bitSizeOf(Limb) + 1));
4026 try testing.expectEqual(0, neg_one.ctz(@bitSizeOf(Limb) * 2 - 1));
4027 try testing.expectEqual(0, neg_one.ctz(@bitSizeOf(Limb) * 2));
4028 try testing.expectEqual(0, neg_one.ctz(@bitSizeOf(Limb) * 2 + 1));
4029
4030 const zero: std.math.big.int.Const = .{
4031 .limbs = &.{0},
4032 .positive = true,
4033 };
4034 try testing.expectEqual(@bitSizeOf(Limb), zero.ctz(@bitSizeOf(Limb)));
4035 try testing.expectEqual(@bitSizeOf(Limb) + 1, zero.ctz(@bitSizeOf(Limb) + 1));
4036 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 1, zero.ctz(@bitSizeOf(Limb) * 2 - 1));
4037 try testing.expectEqual(@bitSizeOf(Limb) * 2, zero.ctz(@bitSizeOf(Limb) * 2));
4038 try testing.expectEqual(@bitSizeOf(Limb) * 2 + 1, zero.ctz(@bitSizeOf(Limb) * 2 + 1));
4039
4040 const one: std.math.big.int.Const = .{
4041 .limbs = &.{1},
4042 .positive = true,
4043 };
4044 try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb)));
4045 try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb) + 1));
4046 try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb) * 2 - 1));
4047 try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb) * 2));
4048 try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb) * 2 + 1));
4049
4050 const limb_msb: std.math.big.int.Const = .{
4051 .limbs = &.{1 << @bitSizeOf(Limb) - 1},
4052 .positive = true,
4053 };
4054 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb)));
4055 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb) + 1));
4056 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb) * 2 - 1));
4057 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb) * 2));
4058 try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb) * 2 + 1));
4059
4060 const limb_max: std.math.big.int.Const = .{
4061 .limbs = &.{maxInt(Limb)},
4062 .positive = true,
4063 };
4064 try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb)));
4065 try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb) + 1));
4066 try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb) * 2 - 1));
4067 try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb) * 2));
4068 try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb) * 2 + 1));
4069
4070 const limb_msb_squared: std.math.big.int.Const = .{
4071 .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 },
4072 .positive = true,
4073 };
4074 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, limb_msb_squared.ctz(@bitSizeOf(Limb) * 2 - 1));
4075 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, limb_msb_squared.ctz(@bitSizeOf(Limb) * 2));
4076 try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, limb_msb_squared.ctz(@bitSizeOf(Limb) * 2 + 1));
4077
4078 const limb_max_squared_minus_one: std.math.big.int.Const = .{
4079 .limbs = &.{ 0, maxInt(Limb) - 1 },
4080 .positive = true,
4081 };
4082 try testing.expectEqual(@bitSizeOf(Limb) + 1, limb_max_squared_minus_one.ctz(@bitSizeOf(Limb) * 2));
4083 try testing.expectEqual(@bitSizeOf(Limb) + 1, limb_max_squared_minus_one.ctz(@bitSizeOf(Limb) * 2 + 1));
4084
4085 const limb_max_squared: std.math.big.int.Const = .{
4086 .limbs = &.{ 1, maxInt(Limb) - 1 },
4087 .positive = true,
4088 };
4089 try testing.expectEqual(0, limb_max_squared.ctz(@bitSizeOf(Limb) * 2));
4090 try testing.expectEqual(0, limb_max_squared.ctz(@bitSizeOf(Limb) * 2 + 1));
4091}
4092
4093test "log2" {
4094 var a = try Managed.init(testing.allocator);
4095 defer a.deinit();
4096
4097 try a.setString(2, "1");
4098 try testing.expectEqual(0, a.toConst().log2());
4099
4100 try a.setString(2, "1111011");
4101 try testing.expectEqual(6, a.toConst().log2());
4102
4103 try a.setString(2, "10100111011101010");
4104 try testing.expectEqual(16, a.toConst().log2());
4105
4106 try a.setString(16, "a22d71c87a9ce406da4f5895f9f3cc3d603192baf6c8a2b5c32649d0465bf188fe799b3618085e49d71bdaec01");
4107 try testing.expectEqual(359, a.toConst().log2());
4108}
4109
4110test "log10" {
4111 var a = try Managed.init(testing.allocator);
4112 defer a.deinit();
4113
4114 try a.setString(10, "1");
4115 try testing.expectEqual(0, a.toConst().log10Alloc(testing.allocator));
4116
4117 try a.setString(10, "1234");
4118 try testing.expectEqual(3, a.toConst().log10Alloc(testing.allocator));
4119
4120 try a.setString(10, "123456789");
4121 try testing.expectEqual(8, a.toConst().log10Alloc(testing.allocator));
4122
4123 try a.setString(10, "57594534510580048222343352832931567593656037535732288627581929757527496850784");
4124 try testing.expectEqual(76, a.toConst().log10Alloc(testing.allocator));
4125
4126 try a.setString(10, "504758845984192913149382719638135788792820830414213085834451043864912744833203879823150928260925344757009154551640690830148486352800955148298533547472300");
4127 try testing.expectEqual(152, a.toConst().log10Alloc(testing.allocator));
4128}