authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-05-05 22:40:29+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-05-05 22:40:29+12:00
logd7b029995c8ac678598de39aa106076dca232902
tree55cef35f6055caedd559cb243653b39e97be7f45
parent87c0060e813be6ee9b449058b4288d148706f8a4

Fix bigint multi-limb shift and masks


2 files changed, 21 insertions(+), 6 deletions(-)

src/bigint.cpp+4-6
......@@ -1259,12 +1259,11 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12591259 bigint_normalize(dest);
12601260 return;
12611261 }
1262 // TODO this code path is untested
1263 uint64_t first_digit = dest->data.digit;
1262
12641263 dest->digit_count = max(op1->digit_count, op2->digit_count);
12651264 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
1266 dest->data.digits[0] = first_digit;
1267 size_t i = 1;
1265
1266 size_t i = 0;
12681267 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
12691268 dest->data.digits[i] = op1_digits[i] & op2_digits[i];
12701269 }
......@@ -1412,7 +1411,6 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
14121411 return;
14131412 }
14141413
1415 // TODO this code path is untested
14161414 size_t digit_shift_count = shift_amt / 64;
14171415 size_t leftover_shift_count = shift_amt % 64;
14181416
......@@ -1427,7 +1425,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
14271425 uint64_t digit = op1_digits[op_digit_index];
14281426 size_t dest_digit_index = op_digit_index - digit_shift_count;
14291427 dest->data.digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
1430 carry = (0xffffffffffffffffULL << leftover_shift_count) & digit;
1428 carry = digit << leftover_shift_count;
14311429
14321430 if (dest_digit_index == 0) { break; }
14331431 op_digit_index -= 1;
test/cases/math.zig+17
......@@ -349,6 +349,23 @@ test "big number shifting" {
349349 }
350350}
351351
352test "big number multi-limb shift and mask" {
353 comptime {
354 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
355
356 assert(u32(a & 0xffffffff) == 0xaaaaaaab);
357 a >>= 32;
358 assert(u32(a & 0xffffffff) == 0xeeeeeeef);
359 a >>= 32;
360 assert(u32(a & 0xffffffff) == 0xa0000001);
361 a >>= 32;
362 assert(u32(a & 0xffffffff) == 0xefffffff);
363 a >>= 32;
364
365 assert(a == 0);
366 }
367}
368
352369test "xor" {
353370 test_xor();
354371 comptime test_xor();