Botan 3.11.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 559 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 561 of file mp_core.h.

561 : m_divisor(divisor) {
562 BOTAN_ARG_CHECK(m_divisor != 0, "Division by zero");
563 }
#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 568 of file mp_core.h.

568 {
569 BOTAN_ASSERT_NOMSG(n1 < m_divisor);
570
571 if(m_divisor == WordInfo<W>::max) {
572 return vartime_div_2to1_max_d(n1, n0);
573 }
574
575 if(m_divisor == WordInfo<W>::top_bit) {
576 // Simply a shift by N-1 bits
577 return (n1 << 1) | (n0 >> (WordInfo<W>::bits - 1));
578 }
579
581#if defined(BOTAN_MP_USE_X86_64_ASM)
582 if constexpr(std::same_as<W, uint64_t>) {
583 W quotient = 0;
584 W remainder = 0;
585 // NOLINTNEXTLINE(*-no-assembler)
586 asm("divq %[v]" : "=a"(quotient), "=d"(remainder) : [v] "r"(m_divisor), "a"(n0), "d"(n1));
587 return quotient;
588 }
589#endif
590
591#if !defined(BOTAN_BUILD_COMPILER_IS_CLANGCL)
592
593 /* clang-cl has a bug where on encountering a 128/64 division it emits
594 * a call to __udivti3() but then fails to link the relevant builtin into
595 * the binary, causing a link failure. Work around this by simply omitting
596 * such code for clang-cl
597 *
598 * See https://github.com/llvm/llvm-project/issues/25679
599 */
600 if constexpr(WordInfo<W>::dword_is_native) {
601 typename WordInfo<W>::dword n = n1;
603 n |= n0;
604 return static_cast<W>(n / m_divisor);
605 }
606#endif
607 }
608
609 W high = n1;
610 W quotient = 0;
611
612 for(size_t i = 0; i != WordInfo<W>::bits; ++i) {
613 const W high_top_bit = high >> (WordInfo<W>::bits - 1);
614
615 high <<= 1;
616 high |= (n0 >> (WordInfo<W>::bits - 1 - i)) & 1;
617 quotient <<= 1;
618
619 if(high_top_bit || high >= m_divisor) {
620 high -= m_divisor;
621 quotient |= 1;
622 }
623 }
624
625 return quotient;
626 }
#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 631 of file mp_core.h.

631 {
632 BOTAN_ASSERT_NOMSG(n1 < m_divisor);
633 W q = this->vartime_div_2to1(n1, n0);
634 W carry = 0;
635 q = word_madd2(q, m_divisor, &carry);
636 return (n0 - q);
637 }
constexpr W vartime_div_2to1(W n1, W n0) const
Definition mp_core.h:568
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: