16#define WNAF_SIZE(x) ((bb::wnaf::SCALAR_BITS + (x) - 1) / (x))
20 if (num_points >= 14617149) {
23 if (num_points >= 1139094) {
27 if (num_points >= 155975) {
30 if (num_points >= 144834)
35 if (num_points >= 25067) {
38 if (num_points >= 13926) {
41 if (num_points >= 7659) {
44 if (num_points >= 2436) {
47 if (num_points >= 376) {
50 if (num_points >= 231) {
53 if (num_points >= 97) {
56 if (num_points >= 35) {
59 if (num_points >= 10) {
62 if (num_points >= 2) {
70 return 1UL << bits_per_bucket;
79template <
size_t bits,
size_t bit_position>
inline uint64_t
get_wnaf_bits_const(
const uint64_t* scalar)
noexcept
81 if constexpr (bits == 0) {
97 constexpr size_t lo_limb_idx = bit_position / 64;
98 constexpr size_t hi_limb_idx = (bit_position + bits - 1) / 64;
99 constexpr uint64_t lo_shift = bit_position & 63UL;
100 constexpr uint64_t bit_mask = (1UL <<
static_cast<uint64_t
>(bits)) - 1UL;
102 uint64_t lo = (scalar[lo_limb_idx] >> lo_shift);
103 if constexpr (lo_limb_idx == hi_limb_idx) {
104 return lo & bit_mask;
106 constexpr uint64_t hi_shift = 64UL - (bit_position & 63UL);
107 uint64_t hi = ((scalar[hi_limb_idx] << (hi_shift)));
108 return (lo | hi) & bit_mask;
113inline uint64_t
get_wnaf_bits(
const uint64_t* scalar,
const uint64_t bits,
const uint64_t bit_position)
noexcept
128 const auto lo_limb_idx =
static_cast<size_t>(bit_position >> 6);
129 const auto hi_limb_idx =
static_cast<size_t>((bit_position + bits - 1) >> 6);
130 const uint64_t lo_shift = bit_position & 63UL;
131 const uint64_t bit_mask = (1UL <<
static_cast<uint64_t
>(bits)) - 1UL;
133 const uint64_t lo = (scalar[lo_limb_idx] >> lo_shift);
134 const uint64_t hi_shift = bit_position ? 64UL - (bit_position & 63UL) : 0;
135 const uint64_t hi = ((scalar[hi_limb_idx] << (hi_shift)));
136 const uint64_t hi_mask = bit_mask & (0ULL - (lo_limb_idx != hi_limb_idx));
138 return (lo & bit_mask) | (hi & hi_mask);
142 const uint64_t* scalar, uint64_t* wnaf,
bool& skew_map,
const uint64_t point_index,
const size_t wnaf_bits)
noexcept
144 skew_map = ((scalar[0] & 1) == 0);
145 uint64_t previous =
get_wnaf_bits(scalar, wnaf_bits, 0) +
static_cast<uint64_t
>(skew_map);
146 const size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
148 for (
size_t round_i = 1; round_i < wnaf_entries - 1; ++round_i) {
150 uint64_t predicate = ((
slice & 1UL) == 0UL);
151 wnaf[(wnaf_entries - round_i)] =
152 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
154 previous =
slice + predicate;
156 size_t final_bits =
SCALAR_BITS - (wnaf_bits * (wnaf_entries - 1));
158 uint64_t predicate = ((
slice & 1UL) == 0UL);
160 wnaf[1] = ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
162 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index);
181 const uint64_t point_index,
182 const uint64_t num_points,
183 const size_t wnaf_bits)
noexcept
185 skew_map = ((scalar[0] & 1) == 0);
186 uint64_t previous =
get_wnaf_bits(scalar, wnaf_bits, 0) +
static_cast<uint64_t
>(skew_map);
187 const size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
189 for (
size_t round_i = 1; round_i < wnaf_entries - 1; ++round_i) {
191 uint64_t predicate = ((
slice & 1UL) == 0UL);
192 wnaf[(wnaf_entries - round_i) * num_points] =
193 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
195 previous =
slice + predicate;
197 size_t final_bits =
SCALAR_BITS - (wnaf_bits * (wnaf_entries - 1));
199 uint64_t predicate = ((
slice & 1UL) == 0UL);
202 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
204 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index);
239 const uint64_t scalar_1_mask = (0ULL - (scalar[1] > 0));
240 const uint64_t scalar_0_mask = (0ULL - (scalar[0] > 0)) & ~scalar_1_mask;
242 const uint64_t msb = (scalar_1_mask & (msb_1 + 64)) | (scalar_0_mask & (msb_0));
277 uint64_t* wnaf_round_counts,
278 const uint64_t point_index,
279 const uint64_t num_points,
280 const size_t wnaf_bits)
noexcept
282 const size_t max_wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
283 if ((scalar[0] | scalar[1]) == 0ULL) {
285 for (
size_t round_i = 0; round_i < max_wnaf_entries; ++round_i) {
286 wnaf[(round_i)*num_points] = 0xffffffffffffffffULL;
291 skew_map = ((scalar[0] & 1) == 0);
292 uint64_t previous =
get_wnaf_bits(scalar, wnaf_bits, 0) +
static_cast<uint64_t
>(skew_map);
293 const auto wnaf_entries =
static_cast<size_t>((current_scalar_bits + wnaf_bits - 1) / wnaf_bits);
295 if (wnaf_entries == 1) {
296 wnaf[(max_wnaf_entries - 1) * num_points] = (previous >> 1UL) | (point_index);
297 ++wnaf_round_counts[max_wnaf_entries - 1];
298 for (
size_t j = wnaf_entries; j < max_wnaf_entries; ++j) {
299 wnaf[(max_wnaf_entries - 1 - j) * num_points] = 0xffffffffffffffffULL;
305 for (
size_t round_i = 1; round_i < wnaf_entries - 1; ++round_i) {
311 uint64_t predicate = ((
slice & 1UL) == 0UL);
314 ++wnaf_round_counts[max_wnaf_entries - round_i];
320 wnaf[(max_wnaf_entries - round_i) * num_points] =
321 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
325 previous =
slice + predicate;
328 auto final_bits =
static_cast<size_t>(current_scalar_bits - (wnaf_bits * (wnaf_entries - 1)));
330 uint64_t predicate = ((
slice & 1UL) == 0UL);
332 ++wnaf_round_counts[(max_wnaf_entries - wnaf_entries + 1)];
333 wnaf[((max_wnaf_entries - wnaf_entries + 1) * num_points)] =
334 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
338 ++wnaf_round_counts[max_wnaf_entries - wnaf_entries];
339 wnaf[(max_wnaf_entries - wnaf_entries) * num_points] = ((
slice + predicate) >> 1UL) | (point_index);
342 for (
size_t j = wnaf_entries; j < max_wnaf_entries; ++j) {
343 wnaf[(max_wnaf_entries - 1 - j) * num_points] = 0xffffffffffffffffULL;
347template <
size_t num_po
ints,
size_t wnaf_bits,
size_t round_i>
348inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf,
const uint64_t point_index,
const uint64_t previous)
noexcept
350 constexpr size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
351 constexpr auto log2_num_points =
static_cast<size_t>(
numeric::get_msb(
static_cast<uint32_t
>(num_points)));
353 if constexpr (round_i < wnaf_entries - 1) {
355 uint64_t predicate = ((
slice & 1UL) == 0UL);
356 wnaf[(wnaf_entries - round_i) << log2_num_points] =
357 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
358 (point_index << 32UL);
359 wnaf_round<num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index,
slice + predicate);
364 uint64_t predicate = ((
slice & 1UL) == 0UL);
366 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
367 (point_index << 32UL);
368 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index << 32UL);
372template <
size_t scalar_bits,
size_t num_po
ints,
size_t wnaf_bits,
size_t round_i>
373inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf,
const uint64_t point_index,
const uint64_t previous)
noexcept
375 constexpr size_t wnaf_entries = (scalar_bits + wnaf_bits - 1) / wnaf_bits;
376 constexpr auto log2_num_points =
static_cast<uint64_t
>(
numeric::get_msb(
static_cast<uint32_t
>(num_points)));
378 if constexpr (round_i < wnaf_entries - 1) {
379 uint64_t
slice = get_wnaf_bits_const<wnaf_bits, round_i * wnaf_bits>(scalar);
380 uint64_t predicate = ((
slice & 1UL) == 0UL);
381 wnaf[(wnaf_entries - round_i) << log2_num_points] =
382 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
383 (point_index << 32UL);
384 wnaf_round<scalar_bits, num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index,
slice + predicate);
386 constexpr size_t final_bits = ((scalar_bits / wnaf_bits) * wnaf_bits == scalar_bits)
388 : scalar_bits - (scalar_bits / wnaf_bits) * wnaf_bits;
390 uint64_t predicate = ((
slice & 1UL) == 0UL);
392 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
393 (point_index << 32UL);
394 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index << 32UL);
398template <
size_t wnaf_bits,
size_t round_i>
401 const uint64_t point_index,
402 const uint64_t previous)
noexcept
404 constexpr size_t wnaf_entries = (
SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
406 if constexpr (round_i < wnaf_entries - 1) {
409 uint64_t predicate = ((
slice & 1UL) == 0UL);
410 wnaf[(wnaf_entries - round_i)] =
411 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
413 wnaf_round_packed<wnaf_bits, round_i + 1>(scalar, wnaf, point_index,
slice + predicate);
418 uint64_t predicate = ((
slice & 1UL) == 0UL);
420 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
423 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index);
427template <
size_t num_po
ints,
size_t wnaf_bits>
428inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf,
bool& skew_map,
const size_t point_index)
noexcept
430 skew_map = ((scalar[0] & 1) == 0);
431 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) +
static_cast<uint64_t
>(skew_map);
432 wnaf_round<num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
435template <
size_t num_bits,
size_t num_po
ints,
size_t wnaf_bits>
436inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf,
bool& skew_map,
const size_t point_index)
noexcept
438 skew_map = ((scalar[0] & 1) == 0);
439 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) +
static_cast<uint64_t
>(skew_map);
440 wnaf_round<num_bits, num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
443template <
size_t scalar_bits,
size_t num_po
ints,
size_t wnaf_bits,
size_t round_i>
446 const uint64_t point_index,
447 const uint64_t previous)
noexcept
449 constexpr size_t wnaf_entries = (scalar_bits + wnaf_bits - 1) / wnaf_bits;
450 constexpr auto log2_num_points =
static_cast<uint64_t
>(
numeric::get_msb(
static_cast<uint32_t
>(num_points)));
451 constexpr size_t bits_in_first_slice = scalar_bits % wnaf_bits;
452 if constexpr (round_i == 1) {
454 uint64_t predicate = ((
slice & 1UL) == 0UL);
456 wnaf[(wnaf_entries - round_i) << log2_num_points] =
457 ((((previous - (predicate << (bits_in_first_slice ))) ^ (0UL - predicate)) >> 1UL) |
458 (predicate << 31UL)) |
459 (point_index << 32UL);
462 <<
" at index " << ((wnaf_entries - round_i) << log2_num_points) <<
std::endl;
464 wnaf_round_with_restricted_first_slice<scalar_bits, num_points, wnaf_bits, round_i + 1>(
465 scalar, wnaf, point_index,
slice + predicate);
467 }
else if constexpr (round_i < wnaf_entries - 1) {
469 uint64_t predicate = ((
slice & 1UL) == 0UL);
470 wnaf[(wnaf_entries - round_i) << log2_num_points] =
471 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
472 (point_index << 32UL);
473 wnaf_round_with_restricted_first_slice<scalar_bits, num_points, wnaf_bits, round_i + 1>(
474 scalar, wnaf, point_index,
slice + predicate);
477 uint64_t predicate = ((
slice & 1UL) == 0UL);
479 ((((previous - (predicate << (wnaf_bits ))) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
480 (point_index << 32UL);
481 wnaf[0] = ((
slice + predicate) >> 1UL) | (point_index << 32UL);
485template <
size_t num_bits,
size_t num_po
ints,
size_t wnaf_bits>
489 const size_t point_index)
noexcept
491 constexpr size_t bits_in_first_slice = num_bits % wnaf_bits;
493 skew_map = ((scalar[0] & 1) == 0);
494 uint64_t previous = get_wnaf_bits_const<bits_in_first_slice, 0>(scalar) +
static_cast<uint64_t
>(skew_map);
496 wnaf_round_with_restricted_first_slice<num_bits, num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
constexpr T get_msb(const T in)
constexpr size_t get_num_buckets(const size_t num_points)
void wnaf_round_packed(const uint64_t *scalar, uint64_t *wnaf, const uint64_t point_index, const uint64_t previous) noexcept
uint64_t get_num_scalar_bits(const uint64_t *scalar)
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
void fixed_wnaf_with_restricted_first_slice(uint64_t *scalar, uint64_t *wnaf, bool &skew_map, const size_t point_index) noexcept
uint64_t get_wnaf_bits_const(const uint64_t *scalar) noexcept
void wnaf_round(uint64_t *scalar, uint64_t *wnaf, const uint64_t point_index, const uint64_t previous) noexcept
constexpr size_t get_optimal_bucket_width(const size_t num_points)
void fixed_wnaf_packed(const uint64_t *scalar, uint64_t *wnaf, bool &skew_map, const uint64_t point_index, const size_t wnaf_bits) noexcept
void fixed_wnaf_with_counts(const uint64_t *scalar, uint64_t *wnaf, bool &skew_map, uint64_t *wnaf_round_counts, const uint64_t point_index, const uint64_t num_points, const size_t wnaf_bits) noexcept
void wnaf_round_with_restricted_first_slice(uint64_t *scalar, uint64_t *wnaf, const uint64_t point_index, const uint64_t previous) noexcept
uint64_t get_wnaf_bits(const uint64_t *scalar, const uint64_t bits, const uint64_t bit_position) noexcept
constexpr size_t get_num_rounds(const size_t num_points)
C slice(C const &container, size_t start)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept