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}