}
}
+bool bigmul(uint32_t qhat, unsigned product[], unsigned vn[], int m,
+ int n)
+{
+ long long t, k;
+ int s, i;
+ uint32_t carry = 0;
+ // VL = n + 1
+ // sv.madded product.v, vn.v, qhat.s, carry.s
+ for (int i = 0; i <= n; i++)
+ {
+ uint32_t vn_v = i < n ? vn[i] : 0;
+ uint64_t value = (uint64_t)vn_v * (uint64_t)qhat + carry;
+ carry = (uint32_t)(value >> 32);
+ product[i] = (uint32_t)value;
+ }
+ return carry != 0;
+}
+
+bool bigadd(unsigned result[], unsigned vn[], unsigned un[], int m, int n,
+ bool ca)
+{
+ // VL = n + 1
+ // sv.subfe un_j.v, product.v, un_j.v
+ for (int i = 0; i <= n; i++)
+ {
+ uint64_t value = (uint64_t)vn[i] + (uint64_t)un[i] + ca;
+ ca = value >> 32 != 0;
+ result[i] = value;
+ }
+ return ca;
+}
+
+bool bigsub(unsigned result[], unsigned vn[], unsigned un[], int m, int n,
+ bool ca)
+{
+ // VL = n + 1
+ // sv.subfe un_j.v, product.v, un_j.v
+ for (int i = 0; i <= n; i++)
+ {
+ uint64_t value = (uint64_t)~vn[i] + (uint64_t)un[i] + ca;
+ ca = value >> 32 != 0;
+ result[i] = value;
+ }
+ return ca;
+}
+
+bool bigmulsub(unsigned long long qhat, unsigned vn[], unsigned un[], int j,
+ int m, int n)
+{
+ // Multiply and subtract.
+ uint32_t product[n + 1];
+ bigmul(qhat, product, vn, m, n);
+ bool ca = bigsub(un, product, un, m, n, true);
+ bool need_fixup = !ca;
+ return need_fixup;
+}
+
/* q[0], r[0], u[0], and v[0] contain the LEAST significant words.
(The sequence is in little-endian order).
for (j = m - n; j >= 0; j--)
{ // Main loop.
+ uint32_t *un_j = &un[j];
// Compute estimate qhat of q[j] from top 2 digits.
uint64_t dig2 = ((uint64_t)un[j + n] << 32) | un[j + n - 1];
divrem_t qr = divrem_64_by_32(dig2, vn[n - 1]);
product[i] = (uint32_t)value;
}
bool ca = true;
- uint32_t *un_j = &un[j];
// VL = n + 1
// sv.subfe un_j.v, product.v, un_j.v
for (int i = 0; i <= n; i++)
if (need_fixup)
{ // If we subtracted too
q[j] = q[j] - 1; // much, add back.
- k = 0;
- for (i = 0; i < n; i++)
- {
- t = (unsigned long long)un[i + j] + vn[i] + k;
- un[i + j] = t;
- k = t >> 32;
- }
- un[j + n] = un[j + n] + k;
+ bigadd(un_j, vn, un_j, m, n, 0);
}
} // End j.
// If the caller wants the remainder, unnormalize