41#define WNAF_SIZE(x) ((bb::wnaf::SCALAR_BITS + (x) - 1) / (x))
59template <
size_t bits,
size_t bit_position>
inline uint64_t
get_wnaf_bits_const(
const uint64_t* scalar)
noexcept
61 if constexpr (bits == 0) {
64 constexpr size_t lo_limb_idx = bit_position / 64;
65 constexpr size_t hi_limb_idx = (bit_position + bits - 1) / 64;
66 constexpr uint64_t lo_shift = bit_position & 63UL;
67 constexpr uint64_t bit_mask = (1UL <<
static_cast<uint64_t
>(bits)) - 1UL;
69 uint64_t lo = (scalar[lo_limb_idx] >> lo_shift);
70 if constexpr (lo_limb_idx == hi_limb_idx) {
73 constexpr uint64_t hi_shift = 64UL - (bit_position & 63UL);
74 uint64_t hi = ((scalar[hi_limb_idx] << (hi_shift)));
75 return (lo | hi) & bit_mask;
88inline uint64_t
get_wnaf_bits(
const uint64_t* scalar,
const uint64_t bits,
const uint64_t bit_position)
noexcept
91 const auto lo_limb_idx =
static_cast<size_t>(bit_position >> 6);
92 const auto hi_limb_idx =
static_cast<size_t>((bit_position + bits - 1) >> 6);
93 const uint64_t lo_shift = bit_position & 63UL;
94 const uint64_t bit_mask = (1UL <<
static_cast<uint64_t
>(bits)) - 1UL;
96 const uint64_t lo = (scalar[lo_limb_idx] >> lo_shift);
97 const uint64_t hi_shift = bit_position ? 64UL - (bit_position & 63UL) : 0;
98 const uint64_t hi = ((scalar[hi_limb_idx] << (hi_shift)));
99 const uint64_t hi_mask = bit_mask & (0ULL - (lo_limb_idx != hi_limb_idx));
101 return (lo & bit_mask) | (hi & hi_mask);
120 const uint64_t point_index,
121 const uint64_t num_points,
122 const size_t wnaf_bits)
noexcept
126 skew_map = ((scalar[0] & 1) == 0);
128 uint64_t previous =
get_wnaf_bits(scalar, wnaf_bits, 0) +
static_cast<uint64_t
>(skew_map);
129 const size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
132 for (
size_t round_i = 1; round_i < wnaf_entries - 1; ++round_i) {
135 uint64_t predicate = ((
slice & 1UL) == 0UL);
143 wnaf[(wnaf_entries - round_i) * num_points] =
144 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
147 previous =
slice + predicate;
149 size_t final_bits =
SCALAR_BITS - (wnaf_bits * (wnaf_entries - 1));
151 uint64_t predicate = ((
slice & 1UL) == 0UL);
154 ((((previous - (predicate << (wnaf_bits))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) | (point_index);
155 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index);
167template <
size_t num_po
ints,
size_t wnaf_bits,
size_t round_i>
168inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf,
const uint64_t point_index,
const uint64_t previous)
noexcept
170 constexpr size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
171 constexpr auto log2_num_points =
static_cast<size_t>(
numeric::get_msb(
static_cast<uint32_t
>(num_points)));
173 if constexpr (round_i < wnaf_entries - 1) {
175 uint64_t predicate = ((
slice & 1UL) == 0UL);
176 wnaf[(wnaf_entries - round_i) << log2_num_points] =
177 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
178 (point_index << 32UL);
179 wnaf_round<num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index,
slice + predicate);
183 uint64_t predicate = ((
slice & 1UL) == 0UL);
185 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
186 (point_index << 32UL);
187 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index << 32UL);
200template <
size_t scalar_bits,
size_t num_po
ints,
size_t wnaf_bits,
size_t round_i>
201inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf,
const uint64_t point_index,
const uint64_t previous)
noexcept
203 constexpr size_t wnaf_entries = (scalar_bits + wnaf_bits - 1) / wnaf_bits;
204 constexpr auto log2_num_points =
static_cast<uint64_t
>(
numeric::get_msb(
static_cast<uint32_t
>(num_points)));
206 if constexpr (round_i < wnaf_entries - 1) {
207 uint64_t
slice = get_wnaf_bits_const<wnaf_bits, round_i * wnaf_bits>(scalar);
208 uint64_t predicate = ((
slice & 1UL) == 0UL);
209 wnaf[(wnaf_entries - round_i) << log2_num_points] =
210 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
211 (point_index << 32UL);
212 wnaf_round<scalar_bits, num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index,
slice + predicate);
214 constexpr size_t final_bits = ((scalar_bits / wnaf_bits) * wnaf_bits == scalar_bits)
216 : scalar_bits - (scalar_bits / wnaf_bits) * wnaf_bits;
218 uint64_t predicate = ((
slice & 1UL) == 0UL);
220 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
221 (point_index << 32UL);
222 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index << 32UL);
226template <
size_t num_po
ints,
size_t wnaf_bits>
227inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf,
bool& skew_map,
const size_t point_index)
noexcept
229 skew_map = ((scalar[0] & 1) == 0);
230 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) +
static_cast<uint64_t
>(skew_map);
231 wnaf_round<num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
234template <
size_t num_bits,
size_t num_po
ints,
size_t wnaf_bits>
235inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf,
bool& skew_map,
const size_t point_index)
noexcept
237 skew_map = ((scalar[0] & 1) == 0);
238 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) +
static_cast<uint64_t
>(skew_map);
239 wnaf_round<num_bits, num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
constexpr T get_msb(const T in)
Fixed-window non-adjacent form (WNAF) scalar decomposition for elliptic curve scalar multiplication.
void fixed_wnaf(const uint64_t *scalar, uint64_t *wnaf, bool &skew_map, const uint64_t point_index, const uint64_t num_points, const size_t wnaf_bits) noexcept
Performs fixed-window non-adjacent form (WNAF) computation for scalar multiplication.
constexpr size_t SCALAR_BITS
uint64_t get_wnaf_bits_const(const uint64_t *scalar) noexcept
Extract a window of bits consecutive bits starting at bit_position from a 128-bit scalar.
void wnaf_round(uint64_t *scalar, uint64_t *wnaf, const uint64_t point_index, const uint64_t previous) noexcept
Recursive WNAF round for a fixed 127-bit scalar (SCALAR_BITS).
uint64_t get_wnaf_bits(const uint64_t *scalar, const uint64_t bits, const uint64_t bit_position) noexcept
A variant of the previous function that the bit position and number of bits are provided at runtime.
C slice(C const &container, size_t start)