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