Botan 3.13.0
Crypto and TLS for C&
Botan::divide_precomp< W > Class Template Referencefinal

#include <mp_core.h>

Public Member Functions

constexpr divide_precomp (W divisor)
constexpr W vartime_div_2to1 (W n1, W n0) const
constexpr W vartime_mod_2to1 (W n1, W n0) const

Detailed Description

template<WordType W>
class Botan::divide_precomp< W >

Setup for variable-time word level division/modulo operations

Currently this just uses the compiler's support for a 2/1 word division, but likely could be improved by precomputed values based on the divisor, for example using the approaches outlined in Hacker's Delight chapter 10.

Definition at line 572 of file mp_core.h.

Constructor & Destructor Documentation

◆ divide_precomp()

template<WordType W>
Botan::divide_precomp< W >::divide_precomp ( W divisor)
inlineexplicitconstexpr

Definition at line 574 of file mp_core.h.

574 : m_divisor(divisor) {
575 BOTAN_ARG_CHECK(m_divisor != 0, "Division by zero");
576 }
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33

References BOTAN_ARG_CHECK.

Member Function Documentation

◆ vartime_div_2to1()

template<WordType W>
W Botan::divide_precomp< W >::vartime_div_2to1 ( W n1,
W n0 ) const
inlineconstexpr

Definition at line 581 of file mp_core.h.

581 {
582 BOTAN_ASSERT_NOMSG(n1 < m_divisor);
583
584 if(m_divisor == WordInfo<W>::max) {
585 return vartime_div_2to1_max_d(n1, n0);
586 }
587
588 if(m_divisor == WordInfo<W>::top_bit) {
589 // Simply a shift by N-1 bits
590 return (n1 << 1) | (n0 >> (WordInfo<W>::bits - 1));
591 }
592
594#if defined(BOTAN_MP_USE_X86_64_ASM)
595 if constexpr(std::same_as<W, uint64_t>) {
596 W quotient = 0;
597 W remainder = 0;
598 // NOLINTNEXTLINE(*-no-assembler)
599 asm("divq %[v]" : "=a"(quotient), "=d"(remainder) : [v] "r"(m_divisor), "a"(n0), "d"(n1) : "cc");
600 return quotient;
601 }
602#endif
603
604#if !defined(BOTAN_BUILD_COMPILER_IS_CLANGCL)
605
606 /* clang-cl has a bug where on encountering a 128/64 division it emits
607 * a call to __udivti3() but then fails to link the relevant builtin into
608 * the binary, causing a link failure. Work around this by simply omitting
609 * such code for clang-cl
610 *
611 * See https://github.com/llvm/llvm-project/issues/25679
612 */
613 if constexpr(WordInfo<W>::dword_is_native) {
614 typename WordInfo<W>::dword n = n1;
616 n |= n0;
617 return static_cast<W>(n / m_divisor);
618 }
619#endif
620 }
621
622 W high = n1;
623 W quotient = 0;
624
625 for(size_t i = 0; i != WordInfo<W>::bits; ++i) {
626 const W high_top_bit = high >> (WordInfo<W>::bits - 1);
627
628 high <<= 1;
629 high |= (n0 >> (WordInfo<W>::bits - 1 - i)) & 1;
630 quotient <<= 1;
631
632 if(high_top_bit || high >= m_divisor) {
633 high -= m_divisor;
634 quotient |= 1;
635 }
636 }
637
638 return quotient;
639 }
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75

References BOTAN_ASSERT_NOMSG.

Referenced by Botan::vartime_divide(), Botan::vartime_divide_pow2k(), and vartime_mod_2to1().

◆ vartime_mod_2to1()

template<WordType W>
W Botan::divide_precomp< W >::vartime_mod_2to1 ( W n1,
W n0 ) const
inlineconstexpr

Definition at line 644 of file mp_core.h.

644 {
645 BOTAN_ASSERT_NOMSG(n1 < m_divisor);
646 W q = this->vartime_div_2to1(n1, n0);
647 W carry = 0;
648 q = word_madd2(q, m_divisor, &carry);
649 return (n0 - q);
650 }
constexpr W vartime_div_2to1(W n1, W n0) const
Definition mp_core.h:581
constexpr auto word_madd2(W a, W b, W *c) -> W
Definition mp_asmi.h:90

References BOTAN_ASSERT_NOMSG, Botan::carry(), vartime_div_2to1(), and Botan::word_madd2().

Referenced by Botan::operator%(), and Botan::BigInt::operator%=().


The documentation for this class was generated from the following file: