10#ifndef BOTAN_MP_CORE_OPS_H_
11#define BOTAN_MP_CORE_OPS_H_
13#include <botan/assert.h>
14#include <botan/exceptn.h>
15#include <botan/mem_ops.h>
16#include <botan/types.h>
17#include <botan/internal/ct_utils.h>
18#include <botan/internal/mp_asmi.h>
34 for(
size_t i = 0; i != size; ++i) {
37 x[i] = mask.select(
b, a);
38 y[i] = mask.select(a,
b);
43inline constexpr W
bigint_cnd_add(W cnd, W x[],
size_t x_size,
const W y[],
size_t y_size) {
50 for(
size_t i = 0; i != y_size; ++i) {
54 for(
size_t i = y_size; i != x_size; ++i) {
58 return (mask &
carry);
43inline constexpr W
bigint_cnd_add(W cnd, W x[],
size_t x_size,
const W y[],
size_t y_size) {
…}
75inline constexpr auto bigint_cnd_sub(W cnd, W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
82 for(
size_t i = 0; i != y_size; ++i) {
86 for(
size_t i = y_size; i != x_size; ++i) {
90 return (mask &
carry);
75inline constexpr auto bigint_cnd_sub(W cnd, W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
…}
98inline constexpr auto bigint_cnd_sub(W cnd, W x[],
const W y[],
size_t size) -> W {
98inline constexpr auto bigint_cnd_sub(W cnd, W x[],
const W y[],
size_t size) -> W {
…}
111 const size_t blocks = size - (size % 8);
119 for(
size_t i = 0; i != blocks; i += 8) {
121 borrow =
word8_sub3(t1, x + i, y + i, borrow);
125 for(
size_t i = blocks; i != size; ++i) {
127 const W s =
word_sub(x[i], y[i], &borrow);
144 const size_t blocks = size - (size % 8);
152 for(
size_t i = 0; i != blocks; i += 8) {
154 borrow =
word8_sub3(t1, x + i, z + i, borrow);
155 mask.select_n(x + i, t0, t1, 8);
158 for(
size_t i = blocks; i != size; ++i) {
160 t1[0] =
word_sub(x[i], z[i], &borrow);
161 x[i] = mask.select(t0[0], t1[0]);
164 return mask.select(
carry, borrow);
176 W
carry = mask.if_set_return(1);
177 for(
size_t i = 0; i != size; ++i) {
179 x[i] = mask.select(z, x[i]);
187inline constexpr auto bigint_add2_nc(W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
192 const size_t blocks = y_size - (y_size % 8);
194 for(
size_t i = 0; i != blocks; i += 8) {
198 for(
size_t i = blocks; i != y_size; ++i) {
202 for(
size_t i = y_size; i != x_size; ++i) {
187inline constexpr auto bigint_add2_nc(W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
…}
213inline constexpr auto bigint_add3_nc(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
214 if(x_size < y_size) {
220 const size_t blocks = y_size - (y_size % 8);
222 for(
size_t i = 0; i != blocks; i += 8) {
226 for(
size_t i = blocks; i != y_size; ++i) {
230 for(
size_t i = y_size; i != x_size; ++i) {
213inline constexpr auto bigint_add3_nc(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
…}
237template <WordType W,
size_t N>
238inline constexpr auto bigint_add(std::span<W, N> z, std::span<const W, N> x, std::span<const W, N> y) -> W {
239 if constexpr(N == 4) {
241 }
else if constexpr(N == 8) {
238inline constexpr auto bigint_add(std::span<W, N> z, std::span<const W, N> x, std::span<const W, N> y) -> W {
…}
256inline constexpr void bigint_add2(W x[],
size_t x_size,
const W y[],
size_t y_size) {
256inline constexpr void bigint_add2(W x[],
size_t x_size,
const W y[],
size_t y_size) {
…}
264inline constexpr void bigint_add3(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
265 z[x_size > y_size ? x_size : y_size] +=
bigint_add3_nc(z, x, x_size, y, y_size);
264inline constexpr void bigint_add3(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
…}
272inline constexpr auto bigint_sub2(W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
277 const size_t blocks = y_size - (y_size % 8);
279 for(
size_t i = 0; i != blocks; i += 8) {
283 for(
size_t i = blocks; i != y_size; ++i) {
284 x[i] =
word_sub(x[i], y[i], &borrow);
287 for(
size_t i = y_size; i != x_size; ++i) {
288 x[i] =
word_sub(x[i],
static_cast<W
>(0), &borrow);
272inline constexpr auto bigint_sub2(W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
…}
301 const size_t blocks = y_size - (y_size % 8);
303 for(
size_t i = 0; i != blocks; i += 8) {
307 for(
size_t i = blocks; i != y_size; ++i) {
308 x[i] =
word_sub(y[i], x[i], &borrow);
322inline constexpr auto bigint_sub3(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
327 const size_t blocks = y_size - (y_size % 8);
329 for(
size_t i = 0; i != blocks; i += 8) {
330 borrow =
word8_sub3(z + i, x + i, y + i, borrow);
333 for(
size_t i = blocks; i != y_size; ++i) {
334 z[i] =
word_sub(x[i], y[i], &borrow);
337 for(
size_t i = y_size; i != x_size; ++i) {
338 z[i] =
word_sub(x[i],
static_cast<W
>(0), &borrow);
322inline constexpr auto bigint_sub3(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) -> W {
…}
358 const size_t blocks = N - (N % 8);
360 for(
size_t i = 0; i != blocks; i += 8) {
361 borrow =
word8_sub3(z + i, x + i, p + i, borrow);
364 for(
size_t i = blocks; i != N; ++i) {
365 z[i] =
word_sub(x[i], p[i], &borrow);
368 borrow = (x0 - borrow) > x0;
383template <
size_t N, WordType W>
387 if constexpr(N == 4) {
389 }
else if constexpr(N == 8) {
392 const constexpr size_t blocks = N - (N % 8);
393 for(
size_t i = 0; i != blocks; i += 8) {
394 borrow =
word8_sub3(z + i, x + i, y + i, borrow);
397 for(
size_t i = blocks; i != N; ++i) {
398 z[i] =
word_sub(x[i], y[i], &borrow);
402 borrow = (x0 - borrow) > x0;
429 const size_t blocks = N - (N % 8);
431 for(
size_t i = 0; i != blocks; i += 8) {
432 borrow0 =
word8_sub3(ws0 + i, x + i, y + i, borrow0);
433 borrow1 =
word8_sub3(ws1 + i, y + i, x + i, borrow1);
436 for(
size_t i = blocks; i != N; ++i) {
437 ws0[i] =
word_sub(x[i], y[i], &borrow0);
438 ws1[i] =
word_sub(y[i], x[i], &borrow1);
448inline constexpr void bigint_shl1(W x[],
size_t x_size,
size_t x_words,
size_t shift) {
452 copy_mem(x + word_shift, x, x_words);
459 for(
size_t i = word_shift; i != x_size; ++i) {
461 x[i] = (w << bit_shift) |
carry;
448inline constexpr void bigint_shl1(W x[],
size_t x_size,
size_t x_words,
size_t shift) {
…}
467inline constexpr void bigint_shr1(W x[],
size_t x_size,
size_t shift) {
471 const size_t top = x_size >= word_shift ? (x_size - word_shift) : 0;
476 clear_mem(x + top, std::min(word_shift, x_size));
483 for(
size_t i = 0; i != top; ++i) {
484 const W w = x[top - i - 1];
485 x[top - i - 1] = (w >> bit_shift) |
carry;
467inline constexpr void bigint_shr1(W x[],
size_t x_size,
size_t shift) {
…}
491inline constexpr void bigint_shl2(W y[],
const W x[],
size_t x_size,
size_t shift) {
495 copy_mem(y + word_shift, x, x_size);
501 for(
size_t i = word_shift; i != x_size + word_shift + 1; ++i) {
503 y[i] = (w << bit_shift) |
carry;
491inline constexpr void bigint_shl2(W y[],
const W x[],
size_t x_size,
size_t shift) {
…}
509inline constexpr void bigint_shr2(W y[],
const W x[],
size_t x_size,
size_t shift) {
512 const size_t new_size = x_size < word_shift ? 0 : (x_size - word_shift);
515 copy_mem(y, x + word_shift, new_size);
522 for(
size_t i = new_size; i > 0; --i) {
524 y[i - 1] = (w >> bit_shift) |
carry;
509inline constexpr void bigint_shr2(W y[],
const W x[],
size_t x_size,
size_t shift) {
…}
533[[nodiscard]]
inline constexpr auto bigint_linmul2(W x[],
size_t x_size, W y) -> W {
534 const size_t blocks = x_size - (x_size % 8);
538 for(
size_t i = 0; i != blocks; i += 8) {
542 for(
size_t i = blocks; i != x_size; ++i) {
551 const size_t blocks = x_size - (x_size % 8);
555 for(
size_t i = 0; i != blocks; i += 8) {
559 for(
size_t i = blocks; i != x_size; ++i) {
573inline constexpr int32_t
bigint_cmp(
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
574 static_assert(
sizeof(W) >=
sizeof(uint32_t),
"Size assumption");
576 const W LT =
static_cast<W
>(-1);
580 const size_t common_elems = std::min(x_size, y_size);
584 for(
size_t i = 0; i != common_elems; i++) {
588 result = is_eq.select(result, is_lt.select(LT, GT));
591 if(x_size < y_size) {
593 for(
size_t i = x_size; i != y_size; i++) {
599 }
else if(y_size < x_size) {
601 for(
size_t i = y_size; i != x_size; i++) {
611 return static_cast<int32_t
>(result);
573inline constexpr int32_t
bigint_cmp(
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
…}
620inline constexpr auto bigint_ct_is_lt(
const W x[],
size_t x_size,
const W y[],
size_t y_size,
bool lt_or_equal =
false)
622 const size_t common_elems = std::min(x_size, y_size);
626 for(
size_t i = 0; i != common_elems; i++) {
629 is_lt = eq.select_mask(is_lt, lt);
632 if(x_size < y_size) {
634 for(
size_t i = x_size; i != y_size; i++) {
639 }
else if(y_size < x_size) {
641 for(
size_t i = y_size; i != x_size; i++) {
620inline constexpr auto bigint_ct_is_lt(
const W x[],
size_t x_size,
const W y[],
size_t y_size,
bool lt_or_equal =
false) {
…}
654 const size_t common_elems = std::min(x_size, y_size);
658 for(
size_t i = 0; i != common_elems; i++) {
659 diff |= (x[i] ^ y[i]);
663 if(x_size < y_size) {
664 for(
size_t i = x_size; i != y_size; i++) {
667 }
else if(y_size < x_size) {
668 for(
size_t i = y_size; i != x_size; i++) {
690inline constexpr int32_t
bigint_sub_abs(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
691 const int32_t relative_size =
bigint_cmp(x, x_size, y, y_size);
694 const bool need_swap = relative_size < 0;
703 y_size = std::min(x_size, y_size);
707 return relative_size;
690inline constexpr int32_t
bigint_sub_abs(W z[],
const W x[],
size_t x_size,
const W y[],
size_t y_size) {
…}
720inline constexpr void bigint_mod_sub(W t[],
const W s[],
const W mod[],
size_t mod_sw, W ws[]) {
722 const W borrow =
bigint_sub3(ws, t, mod_sw, s, mod_sw);
720inline constexpr void bigint_mod_sub(W t[],
const W s[],
const W mod[],
size_t mod_sw, W ws[]) {
…}
741 n <<= WordInfo<W>::bits;
743 return static_cast<W
>(n / d);
755 if(high_top_bit || high >= d) {
816template <
size_t S, WordType W,
size_t N>
818 static_assert(S < WordInfo<W>::bits,
"Shift too large");
821 for(
size_t i = 0; i != N; ++i) {
823 x[i] = (w << S) |
carry;
830template <
size_t S, WordType W,
size_t N>
832 static_assert(S < WordInfo<W>::bits,
"Shift too large");
835 for(
size_t i = 0; i != N; ++i) {
836 const W w = x[N - 1 - i];
837 x[N - 1 - i] = (w >> S) |
carry;
845template <WordType W,
size_t N>
848 const constexpr size_t C = N - 1;
854 const constexpr size_t S = (C + NPW - 1) / NPW;
856 auto hex2int = [](
char c) -> int8_t {
857 if(c >=
'0' && c <=
'9') {
858 return static_cast<int8_t
>(c -
'0');
859 }
else if(c >=
'a' && c <=
'f') {
860 return static_cast<int8_t
>(c -
'a' + 10);
861 }
else if(c >=
'A' && c <=
'F') {
862 return static_cast<int8_t
>(c -
'A' + 10);
868 std::array<W, S> r = {0};
870 for(
size_t i = 0; i != C; ++i) {
871 const int8_t c = hex2int(s[i]);
903template <
size_t N, WordType W>
904constexpr inline void comba_mul(W z[2 * N],
const W x[N],
const W y[N]) {
905 if(!std::is_constant_evaluated()) {
906 if constexpr(std::same_as<W, word> && N == 4) {
909 if constexpr(std::same_as<W, word> && N == 6) {
912 if constexpr(std::same_as<W, word> && N == 7) {
915 if constexpr(std::same_as<W, word> && N == 8) {
918 if constexpr(std::same_as<W, word> && N == 9) {
921 if constexpr(std::same_as<W, word> && N == 16) {
928 for(
size_t i = 0; i != 2 * N; ++i) {
929 const size_t start = i + 1 < N ? 0 : i + 1 - N;
930 const size_t end = std::min(N, i + 1);
932 for(
size_t j = start; j != end; ++j) {
933 accum.
mul(x[j], y[i - j]);
904constexpr inline void comba_mul(W z[2 * N],
const W x[N],
const W y[N]) {
…}
939template <
size_t N, WordType W>
940constexpr inline void comba_sqr(W z[2 * N],
const W x[N]) {
941 if(!std::is_constant_evaluated()) {
942 if constexpr(std::same_as<W, word> && N == 4) {
945 if constexpr(std::same_as<W, word> && N == 6) {
948 if constexpr(std::same_as<W, word> && N == 7) {
951 if constexpr(std::same_as<W, word> && N == 8) {
954 if constexpr(std::same_as<W, word> && N == 9) {
957 if constexpr(std::same_as<W, word> && N == 16) {
964 for(
size_t i = 0; i != 2 * N; ++i) {
965 const size_t start = i + 1 < N ? 0 : i + 1 - N;
966 const size_t end = std::min(N, i + 1);
968 for(
size_t j = start; j != end; ++j) {
969 accum.
mul(x[j], x[i - j]);
1003inline void bigint_monty_redc(word z[],
const word p[],
size_t p_size, word p_dash, word ws[],
size_t ws_size) {
1004 const size_t z_size = 2 * p_size;
1006 BOTAN_ARG_CHECK(ws_size >= p_size,
"Montgomery reduction workspace too small");
1010 }
else if(p_size == 6) {
1012 }
else if(p_size == 8) {
1014 }
else if(p_size == 16) {
1016 }
else if(p_size == 24) {
1018 }
else if(p_size == 32) {
1003inline void bigint_monty_redc(word z[],
const word p[],
size_t p_size, word p_dash, word ws[],
size_t ws_size) {
…}
1029void basecase_mul(word z[],
size_t z_size,
const word x[],
size_t x_size,
const word y[],
size_t y_size);
1035void basecase_sqr(word z[],
size_t z_size,
const word x[],
size_t x_size);
1051void bigint_sqr(word z[],
size_t z_size,
const word x[],
size_t x_size,
size_t x_sw, word workspace[],
size_t ws_size);
1056template <WordType W,
size_t N, W C>
1058 static_assert(C % 2 == 1);
1060 for(
size_t i = 0; i != N; ++i) {
1077template <WordType W,
size_t N, W C>
1079 static_assert(N >= 2);
1081 std::array<W, N> hi = {};
1086 for(
size_t i = 0; i != N; ++i) {
1091 word carry_c[2] = {0};
1098 std::array<W, N> r = {};
1107template <
size_t N, WordType W>
1108constexpr inline void bigint_correct_redc(std::array<W, N>& r,
const std::array<W, N>& P,
const std::array<W, N>& C) {
1108constexpr inline void bigint_correct_redc(std::array<W, N>& r,
const std::array<W, N>& P,
const std::array<W, N>& C) {
…}
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
constexpr void select_n(T output[], const T x[], const T y[], size_t len) const
static constexpr Mask< T > expand(T v)
constexpr T select(T x, T y) const
static constexpr Mask< T > is_equal(T x, T y)
static constexpr Mask< T > is_lt(T x, T y)
static constexpr Mask< T > is_zero(T x)
constexpr void mul(W x, W y)
constexpr void conditional_swap_ptr(bool cnd, T &x, T &y)
constexpr void conditional_swap(bool cnd, T &x, T &y)
constexpr Mask< T > conditional_assign_mem(T cnd, T *sink, const T *src, size_t elems)
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *to, const T *from0, const T *from1, size_t elems)
constexpr void unpoison(const T *p, size_t n)
constexpr void bigint_cnd_abs(W cnd, W x[], size_t size)
constexpr void bigint_linmul3(W z[], const W x[], size_t x_size, W y)
constexpr auto bigint_add(std::span< W, N > z, std::span< const W, N > x, std::span< const W, N > y) -> W
constexpr void bigint_cnd_swap(W cnd, W x[], W y[], size_t size)
constexpr auto word8_sub3(W z[8], const W x[8], const W y[8], W carry) -> W
constexpr W shift_left(std::array< W, N > &x)
constexpr auto word_sub(W x, W y, W *carry) -> W
void bigint_monty_redc(word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size)
constexpr auto word_add(W x, W y, W *carry) -> W
constexpr void comba_sqr(W z[2 *N], const W x[N])
constexpr uint64_t carry_shift(const donna128 &a, size_t shift)
constexpr void bigint_shr2(W y[], const W x[], size_t x_size, size_t shift)
BOTAN_FUZZER_API void basecase_sqr(word z[], size_t z_size, const word x[], size_t x_size)
void bigint_comba_sqr4(word z[8], const word x[4])
void bigint_comba_sqr6(word z[12], const word x[6])
BOTAN_FUZZER_API void bigint_monty_redc_24(word z[48], const word p[24], word p_dash, word ws[])
constexpr void bigint_shr1(W x[], size_t x_size, size_t shift)
constexpr auto word8_add3(W z[8], const W x[8], const W y[8], W carry) -> W
constexpr auto word4_sub3(W z[4], const W x[4], const W y[4], W carry) -> W
constexpr void comba_mul(W z[2 *N], const W x[N], const W y[N])
constexpr auto word8_sub2(W x[8], const W y[8], W carry) -> W
void bigint_comba_sqr7(word z[14], const word x[7])
void bigint_comba_mul4(word z[8], const word x[4], const word y[4])
constexpr auto word_madd2(W a, W b, W *c) -> W
void bigint_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, word workspace[], size_t ws_size)
void bigint_comba_mul16(word z[32], const word x[16], const word y[16])
constexpr auto word8_sub2_rev(W x[8], const W y[8], W carry) -> W
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto monty_inverse(W a) -> W
void bigint_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, word workspace[], size_t ws_size)
constexpr auto bigint_cnd_addsub(CT::Mask< W > mask, W x[], const W y[], const W z[], size_t size) -> W
void bigint_comba_mul6(word z[12], const word x[6], const word y[6])
BOTAN_FUZZER_API void bigint_monty_redc_4(word z[8], const word p[4], word p_dash, word ws[])
constexpr void bigint_shl1(W x[], size_t x_size, size_t x_words, size_t shift)
constexpr auto word4_add3(W z[4], const W x[4], const W y[4], W carry) -> W
consteval std::array< W, N > crandall_p()
constexpr auto bigint_ct_is_eq(const W x[], size_t x_size, const W y[], size_t y_size) -> CT::Mask< W >
constexpr int32_t bigint_cmp(const W x[], size_t x_size, const W y[], size_t y_size)
void bigint_comba_mul7(word z[14], const word x[7], const word y[7])
constexpr auto bigint_cnd_sub(W cnd, W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
constexpr void bigint_shl2(W y[], const W x[], size_t x_size, size_t shift)
void bigint_comba_mul9(word z[18], const word x[9], const word y[9])
constexpr W bigint_cnd_add(W cnd, W x[], size_t x_size, const W y[], size_t y_size)
void carry(int64_t &h0, int64_t &h1)
constexpr auto word8_linmul2(W x[8], W y, W carry) -> W
void bigint_comba_mul24(word z[48], const word x[24], const word y[24])
constexpr auto bigint_modop_vartime(W n1, W n0, W d) -> W
constexpr auto bigint_sub_abs(W z[], const W x[], const W y[], size_t N, W ws[]) -> CT::Mask< W >
BOTAN_FUZZER_API void bigint_monty_redc_6(word z[12], const word p[6], word p_dash, word ws[])
constexpr void bigint_add2(W x[], size_t x_size, const W y[], size_t y_size)
constexpr auto bigint_ct_is_lt(const W x[], size_t x_size, const W y[], size_t y_size, bool lt_or_equal=false) -> CT::Mask< W >
constexpr std::array< W, N > redc_crandall(std::span< const W, 2 *N > z)
constexpr void bigint_correct_redc(std::array< W, N > &r, const std::array< W, N > &P, const std::array< W, N > &C)
constexpr auto word8_add2(W x[8], const W y[8], W carry) -> W
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
void bigint_comba_sqr8(word z[16], const word x[8])
constexpr auto hex_to_words(const char(&s)[N])
void bigint_comba_sqr16(word z[32], const word x[16])
constexpr void bigint_cnd_add_or_sub(CT::Mask< W > mask, W x[], const W y[], size_t size)
constexpr void bigint_sub2_rev(W x[], const W y[], size_t y_size)
void bigint_comba_sqr9(word z[18], const word x[9])
constexpr auto bigint_add2_nc(W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto word8_linmul3(W z[8], const W x[8], W y, W carry) -> W
BOTAN_FUZZER_API void basecase_mul(word z[], size_t z_size, const word x[], size_t x_size, const word y[], size_t y_size)
constexpr void bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size)
BOTAN_FUZZER_API void bigint_monty_redc_generic(word z[], size_t z_size, const word p[], size_t p_size, word p_dash, word ws[])
void bigint_comba_sqr24(word z[48], const word x[24])
constexpr void copy_mem(T *out, const T *in, size_t n)
BOTAN_FUZZER_API void bigint_monty_redc_32(word z[64], const word p[32], word p_dash, word ws[])
void bigint_comba_mul8(word z[16], const word x[8], const word y[8])
BOTAN_FUZZER_API void bigint_monty_redc_16(word z[32], const word p[16], word p_dash, word ws[])
constexpr void clear_mem(T *ptr, size_t n)
constexpr auto bigint_divop_vartime(W n1, W n0, W d) -> W
constexpr W shift_right(std::array< W, N > &x)
BOTAN_FUZZER_API void bigint_monty_redc_8(word z[16], const word p[8], word p_dash, word ws[])
constexpr void bigint_mod_sub(W t[], const W s[], const W mod[], size_t mod_sw, W ws[])
constexpr auto word_madd3(W a, W b, W c, W *d) -> W
constexpr auto bigint_add3_nc(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto bigint_linmul2(W x[], size_t x_size, W y) -> W