MPuint MPuint::operator-(const MPuint& mpu) { MPuint out; LPuint *a1 = m_data->A, *a2 = mpu.m_data->A, *a3 = out.m_data->A; int l1 = m_data->len, l2 = mpu.m_data->len; out.m_data->len = l1; unsigned char rem = 0; for (int i = 0; i < l2; i++) { rem = _subborrow_u64(rem, a1[i], a2[i], a3 + i); } if (rem == 0) memcpy(a3 + l2, a1 + l2, (l1 - l2) * sizeof(LPuint)); else { for (int i = l2; i < l1; i++) { rem = _subborrow_u64(rem, a1[i], 0, a3 + i); } } while (a3[out.m_data->len - 1] == 0) out.m_data->len--; return out; }
static void adx_test (void) { volatile unsigned char c; unsigned long long x; volatile unsigned long long y, sum_ref; c = 0; x = y = 0xFFFFFFFFFFFFFFFFLL; sum_ref = 0xFFFFFFFFFFFFFFFELL; /* X = 0xFFFFFFFFFFFFFFFF, Y = 0xFFFFFFFFFFFFFFFF, C = 0. */ c = _addcarryx_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ c = _addcarryx_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ if (x != sum_ref) abort (); c = 0; x = y = 0xFFFFFFFFFFFFFFFFLL; sum_ref = 0xFFFFFFFFFFFFFFFELL; /* X = 0xFFFFFFFFFFFFFFFF, Y = 0xFFFFFFFFFFFFFFFF, C = 0. */ c = _addcarry_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ c = _addcarry_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ if (x != sum_ref) abort (); c = 0; x = 1LL; y = 0LL; sum_ref = 0x0LL; /* X = 0x0000000000000001, Y = 0x0000000000000000, C = 0. */ c = _subborrow_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFF, Y = 0x0000000000000000, C = 1. */ c = _subborrow_u64 (c, x, y, &x); /* X = 0x0000000000000000, Y = 0x0000000000000000, C = 1. */ if (x != sum_ref) abort (); }
uint2048& operator-=(uint2048& operand_a, const uint2048& operand_b){ uint64_t a, b; uint64_t* c; uint8_t borrow_flag = 0u; for (auto i = 0u; i < 32u; ++i){ a = operand_a.parts_[i]; b = operand_b.parts_[i]; c = &(operand_a.parts_[i]); // intrinsic function // sbb instruction // *c = a - (b + borrow) // borrow_flag is set to 1 if (a < (b + borrow)) borrow_flag = _subborrow_u64(borrow_flag, a, b, c); } return operand_a; }