_ZNK5Botan16AlgorithmPattern9to_stringEv:
   98|      2|      std::string_view to_string() const { return m_text; }
_ZNK5Botan16AlgorithmPattern8any_headEv:
  103|      5|      bool any_head() const { return m_head_count == 0; }
_ZNK5Botan16AlgorithmPattern17head_alternativesEv:
  105|      5|      std::span<const std::string_view> head_alternatives() const { return std::span(m_heads).first(m_head_count); }
_ZNK5Botan16AlgorithmPattern8elementsEv:
  107|      4|      std::span<const Element> elements() const { return std::span(m_elements).first(m_element_count); }
_ZNK5Botan13AlgorithmSpec4headEv:
  171|      2|      std::string_view head() const { return m_head; }
_ZN5Botan13AlgorithmSpecC2Ev:
  212|      4|      AlgorithmSpec() = default;

_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EED2Ev:
   64|      1|      ~AlignmentBuffer() { secure_zeroize_buffer(m_buffer.data(), sizeof(T) * m_buffer.size()); }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EEC2Ev:
   62|      1|      AlignmentBuffer() = default;
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE5clearEv:
   71|      7|      void clear() {
   72|      7|         zeroize_buffer(m_buffer.data(), m_buffer.size());
   73|      7|         m_position = 0;
   74|      7|      }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE21handle_unaligned_dataERNS_12BufferSlicerE:
  166|      9|      [[nodiscard]] std::optional<std::span<const T>> handle_unaligned_data(BufferSlicer& slicer) {
  167|       |         // When the final block is to be deferred, we would need to store and
  168|       |         // hold a buffer that contains exactly one block until more data is
  169|       |         // passed or it is explicitly consumed.
  170|      9|         const size_t defer = (defers_final_block()) ? 1 : 0;
  ------------------
  |  Branch (170:31): [True: 0, False: 9]
  ------------------
  171|       |
  172|      9|         if(in_alignment() && slicer.remaining() >= m_buffer.size() + defer) {
  ------------------
  |  Branch (172:13): [True: 9, False: 0]
  |  Branch (172:31): [True: 6, False: 3]
  ------------------
  173|       |            // We are currently in alignment and the passed-in data source
  174|       |            // contains enough data to benefit from aligned processing.
  175|       |            // Therefore, we don't copy anything into the intermittent buffer.
  176|      6|            return std::nullopt;
  177|      6|         }
  178|       |
  179|       |         // Fill the buffer with as much input data as needed to reach alignment
  180|       |         // or until the input source is depleted.
  181|      3|         const auto elements_to_consume = std::min(m_buffer.size() - m_position, slicer.remaining());
  182|      3|         append(slicer.take(elements_to_consume));
  183|       |
  184|       |         // If we collected enough data, we push out one full block. When
  185|       |         // deferring the final block is enabled, we additionally check that
  186|       |         // more input data is available to continue processing a consecutive
  187|       |         // block.
  188|      3|         if(ready_to_consume() && (!defers_final_block() || !slicer.empty())) {
  ------------------
  |  Branch (188:13): [True: 0, False: 3]
  |  Branch (188:36): [True: 0, False: 0]
  |  Branch (188:61): [True: 0, False: 0]
  ------------------
  189|      0|            return consume();
  190|      3|         } else {
  191|      3|            return std::nullopt;
  192|      3|         }
  193|      3|      }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE18defers_final_blockEv:
  233|     15|      constexpr bool defers_final_block() const {
  234|     15|         return FINAL_BLOCK_STRATEGY == AlignmentBufferFinalBlock::must_be_deferred;
  235|     15|      }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE6appendENSt3__14spanIKhLm18446744073709551615EEE:
   90|      7|      void append(std::span<const T> elements) {
   91|      7|         BOTAN_ASSERT_NOMSG(elements.size() <= elements_until_alignment());
  ------------------
  |  |   84|      7|   do {                                                                     \
  |  |   85|      7|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      7|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 7]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      7|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 7]
  |  |  ------------------
  ------------------
   92|      7|         std::copy(elements.begin(), elements.end(), m_buffer.begin() + m_position);
   93|      7|         m_position += elements.size();
   94|      7|      }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE24elements_until_alignmentEv:
  221|     19|      size_t elements_until_alignment() const { return m_buffer.size() - m_position; }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE16ready_to_consumeEv:
  231|     15|      bool ready_to_consume() const { return m_position == m_buffer.size(); }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE7consumeEv:
  200|      4|      [[nodiscard]] std::span<const T> consume() {
  201|      4|         BOTAN_ASSERT_NOMSG(ready_to_consume());
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
  202|      4|         m_position = 0;
  203|      4|         return m_buffer;
  204|      4|      }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE12in_alignmentEv:
  226|     24|      bool in_alignment() const { return m_position == 0; }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE23aligned_data_to_processERNS_12BufferSlicerE:
  126|      6|      [[nodiscard]] std::tuple<std::span<const uint8_t>, size_t> aligned_data_to_process(BufferSlicer& slicer) const {
  127|      6|         BOTAN_ASSERT_NOMSG(in_alignment());
  ------------------
  |  |   84|      6|   do {                                                                     \
  |  |   85|      6|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      6|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 6]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      6|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 6]
  |  |  ------------------
  ------------------
  128|       |
  129|       |         // When the final block is to be deferred, the last block must not be
  130|       |         // selected for processing if there is no (unaligned) extra input data.
  131|      6|         const size_t defer = (defers_final_block()) ? 1 : 0;
  ------------------
  |  Branch (131:31): [True: 0, False: 6]
  ------------------
  132|      6|         const size_t full_blocks_to_process = (slicer.remaining() - defer) / m_buffer.size();
  133|      6|         return {slicer.take(full_blocks_to_process * m_buffer.size()), full_blocks_to_process};
  134|      6|      }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE18fill_up_with_zerosEv:
   79|      4|      void fill_up_with_zeros() {
   80|      4|         if(!ready_to_consume()) {
  ------------------
  |  Branch (80:13): [True: 4, False: 0]
  ------------------
   81|      4|            zeroize_buffer(&m_buffer[m_position], elements_until_alignment());
   82|      4|            m_position = m_buffer.size();
   83|      4|         }
   84|      4|      }
_ZN5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE20directly_modify_lastEm:
  113|      4|      std::span<T> directly_modify_last(size_t elements) {
  114|      4|         BOTAN_ASSERT_NOMSG(size() >= elements);
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
  115|      4|         return std::span(m_buffer).last(elements);
  116|      4|      }
_ZNK5Botan15AlignmentBufferIhLm64ELNS_25AlignmentBufferFinalBlockE0EE4sizeEv:
  217|      4|      constexpr size_t size() const { return m_buffer.size(); }

_ZN5Botan17ct_expand_top_bitITkNSt3__117unsigned_integralEmEET_S2_:
   28|  2.72M|BOTAN_FORCE_INLINE constexpr T ct_expand_top_bit(T a) {
   29|  2.72M|   const T top = CT::value_barrier<T>(a >> (sizeof(T) * 8 - 1));
   30|  2.72M|   return static_cast<T>(0) - top;
   31|  2.72M|}
_ZN5Botan10ct_is_zeroITkNSt3__117unsigned_integralEmEET_S2_:
   37|  1.53M|BOTAN_FORCE_INLINE constexpr T ct_is_zero(T x) {
   38|  1.53M|   return ct_expand_top_bit<T>(~x & (x - 1));
   39|  1.53M|}
_ZN5Botan6chooseITkNSt3__117unsigned_integralEmEET_S2_S2_S2_:
  217|  2.01M|BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b) {
  218|       |   //return (mask & a) | (~mask & b);
  219|  2.01M|   return (b ^ (mask & (a ^ b)));
  220|  2.01M|}
_ZN5Botan17ct_if_is_zero_retITkNSt3__117unsigned_integralEmEEmT_m:
   45|  1.28M|BOTAN_FORCE_INLINE constexpr size_t ct_if_is_zero_ret(T x, size_t s) {
   46|       |   /*
   47|       |   Similar to `return ct_is_zero(x) & s` but has to account for possibility that
   48|       |   sizeof(T) is smaller than sizeof(size_t) which would lead to incomplete masking
   49|       |   */
   50|  1.28M|   const T a = ~x & (x - 1);
   51|  1.28M|   const size_t a_top = static_cast<size_t>(CT::value_barrier<T>(a >> (sizeof(T) * 8 - 1)));
   52|  1.28M|   const size_t mask = static_cast<size_t>(0) - a_top;
   53|  1.28M|   return mask & s;
   54|  1.28M|}
_ZN5Botan8high_bitITkNSt3__117unsigned_integralEmEEmT_:
   73|  30.3k|BOTAN_FORCE_INLINE constexpr size_t high_bit(T n) {
   74|  30.3k|   size_t hb = 0;
   75|       |
   76|   212k|   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
  ------------------
  |  Branch (76:38): [True: 182k, False: 30.3k]
  ------------------
   77|       |      // Equivalent to: ((n >> s) == 0) ? 0 : s;
   78|   182k|      const size_t z = s - ct_if_is_zero_ret<T>(n >> s, s);
   79|   182k|      hb += z;
   80|   182k|      n >>= z;
   81|   182k|   }
   82|       |
   83|  30.3k|   hb += static_cast<size_t>(n);
   84|       |
   85|  30.3k|   return hb;
   86|  30.3k|}
_ZN5Botan13is_power_of_2ITkNSt3__117unsigned_integralEmEEbT_:
   62|  27.2k|BOTAN_FORCE_INLINE constexpr bool is_power_of_2(T arg) {
   63|  27.2k|   return (arg != 0) && (arg != 1) && ((arg & static_cast<T>(arg - 1)) == 0);
  ------------------
  |  Branch (63:11): [True: 27.2k, False: 0]
  |  Branch (63:25): [True: 27.2k, False: 0]
  |  Branch (63:39): [True: 11.3k, False: 15.8k]
  ------------------
   64|  27.2k|}
_ZN5Botan12ceil_tobytesITkNSt3__117unsigned_integralEmEET_S2_:
  176|     53|BOTAN_FORCE_INLINE constexpr T ceil_tobytes(T bits) {
  177|     53|   return (bits + 7) / 8;
  178|     53|}
_ZN5Botan13ceil_divisionITkNSt3__117unsigned_integralEmEET_S2_S2_:
  167|    866|BOTAN_FORCE_INLINE constexpr T ceil_division(T a, T b) {
  168|       |   // Same as `(a + b - 1) / b` but avoids possible overflow
  169|    866|   return a / b + ((a % b != 0) ? 1 : 0);
  ------------------
  |  Branch (169:20): [True: 866, False: 0]
  ------------------
  170|    866|}
_ZN5Botan10ct_is_zeroITkNSt3__117unsigned_integralEhEET_S2_:
   37|  5.09k|BOTAN_FORCE_INLINE constexpr T ct_is_zero(T x) {
   38|  5.09k|   return ct_expand_top_bit<T>(~x & (x - 1));
   39|  5.09k|}
_ZN5Botan17ct_expand_top_bitITkNSt3__117unsigned_integralEhEET_S2_:
   28|  5.09k|BOTAN_FORCE_INLINE constexpr T ct_expand_top_bit(T a) {
   29|  5.09k|   const T top = CT::value_barrier<T>(a >> (sizeof(T) * 8 - 1));
   30|  5.09k|   return static_cast<T>(0) - top;
   31|  5.09k|}
_ZN5Botan6chooseITkNSt3__117unsigned_integralEhEET_S2_S2_S2_:
  217|  5.09k|BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b) {
  218|       |   //return (mask & a) | (~mask & b);
  219|  5.09k|   return (b ^ (mask & (a ^ b)));
  220|  5.09k|}
_ZN5Botan3ctzITkNSt3__117unsigned_integralEmEEmT_:
  115|   156k|BOTAN_FORCE_INLINE constexpr size_t ctz(T n) {
  116|       |   /*
  117|       |   * If n == 0 then this function will compute 8*sizeof(T)-1, so
  118|       |   * initialize lb to 1 if n == 0 to produce the expected result.
  119|       |   */
  120|   156k|   size_t lb = ct_if_is_zero_ret<T>(n, 1);
  121|       |
  122|  1.09M|   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
  ------------------
  |  Branch (122:38): [True: 941k, False: 156k]
  ------------------
  123|   941k|      const T range = (static_cast<T>(1) << s) - 1;
  124|       |      // Equivalent to: ((n & range) == 0) ? s : 0;
  125|   941k|      const size_t z = ct_if_is_zero_ret<T>(n & range, s);
  126|   941k|      lb += z;
  127|   941k|      n >>= z;
  128|   941k|   }
  129|       |
  130|   156k|   return lb;
  131|   156k|}

_ZN5Botan13reverse_bytesITkNSt3__117unsigned_integralEmQooooooeqstT_Li1EeqstS2_Li2EeqstS2_Li4EeqstS2_Li8EEES2_S2_:
   25|  1.43k|inline constexpr T reverse_bytes(T x) {
   26|       |   if constexpr(sizeof(T) == 1) {
   27|       |      return x;
   28|       |   } else if constexpr(sizeof(T) == 2) {
   29|       |#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap16)
   30|       |      return static_cast<T>(__builtin_bswap16(x));
   31|       |#else
   32|       |      return static_cast<T>((x << 8) | (x >> 8));
   33|       |#endif
   34|       |   } else if constexpr(sizeof(T) == 4) {
   35|       |#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap32)
   36|       |      return static_cast<T>(__builtin_bswap32(x));
   37|       |#else
   38|       |      // MSVC at least recognizes this as a bswap
   39|       |      return static_cast<T>(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8) |
   40|       |                            ((x & 0xFF000000) >> 24));
   41|       |#endif
   42|  1.43k|   } else if constexpr(sizeof(T) == 8) {
   43|  1.43k|#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap64)
   44|  1.43k|      return static_cast<T>(__builtin_bswap64(x));
   45|       |#else
   46|       |      uint32_t hi = static_cast<uint32_t>(x >> 32);
   47|       |      uint32_t lo = static_cast<uint32_t>(x);
   48|       |
   49|       |      hi = reverse_bytes(hi);
   50|       |      lo = reverse_bytes(lo);
   51|       |
   52|       |      return (static_cast<T>(lo) << 32) | hi;
   53|       |#endif
   54|  1.43k|   }
   55|  1.43k|}
_ZN5Botan13reverse_bytesITkNSt3__117unsigned_integralEjQooooooeqstT_Li1EeqstS2_Li2EeqstS2_Li4EeqstS2_Li8EEES2_S2_:
   25|     32|inline constexpr T reverse_bytes(T x) {
   26|       |   if constexpr(sizeof(T) == 1) {
   27|       |      return x;
   28|       |   } else if constexpr(sizeof(T) == 2) {
   29|       |#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap16)
   30|       |      return static_cast<T>(__builtin_bswap16(x));
   31|       |#else
   32|       |      return static_cast<T>((x << 8) | (x >> 8));
   33|       |#endif
   34|     32|   } else if constexpr(sizeof(T) == 4) {
   35|     32|#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap32)
   36|     32|      return static_cast<T>(__builtin_bswap32(x));
   37|       |#else
   38|       |      // MSVC at least recognizes this as a bswap
   39|       |      return static_cast<T>(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8) |
   40|       |                            ((x & 0xFF000000) >> 24));
   41|       |#endif
   42|       |   } else if constexpr(sizeof(T) == 8) {
   43|       |#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_bswap64)
   44|       |      return static_cast<T>(__builtin_bswap64(x));
   45|       |#else
   46|       |      uint32_t hi = static_cast<uint32_t>(x >> 32);
   47|       |      uint32_t lo = static_cast<uint32_t>(x);
   48|       |
   49|       |      hi = reverse_bytes(hi);
   50|       |      lo = reverse_bytes(lo);
   51|       |
   52|       |      return (static_cast<T>(lo) << 32) | hi;
   53|       |#endif
   54|       |   }
   55|     32|}

_ZN5Botan12BufferSlicerC2ENSt3__14spanIKhLm18446744073709551615EEE:
   25|      9|      explicit BufferSlicer(std::span<const uint8_t> buffer) : m_remaining(buffer) {}
_ZN5Botan12BufferSlicer4takeEm:
   37|      9|      std::span<const uint8_t> take(const size_t count) {
   38|      9|         BOTAN_STATE_CHECK(remaining() >= count);
  ------------------
  |  |   51|      9|   do {                                                         \
  |  |   52|      9|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */             \
  |  |   53|      9|      if(!(expr)) {                                             \
  |  |  ------------------
  |  |  |  Branch (53:10): [True: 0, False: 9]
  |  |  ------------------
  |  |   54|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */    \
  |  |   55|      0|         Botan::throw_invalid_state(#expr, __func__, __FILE__); \
  |  |   56|      0|      }                                                         \
  |  |   57|      9|   } while(0)
  |  |  ------------------
  |  |  |  Branch (57:12): [Folded, False: 9]
  |  |  ------------------
  ------------------
   39|      9|         const auto result = m_remaining.first(count);
   40|      9|         m_remaining = m_remaining.subspan(count);
   41|      9|         return result;
   42|      9|      }
_ZNK5Botan12BufferSlicer9remainingEv:
   73|     27|      size_t remaining() const { return m_remaining.size(); }
_ZNK5Botan12BufferSlicer5emptyEv:
   75|     18|      bool empty() const { return m_remaining.empty(); }

_ZN5Botan5CPUID3hasENS_10CPUFeatureE:
   93|  1.87k|      static bool has(CPUID::Feature feat) { return state().has_bit(feat.as_u32()); }
_ZN5Botan5CPUID3hasENS_10CPUFeatureES1_:
   98|   369k|      static bool has(CPUID::Feature feat1, CPUID::Feature feat2) {
   99|   369k|         return state().has_bit(feat1.as_u32() | feat2.as_u32());
  100|   369k|      }
_ZN5Botan5CPUID6is_setEjNS_10CPUFeatureE:
  126|      5|      static inline bool is_set(uint32_t allowed, CPUID::Feature bit) {
  127|      5|         const uint32_t feat_bit = bit.as_u32();
  128|      5|         return ((allowed & feat_bit) == feat_bit);
  129|      5|      }
_ZNK5Botan5CPUID10CPUID_Data7has_bitEj:
  143|   371k|            bool has_bit(uint32_t bit) const { return (m_processor_features & bit) == bit; }
_ZN5Botan5CPUID5stateEv:
  155|   371k|      static CPUID_Data& state() {
  156|   371k|         static CPUID::CPUID_Data g_cpuid;
  157|   371k|         return g_cpuid;
  158|   371k|      }
cpuid_x86.cpp:_ZN5Botan5CPUID6if_setIZNS0_10CPUID_Data19detect_cpu_featuresEjE16x86_CPUID_1_bitsEEjmT_NS_10CPUFeatureEj:
  116|      7|      static inline uint32_t if_set(uint64_t cpuid, T flag, CPUID::Feature bit, uint32_t allowed) {
  117|      7|         const uint64_t flag64 = static_cast<uint64_t>(flag);
  118|      7|         if((cpuid & flag64) == flag64) {
  ------------------
  |  Branch (118:13): [True: 7, False: 0]
  ------------------
  119|      7|            return (bit.as_u32() & allowed);
  120|      7|         } else {
  121|      0|            return 0;
  122|      0|         }
  123|      7|      }
cpuid_x86.cpp:_ZN5Botan5CPUID6if_setIZNS0_10CPUID_Data19detect_cpu_featuresEjE16x86_CPUID_7_bitsEEjmT_NS_10CPUFeatureEj:
  116|      8|      static inline uint32_t if_set(uint64_t cpuid, T flag, CPUID::Feature bit, uint32_t allowed) {
  117|      8|         const uint64_t flag64 = static_cast<uint64_t>(flag);
  118|      8|         if((cpuid & flag64) == flag64) {
  ------------------
  |  Branch (118:13): [True: 5, False: 3]
  ------------------
  119|      5|            return (bit.as_u32() & allowed);
  120|      5|         } else {
  121|      3|            return 0;
  122|      3|         }
  123|      8|      }
cpuid_x86.cpp:_ZN5Botan5CPUID6if_setIZNS0_10CPUID_Data19detect_cpu_featuresEjE18x86_CPUID_7_1_bitsEEjmT_NS_10CPUFeatureEj:
  116|      3|      static inline uint32_t if_set(uint64_t cpuid, T flag, CPUID::Feature bit, uint32_t allowed) {
  117|      3|         const uint64_t flag64 = static_cast<uint64_t>(flag);
  118|      3|         if((cpuid & flag64) == flag64) {
  ------------------
  |  Branch (118:13): [True: 0, False: 3]
  ------------------
  119|      0|            return (bit.as_u32() & allowed);
  120|      3|         } else {
  121|      3|            return 0;
  122|      3|         }
  123|      3|      }

_ZN5Botan10CPUFeatureC2ENS0_3BitE:
   54|   741k|      CPUFeature(Bit b) : m_bit(b) {}  // NOLINT(*-explicit-conversions,*-explicit-constructor)
_ZNK5Botan10CPUFeature6as_u32Ev:
   56|   741k|      uint32_t as_u32() const { return static_cast<uint32_t>(m_bit); }

_ZN5Botan2CT4MaskImE5is_gtEmm:
  458|  82.6k|      static constexpr Mask<T> is_gt(T x, T y) { return Mask<T>::is_lt(y, x); }
_ZN5Botan2CT4MaskImE5is_ltEmm:
  450|   823k|      static constexpr Mask<T> is_lt(T x, T y) {
  451|   823k|         T u = x ^ ((x ^ y) | ((x - y) ^ x));
  452|   823k|         return Mask<T>::expand_top_bit(u);
  453|   823k|      }
_ZN5Botan2CT4MaskImE14expand_top_bitEm:
  415|  1.18M|      static constexpr Mask<T> expand_top_bit(T v) { return Mask<T>(ct_expand_top_bit<T>(v)); }
_ZN5Botan2CT4MaskImEC2Em:
  637|  3.97M|      constexpr explicit Mask(T m) : m_mask(m) {}
_ZNK5Botan2CT4MaskImE13if_set_returnEm:
  538|  1.31M|      constexpr T if_set_return(T x) const { return value() & x; }
_ZNK5Botan2CT4MaskImE5valueEv:
  630|  4.89M|      constexpr T value() const { return value_barrier<T>(m_mask); }
_ZN5Botan2CT4MaskImE6is_gteEmm:
  468|   413k|      static constexpr Mask<T> is_gte(T x, T y) { return ~Mask<T>::is_lt(x, y); }
_ZNK5Botan2CT4MaskImEcoEv:
  533|  1.03M|      constexpr Mask<T> operator~() const { return Mask<T>(~value()); }
_ZN5Botan2CT6Choice9from_maskEm:
  303|  10.5k|      constexpr static Choice from_mask(underlying_type v) { return Choice(v); }
_ZNK5Botan2CT6ChoicentEv:
  309|  10.5k|      constexpr Choice operator!() const { return Choice(~value()); }
_ZNK5Botan2CT6ChoiceaaERKS1_:
  311|  10.5k|      constexpr Choice operator&&(const Choice& other) const { return Choice(value() & other.value()); }
_ZNK5Botan2CT6Choice7as_boolEv:
  329|  10.5k|      constexpr bool as_bool() const { return m_value != 0; }
_ZNK5Botan2CT6Choice5valueEv:
  332|  31.5k|      constexpr underlying_type value() const { return value_barrier(m_value); }
_ZN5Botan2CT6ChoiceC2Em:
  341|  42.0k|      constexpr explicit Choice(underlying_type v) : m_value(CT::value_barrier<underlying_type>(v)) {}
_ZN5Botan2CT4MaskImE7is_zeroEm:
  437|  1.07M|      static constexpr Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(value_barrier<T>(x))); }
_ZN5Botan2CT4MaskImE6expandEm:
  392|   619k|      static constexpr Mask<T> expand(T v) { return ~Mask<T>::is_zero(value_barrier<T>(v)); }
_ZNK5Botan2CT4MaskImE6selectEmm:
  548|   435k|      constexpr T select(T x, T y) const { return choose(value(), x, y); }
_ZN5Botan2CT8unpoisonImEEvPKT_m:
   67|   280k|constexpr inline void unpoison(const T* p, size_t n) {
   68|       |#if defined(BOTAN_HAS_VALGRIND)
   69|       |   if(!std::is_constant_evaluated()) {
   70|       |      VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
   71|       |   }
   72|       |#endif
   73|       |
   74|   280k|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  151|   280k|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   75|   280k|}
_ZN5Botan2CT8unpoisonITkNSt3__18integralEmEEvRKT_:
  112|   152k|constexpr void unpoison(const T& p) {
  113|   152k|   unpoison(&p, 1);
  114|   152k|}
_ZNK5Botan2CT4MaskImE16unpoisoned_valueEv:
  598|  38.7k|      constexpr T unpoisoned_value() const {
  599|  38.7k|         T r = value();
  600|  38.7k|         CT::unpoison(r);
  601|  38.7k|         return r;
  602|  38.7k|      }
_ZNK5Botan2CT4MaskImE9as_choiceEv:
  619|  10.5k|      constexpr CT::Choice as_choice() const {
  620|  10.5k|         if constexpr(sizeof(T) >= sizeof(Choice::underlying_type)) {
  621|  10.5k|            return CT::Choice::from_mask(static_cast<Choice::underlying_type>(unpoisoned_value()));
  622|       |         } else {
  623|       |            return CT::Choice::from_int(unpoisoned_value());
  624|       |         }
  625|  10.5k|      }
_ZN5Botan2CTorENS0_4MaskImEES2_:
  528|   396k|      friend constexpr Mask<T> operator|(Mask<T> x, Mask<T> y) { return Mask<T>(x.value() | y.value()); }
_ZN5Botan2CT4MaskImE8is_equalEmm:
  442|   424k|      static constexpr Mask<T> is_equal(T x, T y) {
  443|   424k|         const T diff = value_barrier(x) ^ value_barrier(y);
  444|   424k|         return Mask<T>::is_zero(diff);
  445|   424k|      }
_ZN5Botan2CT20conditional_copy_memImEENS0_4MaskIT_EES3_PS3_PKS3_S7_m:
  738|  8.35k|constexpr inline Mask<T> conditional_copy_mem(T cnd, T* dest, const T* if_set, const T* if_unset, size_t elems) {
  739|  8.35k|   const auto mask = CT::Mask<T>::expand(cnd);
  740|  8.35k|   return CT::conditional_copy_mem(mask, dest, if_set, if_unset, elems);
  741|  8.35k|}
_ZN5Botan2CT20conditional_copy_memImEENS0_4MaskIT_EES4_PS3_PKS3_S7_m:
  732|  8.35k|constexpr inline Mask<T> conditional_copy_mem(Mask<T> mask, T* dest, const T* if_set, const T* if_unset, size_t elems) {
  733|  8.35k|   mask.select_n(dest, if_set, if_unset, elems);
  734|  8.35k|   return mask;
  735|  8.35k|}
_ZNK5Botan2CT4MaskImE8select_nEPmPKmS5_m:
  565|   384k|      constexpr void select_n(T output[], const T x[], const T y[], size_t len) const {
  566|   384k|         const T mask = value();
  567|  1.96M|         for(size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (567:28): [True: 1.58M, False: 384k]
  ------------------
  568|  1.58M|            output[i] = choose(mask, x[i], y[i]);
  569|  1.58M|         }
  570|   384k|      }
_ZNK5Botan2CT4MaskImE7as_boolEv:
  614|  28.2k|      constexpr bool as_bool() const { return unpoisoned_value() != 0; }
_ZNK5Botan2CT4MaskImE11select_maskES2_S2_:
  559|   229k|      Mask<T> select_mask(Mask<T> x, Mask<T> y) const { return Mask<T>(select(x.value(), y.value())); }
_ZN5Botan2CT4MaskImEoRES2_:
  510|   157k|      Mask<T>& operator|=(Mask<T> o) {
  511|   157k|         m_mask |= o.value();
  512|   157k|         return (*this);
  513|   157k|      }
_ZN5Botan2CT4MaskImEaNES2_:
  494|  38.0k|      Mask<T>& operator&=(Mask<T> o) {
  495|  38.0k|         m_mask &= o.value();
  496|  38.0k|         return (*this);
  497|  38.0k|      }
_ZN5Botan2CT4MaskIhE11expand_boolEb:
  397|  5.09k|      static constexpr Mask<T> expand_bool(bool v) { return Mask<T>::expand(static_cast<T>(v)); }
_ZN5Botan2CT4MaskIhE6expandEh:
  392|  5.09k|      static constexpr Mask<T> expand(T v) { return ~Mask<T>::is_zero(value_barrier<T>(v)); }
_ZN5Botan2CT4MaskIhE7is_zeroEh:
  437|  5.09k|      static constexpr Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(value_barrier<T>(x))); }
_ZN5Botan2CT4MaskIhEC2Eh:
  637|  10.1k|      constexpr explicit Mask(T m) : m_mask(m) {}
_ZNK5Botan2CT4MaskIhEcoEv:
  533|  5.09k|      constexpr Mask<T> operator~() const { return Mask<T>(~value()); }
_ZNK5Botan2CT4MaskIhE5valueEv:
  630|  10.1k|      constexpr T value() const { return value_barrier<T>(m_mask); }
_ZNK5Botan2CT4MaskIhE6selectEhh:
  548|  5.09k|      constexpr T select(T x, T y) const { return choose(value(), x, y); }
_ZN5Botan2CT6poisonImEEvPKT_m:
   56|  9.04k|constexpr inline void poison(const T* p, size_t n) {
   57|       |#if defined(BOTAN_HAS_VALGRIND)
   58|       |   if(!std::is_constant_evaluated()) {
   59|       |      VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
   60|       |   }
   61|       |#endif
   62|       |
   63|  9.04k|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  151|  9.04k|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   64|  9.04k|}
_ZN5Botan2CTanENS0_4MaskImEES2_:
  518|  36.0k|      friend constexpr Mask<T> operator&(Mask<T> x, Mask<T> y) { return Mask<T>(x.value() & y.value()); }
_ZN5Botan2CT6Choice8from_intIjQaasr3stdE17unsigned_integralIT_Entsr3stdE7same_asIbS3_EEES1_S3_:
  268|  10.5k|      constexpr static Choice from_int(T v) {
  269|  10.5k|         if constexpr(sizeof(T) <= sizeof(underlying_type)) {
  270|  10.5k|            return !Choice(ct_is_zero<underlying_type>(v));
  271|       |         } else {
  272|       |            // Mask of T that is either |0| or |1|
  273|       |            const T v_is_0 = ct_is_zero<T>(value_barrier<T>(v));
  274|       |
  275|       |            // We want the mask to be set if v != 0 so we must check that
  276|       |            // v_is_0 is itself zero.
  277|       |            //
  278|       |            // Also sizeof(T) may not equal sizeof(underlying_type) so we must
  279|       |            // use ct_is_zero<underlying_type>. It's ok to either truncate or
  280|       |            // zero extend v_is_0 to 32 bits since we know it is |0| or |1|
  281|       |            // so even just the low bit is sufficient.
  282|       |            return Choice(ct_is_zero<underlying_type>(static_cast<underlying_type>(v_is_0)));
  283|       |         }
  284|  10.5k|      }
_ZN5Botan2CT6poisonITkNS_6ranges14spanable_rangeENSt3__14spanIKmLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEnt17custom_poisonableISB_EEEvRKSB_:
  121|  8.35k|constexpr void poison(const R& r) {
  122|  8.35k|   const std::span s{r};
  123|  8.35k|   poison(s.data(), s.size());
  124|  8.35k|}
_ZN5Botan2CT8unpoisonITkNS_6ranges14spanable_rangeENSt3__16vectorImNS_16secure_allocatorImEEEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEnt19custom_unpoisonableISC_EEEvRKSC_:
  128|  26.9k|constexpr void unpoison(const R& r) {
  129|  26.9k|   const std::span s{r};
  130|  26.9k|   unpoison(s.data(), s.size());
  131|  26.9k|}
_ZN5Botan2CT8unpoisonITkNS_6ranges14spanable_rangeENSt3__14spanIKmLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEnt19custom_unpoisonableISB_EEEvRKSB_:
  128|  8.35k|constexpr void unpoison(const R& r) {
  129|  8.35k|   const std::span s{r};
  130|  8.35k|   unpoison(s.data(), s.size());
  131|  8.35k|}
_ZN5Botan2CT4MaskImE3setEv:
  382|     96|      static constexpr Mask<T> set() { return Mask<T>(static_cast<T>(~0)); }
_ZN5Botan2CT6poisonITkNS_6ranges14spanable_rangeENSt3__16vectorImNS_16secure_allocatorImEEEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEnt17custom_poisonableISC_EEEvRKSC_:
  121|    688|constexpr void poison(const R& r) {
  122|    688|   const std::span s{r};
  123|    688|   poison(s.data(), s.size());
  124|    688|}
_ZN5Botan2CT22conditional_assign_memImEENS0_4MaskIT_EES3_PS3_PKS3_m:
  749|   351k|constexpr inline Mask<T> conditional_assign_mem(T cnd, T* dest, const T* src, size_t elems) {
  750|   351k|   const auto mask = CT::Mask<T>::expand(cnd);
  751|   351k|   mask.select_n(dest, src, dest, elems);
  752|   351k|   return mask;
  753|   351k|}
_ZN5Botan2CT9all_zerosImEENS0_4MaskIT_EEPKS3_m:
  785|      1|constexpr inline CT::Mask<T> all_zeros(const T elem[], size_t len) {
  786|      1|   T sum = 0;
  787|      5|   for(size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (787:22): [True: 4, False: 1]
  ------------------
  788|      4|      sum |= elem[i];
  789|      4|   }
  790|      1|   return CT::Mask<T>::is_zero(sum);
  791|      1|}
_ZN5Botan2CT4MaskImE7clearedEv:
  387|  23.2k|      static constexpr Mask<T> cleared() { return Mask<T>(0); }
_ZNK5Botan2CT4MaskImE17if_not_set_returnEm:
  543|   156k|      constexpr T if_not_set_return(T x) const { return ~value() & x; }
_ZN5Botan2CT16driveby_unpoisonITkNS0_12unpoisonableEmEEDcOT_Qsr3stdE21is_rvalue_reference_vIDtfp_EE:
  245|     15|{
  246|     15|   unpoison(v);
  247|     15|   return std::forward<T>(v);
  248|     15|}
_ZN5Botan2CT8is_equalImEENS0_4MaskIT_EEPKS3_S6_m:
  798|    261|constexpr inline CT::Mask<T> is_equal(const T x[], const T y[], size_t len) {
  799|    261|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (799:7): [Folded, False: 261]
  ------------------
  800|      0|      T difference = 0;
  801|       |
  802|      0|      for(size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (802:25): [True: 0, False: 0]
  ------------------
  803|      0|         difference = difference | (x[i] ^ y[i]);
  804|      0|      }
  805|       |
  806|      0|      return CT::Mask<T>::is_zero(difference);
  807|    261|   } else {
  808|    261|      volatile T difference = 0;
  809|       |
  810|  1.30k|      for(size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (810:25): [True: 1.04k, False: 261]
  ------------------
  811|  1.04k|         difference = difference | (x[i] ^ y[i]);
  812|  1.04k|      }
  813|       |
  814|    261|      return CT::Mask<T>::is_zero(difference);
  815|    261|   }
  816|    261|}
_ZN5Botan2CT12poison_rangeITkNSt3__16ranges5rangeENS2_6vectorINS_14Montgomery_IntENS2_9allocatorIS5_EEEEQ10poisonableINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEEEvRKSC_:
  181|     43|constexpr void poison_range(const R& r) {
  182|    688|   for(const auto& v : r) {
  ------------------
  |  Branch (182:22): [True: 688, False: 43]
  ------------------
  183|    688|      poison(v);
  184|    688|   }
  185|     43|}
_ZN5Botan2CT6poisonITkNS0_17custom_poisonableENS_14Montgomery_IntEEEvRKT_:
  138|    688|constexpr void poison(const T& x) {
  139|    688|   x._const_time_poison();
  140|    688|}
_ZN5Botan2CT8unpoisonITkNS0_19custom_unpoisonableENS_14Montgomery_IntEEEvRKT_:
  143|  1.84k|constexpr void unpoison(const T& x) {
  144|  1.84k|   x._const_time_unpoison();
  145|  1.84k|}

_ZN5Botan10fmt_detail6do_fmtERNSt3__119basic_ostringstreamIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_17basic_string_viewIcS4_EE:
   20|      1|inline void do_fmt(std::ostringstream& oss, std::string_view format) {
   21|      1|   oss << format;
   22|      1|}
_ZN5Botan3fmtIJPKcS2_S2_EEENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS3_17basic_string_viewIcS6_EEDpRKT_:
   53|      1|std::string fmt(std::string_view format, const T&... args) {
   54|      1|   std::ostringstream oss;
   55|      1|   oss.imbue(std::locale::classic());
   56|      1|   fmt_detail::do_fmt(oss, format, args...);
   57|      1|   return oss.str();
   58|      1|}
_ZN5Botan10fmt_detail6do_fmtIPKcJS3_S3_EEEvRNSt3__119basic_ostringstreamIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS4_17basic_string_viewIcS7_EERKT_DpRKT0_:
   25|      1|void do_fmt(std::ostringstream& oss, std::string_view format, const T& val, const Ts&... rest) {
   26|      1|   size_t i = 0;
   27|       |
   28|      1|   while(i < format.size()) {
  ------------------
  |  Branch (28:10): [True: 1, False: 0]
  ------------------
   29|      1|      if(format[i] == '{' && (format.size() > (i + 1)) && format.at(i + 1) == '}') {
  ------------------
  |  Branch (29:10): [True: 1, False: 0]
  |  Branch (29:30): [True: 1, False: 0]
  |  Branch (29:59): [True: 1, False: 0]
  ------------------
   30|      1|         oss << val;
   31|      1|         return do_fmt(oss, format.substr(i + 2), rest...);
   32|      1|      } else {
   33|      0|         oss << format[i];
   34|      0|      }
   35|       |
   36|      0|      i += 1;
   37|      0|   }
   38|      1|}
_ZN5Botan10fmt_detail6do_fmtIPKcJS3_EEEvRNSt3__119basic_ostringstreamIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS4_17basic_string_viewIcS7_EERKT_DpRKT0_:
   25|      1|void do_fmt(std::ostringstream& oss, std::string_view format, const T& val, const Ts&... rest) {
   26|      1|   size_t i = 0;
   27|       |
   28|      5|   while(i < format.size()) {
  ------------------
  |  Branch (28:10): [True: 5, False: 0]
  ------------------
   29|      5|      if(format[i] == '{' && (format.size() > (i + 1)) && format.at(i + 1) == '}') {
  ------------------
  |  Branch (29:10): [True: 1, False: 4]
  |  Branch (29:30): [True: 1, False: 0]
  |  Branch (29:59): [True: 1, False: 0]
  ------------------
   30|      1|         oss << val;
   31|      1|         return do_fmt(oss, format.substr(i + 2), rest...);
   32|      4|      } else {
   33|      4|         oss << format[i];
   34|      4|      }
   35|       |
   36|      4|      i += 1;
   37|      4|   }
   38|      1|}
_ZN5Botan10fmt_detail6do_fmtIPKcJEEEvRNSt3__119basic_ostringstreamIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS4_17basic_string_viewIcS7_EERKT_DpRKT0_:
   25|      1|void do_fmt(std::ostringstream& oss, std::string_view format, const T& val, const Ts&... rest) {
   26|      1|   size_t i = 0;
   27|       |
   28|      2|   while(i < format.size()) {
  ------------------
  |  Branch (28:10): [True: 2, False: 0]
  ------------------
   29|      2|      if(format[i] == '{' && (format.size() > (i + 1)) && format.at(i + 1) == '}') {
  ------------------
  |  Branch (29:10): [True: 1, False: 1]
  |  Branch (29:30): [True: 1, False: 0]
  |  Branch (29:59): [True: 1, False: 0]
  ------------------
   30|      1|         oss << val;
   31|      1|         return do_fmt(oss, format.substr(i + 2), rest...);
   32|      1|      } else {
   33|      1|         oss << format[i];
   34|      1|      }
   35|       |
   36|      1|      i += 1;
   37|      1|   }
   38|      1|}

_ZN5Botan11checked_mulITkNSt3__117unsigned_integralEmEENS1_8optionalIT_EES3_S3_:
   46|   124k|constexpr inline std::optional<T> checked_mul(T a, T b) {
   47|       |   // Multiplication by 1U is a hack to work around C's insane
   48|       |   // integer promotion rules.
   49|       |   // https://stackoverflow.com/questions/24795651
   50|   124k|   const T r = (1U * a) * b;
   51|       |   // If a == 0 then the multiply certainly did not overflow
   52|       |   // Otherwise r / a == b unless overflow occurred
   53|   124k|   if(a != 0 && r / a != b) {
  ------------------
  |  Branch (53:7): [True: 124k, False: 0]
  |  Branch (53:17): [True: 0, False: 124k]
  ------------------
   54|      0|      return {};
   55|      0|   }
   56|   124k|   return r;
   57|   124k|}

_ZN5Botan8store_beINS_6detail10AutoDetectEJRKmPhEEEDaDpOT0_:
  745|      4|inline constexpr auto store_be(ParamTs&&... params) {
  746|      4|   return detail::store_any<std::endian::big, ModifierT>(std::forward<ParamTs>(params)...);
  747|      4|}
_ZN5Botan6detail9store_anyILNSt3__16endianE64206ENS0_10AutoDetectETkNS0_20unsigned_integralishEmQoosr3stdE7same_asIS4_T0_Esr3stdE7same_asIT1_S5_EEEvS6_Ph:
  711|      4|inline constexpr void store_any(T in, uint8_t out[]) {
  712|       |   // asserts that *out points to enough bytes to write into
  713|      4|   store_any<endianness, InT>(in, std::span<uint8_t, sizeof(T)>(out, sizeof(T)));
  714|      4|}
_ZN5Botan6detail9store_anyILNSt3__16endianE64206ENS0_10AutoDetectETkNS0_20unsigned_integralishEmTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm8EEEQsr3stdE7same_asIS4_T0_EEEvT1_OT2_:
  646|      4|inline constexpr void store_any(T in, OutR&& out_range) {
  647|      4|   store_any<endianness, T>(in, std::forward<OutR>(out_range));
  648|      4|}
_ZN5Botan6detail9store_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEmTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm8EEEQnt15custom_storableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEEvS9_OT1_:
  525|      4|inline constexpr void store_any(WrappedInT wrapped_in, OutR&& out_range) {
  526|      4|   const auto in = detail::unwrap_strong_type_or_enum(wrapped_in);
  527|      4|   using InT = decltype(in);
  528|      4|   ranges::assert_exact_byte_length<sizeof(in)>(out_range);
  529|      4|   const std::span out{out_range};
  530|       |
  531|       |   // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  532|       |   // internally to copy ranges on a byte-by-byte basis, which is not allowed
  533|       |   // in a `constexpr` context.
  534|      4|   if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (534:7): [Folded, False: 4]
  ------------------
  535|      0|      return fallback_store_any<endianness, InT>(in, std::forward<OutR>(out_range));
  536|      4|   } else {
  537|       |      if constexpr(sizeof(InT) == 1) {
  538|       |         out[0] = static_cast<uint8_t>(in);
  539|       |      } else if constexpr(endianness == std::endian::native) {
  540|       |         typecast_copy(out, in);
  541|      4|      } else {
  542|      4|         static_assert(opposite(endianness) == std::endian::native);
  543|      4|         typecast_copy(out, reverse_bytes(in));
  544|      4|      }
  545|      4|   }
  546|      4|}
_ZN5Botan6detail26unwrap_strong_type_or_enumITkNS0_20unsigned_integralishEmEEDaT_:
  190|      4|constexpr auto unwrap_strong_type_or_enum(InT t) {
  191|       |   if constexpr(std::is_enum_v<InT>) {
  192|       |      // TODO: C++23: use std::to_underlying(in) instead
  193|       |      return static_cast<std::underlying_type_t<InT>>(t);
  194|      4|   } else {
  195|      4|      return Botan::unwrap_strong_type(t);
  196|      4|   }
  197|      4|}
_ZN5Botan7load_beImJNSt3__14spanIKhLm8EEEEEEDaDpOT0_:
  504|    843|inline constexpr auto load_be(ParamTs&&... params) {
  505|    843|   return detail::load_any<std::endian::big, OutT>(std::forward<ParamTs>(params)...);
  506|    843|}
_ZN5Botan6detail8load_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEmTkNS_6ranges16contiguous_rangeIhEENS2_4spanIKhLm8EEEQnt15custom_loadableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEESA_OT1_:
  278|    843|inline constexpr WrappedOutT load_any(InR&& in_range) {
  279|    843|   using OutT = detail::wrapped_type<WrappedOutT>;
  280|    843|   ranges::assert_exact_byte_length<sizeof(OutT)>(in_range);
  281|       |
  282|    843|   return detail::wrap_strong_type_or_enum<WrappedOutT>([&]() -> OutT {
  283|       |      // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  284|       |      // internally to copy ranges on a byte-by-byte basis, which is not allowed
  285|       |      // in a `constexpr` context.
  286|    843|      if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  287|    843|         return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
  288|    843|      } else {
  289|    843|         const std::span in{in_range};
  290|    843|         if constexpr(sizeof(OutT) == 1) {
  291|    843|            return static_cast<OutT>(in[0]);
  292|    843|         } else if constexpr(endianness == std::endian::native) {
  293|    843|            return typecast_copy<OutT>(in);
  294|    843|         } else {
  295|    843|            static_assert(opposite(endianness) == std::endian::native);
  296|    843|            return reverse_bytes(typecast_copy<OutT>(in));
  297|    843|         }
  298|    843|      }
  299|    843|   }());
  300|    843|}
_ZN5Botan6detail24wrap_strong_type_or_enumITkNS0_20unsigned_integralishEmTkNSt3__117unsigned_integralEmEEDaT0_:
  200|  1.43k|constexpr auto wrap_strong_type_or_enum(T t) {
  201|       |   if constexpr(std::is_enum_v<OutT>) {
  202|       |      return static_cast<OutT>(t);
  203|  1.43k|   } else {
  204|  1.43k|      return Botan::wrap_strong_type<OutT>(t);
  205|  1.43k|   }
  206|  1.43k|}
_ZZN5Botan6detail8load_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEmTkNS_6ranges16contiguous_rangeIhEENS2_4spanIKhLm8EEEQnt15custom_loadableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEESA_OT1_ENKUlvE_clEv:
  282|    843|   return detail::wrap_strong_type_or_enum<WrappedOutT>([&]() -> OutT {
  283|       |      // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  284|       |      // internally to copy ranges on a byte-by-byte basis, which is not allowed
  285|       |      // in a `constexpr` context.
  286|    843|      if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (286:10): [Folded, False: 843]
  ------------------
  287|      0|         return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
  288|    843|      } else {
  289|    843|         const std::span in{in_range};
  290|       |         if constexpr(sizeof(OutT) == 1) {
  291|       |            return static_cast<OutT>(in[0]);
  292|       |         } else if constexpr(endianness == std::endian::native) {
  293|       |            return typecast_copy<OutT>(in);
  294|    843|         } else {
  295|    843|            static_assert(opposite(endianness) == std::endian::native);
  296|    843|            return reverse_bytes(typecast_copy<OutT>(in));
  297|    843|         }
  298|    843|      }
  299|    843|   }());
_ZN5Botan7load_beImJRNSt3__15arrayIhLm8EEEEEEDaDpOT0_:
  504|    591|inline constexpr auto load_be(ParamTs&&... params) {
  505|    591|   return detail::load_any<std::endian::big, OutT>(std::forward<ParamTs>(params)...);
  506|    591|}
_ZN5Botan6detail8load_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEmTkNS_6ranges16contiguous_rangeIhEERNS2_5arrayIhLm8EEEQnt15custom_loadableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEESA_OT1_:
  278|    591|inline constexpr WrappedOutT load_any(InR&& in_range) {
  279|    591|   using OutT = detail::wrapped_type<WrappedOutT>;
  280|    591|   ranges::assert_exact_byte_length<sizeof(OutT)>(in_range);
  281|       |
  282|    591|   return detail::wrap_strong_type_or_enum<WrappedOutT>([&]() -> OutT {
  283|       |      // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  284|       |      // internally to copy ranges on a byte-by-byte basis, which is not allowed
  285|       |      // in a `constexpr` context.
  286|    591|      if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  287|    591|         return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
  288|    591|      } else {
  289|    591|         const std::span in{in_range};
  290|    591|         if constexpr(sizeof(OutT) == 1) {
  291|    591|            return static_cast<OutT>(in[0]);
  292|    591|         } else if constexpr(endianness == std::endian::native) {
  293|    591|            return typecast_copy<OutT>(in);
  294|    591|         } else {
  295|    591|            static_assert(opposite(endianness) == std::endian::native);
  296|    591|            return reverse_bytes(typecast_copy<OutT>(in));
  297|    591|         }
  298|    591|      }
  299|    591|   }());
  300|    591|}
_ZZN5Botan6detail8load_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEmTkNS_6ranges16contiguous_rangeIhEERNS2_5arrayIhLm8EEEQnt15custom_loadableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEESA_OT1_ENKUlvE_clEv:
  282|    591|   return detail::wrap_strong_type_or_enum<WrappedOutT>([&]() -> OutT {
  283|       |      // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  284|       |      // internally to copy ranges on a byte-by-byte basis, which is not allowed
  285|       |      // in a `constexpr` context.
  286|    591|      if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (286:10): [Folded, False: 591]
  ------------------
  287|      0|         return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
  288|    591|      } else {
  289|    591|         const std::span in{in_range};
  290|       |         if constexpr(sizeof(OutT) == 1) {
  291|       |            return static_cast<OutT>(in[0]);
  292|       |         } else if constexpr(endianness == std::endian::native) {
  293|       |            return typecast_copy<OutT>(in);
  294|    591|         } else {
  295|    591|            static_assert(opposite(endianness) == std::endian::native);
  296|    591|            return reverse_bytes(typecast_copy<OutT>(in));
  297|    591|         }
  298|    591|      }
  299|    591|   }());
_ZN5Botan6detail9store_anyILNSt3__16endianE64206ETkNS0_20unsigned_integralishEjTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm4EEEQnt15custom_storableINS0_19wrapped_type_helperIu14__remove_cvrefIT0_EE4typeEEEEvS9_OT1_:
  525|     32|inline constexpr void store_any(WrappedInT wrapped_in, OutR&& out_range) {
  526|     32|   const auto in = detail::unwrap_strong_type_or_enum(wrapped_in);
  527|     32|   using InT = decltype(in);
  528|     32|   ranges::assert_exact_byte_length<sizeof(in)>(out_range);
  529|     32|   const std::span out{out_range};
  530|       |
  531|       |   // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  532|       |   // internally to copy ranges on a byte-by-byte basis, which is not allowed
  533|       |   // in a `constexpr` context.
  534|     32|   if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (534:7): [Folded, False: 32]
  ------------------
  535|      0|      return fallback_store_any<endianness, InT>(in, std::forward<OutR>(out_range));
  536|     32|   } else {
  537|       |      if constexpr(sizeof(InT) == 1) {
  538|       |         out[0] = static_cast<uint8_t>(in);
  539|       |      } else if constexpr(endianness == std::endian::native) {
  540|       |         typecast_copy(out, in);
  541|     32|      } else {
  542|     32|         static_assert(opposite(endianness) == std::endian::native);
  543|     32|         typecast_copy(out, reverse_bytes(in));
  544|     32|      }
  545|     32|   }
  546|     32|}
_ZN5Botan6detail26unwrap_strong_type_or_enumITkNS0_20unsigned_integralishEjEEDaT_:
  190|     32|constexpr auto unwrap_strong_type_or_enum(InT t) {
  191|       |   if constexpr(std::is_enum_v<InT>) {
  192|       |      // TODO: C++23: use std::to_underlying(in) instead
  193|       |      return static_cast<std::underlying_type_t<InT>>(t);
  194|     32|   } else {
  195|     32|      return Botan::unwrap_strong_type(t);
  196|     32|   }
  197|     32|}
_ZN5Botan11copy_out_beITkNS_6ranges14spanable_rangeENSt3__16vectorIjNS_16secure_allocatorIjEEEEEEvNS2_4spanIhLm18446744073709551615EEERKT_:
  773|      4|inline void copy_out_be(std::span<uint8_t> out, const InR& in) {
  774|      4|   using T = std::ranges::range_value_t<InR>;
  775|      4|   std::span<const T> in_s{in};
  776|      4|   const auto remaining_bytes = detail::copy_out_any_word_aligned_portion<std::endian::big>(out, in_s);
  777|       |
  778|       |   // copy remaining bytes as a partial word
  779|      4|   for(size_t i = 0; i < remaining_bytes; ++i) {
  ------------------
  |  Branch (779:22): [True: 0, False: 4]
  ------------------
  780|      0|      out[i] = get_byte_var(i, in_s.front());
  781|      0|   }
  782|      4|}
_ZN5Botan6detail33copy_out_any_word_aligned_portionILNSt3__16endianE64206ETkNS0_20unsigned_integralishEjEEmRNS2_4spanIhLm18446744073709551615EEERNS4_IKT0_Lm18446744073709551615EEE:
  752|      4|inline size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<const T>& in) {
  753|      4|   const size_t full_words = out.size() / sizeof(T);
  754|      4|   const size_t full_word_bytes = full_words * sizeof(T);
  755|      4|   const size_t remaining_bytes = out.size() - full_word_bytes;
  756|      4|   BOTAN_ASSERT_NOMSG(in.size_bytes() >= full_word_bytes + remaining_bytes);
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
  757|       |
  758|       |   // copy full words
  759|      4|   store_any<endianness, T>(out.first(full_word_bytes), in.first(full_words));
  760|      4|   out = out.subspan(full_word_bytes);
  761|      4|   in = in.subspan(full_words);
  762|       |
  763|      4|   return remaining_bytes;
  764|      4|}
_ZN5Botan6detail9store_anyILNSt3__16endianE64206EjTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm18446744073709551615EEETkNS4_14spanable_rangeENS6_IKjLm18446744073709551615EEEQoosr3stdE7same_asINS0_10AutoDetectET0_Esr3stdE7same_asISB_NS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT2_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISJ_EESK_E4type10value_typeEEEEvOT1_RKSG_:
  603|      4|inline constexpr void store_any(OutR&& out /* NOLINT(*-std-forward) */, const InR& in) {
  604|      4|   ranges::assert_equal_byte_lengths(out, in);
  605|      4|   using element_type = std::ranges::range_value_t<InR>;
  606|       |
  607|      4|   const auto store_elementwise = [&] {
  608|      4|      constexpr size_t bytes_per_element = sizeof(element_type);
  609|      4|      std::span<uint8_t> out_s(out);
  610|      4|      for(const auto in_elem : in) {
  611|      4|         store_any<endianness, element_type>(out_s.template first<bytes_per_element>(), in_elem);
  612|      4|         out_s = out_s.subspan(bytes_per_element);
  613|      4|      }
  614|      4|   };
  615|       |
  616|       |   // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  617|       |   // internally to copy ranges on a byte-by-byte basis, which is not allowed
  618|       |   // in a `constexpr` context.
  619|      4|   if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (619:7): [Folded, False: 4]
  ------------------
  620|      0|      store_elementwise();
  621|      4|   } else {
  622|       |      if constexpr(endianness == std::endian::native && !custom_storable<element_type>) {
  623|       |         typecast_copy(out, in);
  624|      4|      } else {
  625|      4|         store_elementwise();
  626|      4|      }
  627|      4|   }
  628|      4|}
_ZZN5Botan6detail9store_anyILNSt3__16endianE64206EjTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm18446744073709551615EEETkNS4_14spanable_rangeENS6_IKjLm18446744073709551615EEEQoosr3stdE7same_asINS0_10AutoDetectET0_Esr3stdE7same_asISB_NS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT2_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISJ_EESK_E4type10value_typeEEEEvOT1_RKSG_ENKUlvE_clEv:
  607|      4|   const auto store_elementwise = [&] {
  608|      4|      constexpr size_t bytes_per_element = sizeof(element_type);
  609|      4|      std::span<uint8_t> out_s(out);
  610|     32|      for(const auto in_elem : in) {
  ------------------
  |  Branch (610:30): [True: 32, False: 4]
  ------------------
  611|     32|         store_any<endianness, element_type>(out_s.template first<bytes_per_element>(), in_elem);
  612|     32|         out_s = out_s.subspan(bytes_per_element);
  613|     32|      }
  614|      4|   };
_ZN5Botan6detail9store_anyILNSt3__16endianE64206EjTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm4EEETpTkNS0_20unsigned_integralishEJjEQaagtsZT2_Li0Eooaasr3stdE7same_asINS0_10AutoDetectET0_E10all_same_vIDpT2_Eaa20unsigned_integralishIS9_E10all_same_vIS9_SB_EEEvOT1_SB_:
  582|     32|inline constexpr void store_any(OutR&& out /* NOLINT(*-std-forward) */, Ts... ins) {
  583|     32|   ranges::assert_exact_byte_length<(sizeof(Ts) + ...)>(out);
  584|     32|   auto store_one = [off = 0]<typename T>(auto o, T i) mutable {
  585|     32|      store_any<endianness, T>(i, o.subspan(off).template first<sizeof(T)>());
  586|     32|      off += sizeof(T);
  587|     32|   };
  588|       |
  589|     32|   (store_one(std::span{out}, ins), ...);
  590|     32|}
_ZZN5Botan6detail9store_anyILNSt3__16endianE64206EjTkNS_6ranges23contiguous_output_rangeIhEENS2_4spanIhLm4EEETpTkNS0_20unsigned_integralishEJjEQaagtsZT2_Li0Eooaasr3stdE7same_asINS0_10AutoDetectET0_E10all_same_vIDpT2_Eaa20unsigned_integralishIS9_E10all_same_vIS9_SB_EEEvOT1_SB_ENUlTyS9_T_E_clIjS7_EEDaS9_SE_:
  584|     32|   auto store_one = [off = 0]<typename T>(auto o, T i) mutable {
  585|     32|      store_any<endianness, T>(i, o.subspan(off).template first<sizeof(T)>());
  586|     32|      off += sizeof(T);
  587|     32|   };
_ZN5Botan7load_leIjJPjPKhmEEEDaDpOT0_:
  495|      2|inline constexpr auto load_le(ParamTs&&... params) {
  496|      2|   return detail::load_any<std::endian::little, OutT>(std::forward<ParamTs>(params)...);
  497|      2|}
_ZN5Botan6detail8load_anyILNSt3__16endianE57005EjTkNS0_20unsigned_integralishEjQoosr3stdE7same_asINS0_10AutoDetectET0_Esr3stdE7same_asIT1_S5_EEEvPS6_PKhm:
  483|      2|inline constexpr void load_any(T out[], const uint8_t in[], size_t count) {
  484|       |   // asserts that *in and *out point to the correct amount of memory
  485|      2|   load_any<endianness, OutT>(std::span<T>(out, count), std::span<const uint8_t>(in, count * sizeof(T)));
  486|      2|}
_ZN5Botan6detail8load_anyILNSt3__16endianE57005EjTkNS_6ranges23contiguous_output_rangeENS2_4spanIjLm18446744073709551615EEETkNS4_16contiguous_rangeIhEENS5_IKhLm18446744073709551615EEEQaa20unsigned_integralishINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT1_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISH_EESI_E4type10value_typeEEoosr3stdE7same_asINS0_10AutoDetectET0_Esr3stdE7same_asISP_SN_EEEvOSE_RKT2_:
  355|      2|inline constexpr void load_any(OutR&& out /* NOLINT(*-std-forward) */, const InR& in) {
  356|      2|   ranges::assert_equal_byte_lengths(out, in);
  357|      2|   using element_type = std::ranges::range_value_t<OutR>;
  358|       |
  359|      2|   const auto load_elementwise = [&] {
  360|      2|      constexpr size_t bytes_per_element = sizeof(element_type);
  361|      2|      std::span<const uint8_t> in_s(in);
  362|      2|      for(auto& out_elem : out) {
  363|      2|         out_elem = load_any<endianness, element_type>(in_s.template first<bytes_per_element>());
  364|      2|         in_s = in_s.subspan(bytes_per_element);
  365|      2|      }
  366|      2|   };
  367|       |
  368|       |   // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
  369|       |   // internally to copy ranges on a byte-by-byte basis, which is not allowed
  370|       |   // in a `constexpr` context.
  371|      2|   if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
  ------------------
  |  Branch (371:7): [Folded, False: 2]
  ------------------
  372|      0|      load_elementwise();
  373|      2|   } else {
  374|      2|      if constexpr(endianness == std::endian::native && !custom_loadable<element_type>) {
  375|      2|         typecast_copy(out, in);
  376|       |      } else {
  377|       |         load_elementwise();
  378|       |      }
  379|      2|   }
  380|      2|}

_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EEC2Ev:
   42|      1|      MerkleDamgard_Hash() { clear(); }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE5clearEv:
   70|      7|      void clear() {
   71|      7|         MD::init(m_digest);
   72|      7|         m_buffer.clear();
   73|      7|         m_count = 0;
   74|      7|      }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE6updateENSt3__14spanIKhLm18446744073709551615EEE:
   44|      9|      void update(std::span<const uint8_t> input) {
   45|      9|         BufferSlicer in(input);
   46|       |
   47|     18|         while(!in.empty()) {
  ------------------
  |  Branch (47:16): [True: 9, False: 9]
  ------------------
   48|      9|            if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
  ------------------
  |  Branch (48:27): [True: 0, False: 9]
  ------------------
   49|      0|               MD::compress_n(m_digest, one_block.value(), 1);
   50|      0|            }
   51|       |
   52|      9|            if(m_buffer.in_alignment()) {
  ------------------
  |  Branch (52:16): [True: 6, False: 3]
  ------------------
   53|      6|               const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
   54|      6|               if(full_blocks > 0) {
  ------------------
  |  Branch (54:19): [True: 6, False: 0]
  ------------------
   55|      6|                  MD::compress_n(m_digest, aligned_data, full_blocks);
   56|      6|               }
   57|      6|            }
   58|      9|         }
   59|       |
   60|      9|         m_count += input.size();
   61|      9|      }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE5finalENSt3__14spanIhLm18446744073709551615EEE:
   63|      4|      void final(std::span<uint8_t> output) {
   64|      4|         append_padding_bit();
   65|      4|         append_counter_and_finalize();
   66|      4|         copy_output(output);
   67|      4|         clear();
   68|      4|      }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE18append_padding_bitEv:
   77|      4|      void append_padding_bit() {
   78|      4|         BOTAN_ASSERT_NOMSG(!m_buffer.ready_to_consume());
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
   79|      4|         if constexpr(MD::bit_endianness == MD_Endian::Big) {
   80|      4|            const uint8_t final_byte = 0x80;
   81|      4|            m_buffer.append({&final_byte, 1});
   82|       |         } else {
   83|       |            const uint8_t final_byte = 0x01;
   84|       |            m_buffer.append({&final_byte, 1});
   85|       |         }
   86|      4|      }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE27append_counter_and_finalizeEv:
   88|      4|      void append_counter_and_finalize() {
   89|       |         // Compress the remaining data if the final data block does not provide
   90|       |         // enough space for the counter bytes.
   91|      4|         if(m_buffer.elements_until_alignment() < MD::ctr_bytes) {
  ------------------
  |  Branch (91:13): [True: 0, False: 4]
  ------------------
   92|      0|            m_buffer.fill_up_with_zeros();
   93|      0|            MD::compress_n(m_digest, m_buffer.consume(), 1);
   94|      0|         }
   95|       |
   96|       |         // Make sure that any remaining bytes in the very last block are zero.
   97|      4|         BOTAN_ASSERT_NOMSG(m_buffer.elements_until_alignment() >= MD::ctr_bytes);
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
   98|      4|         m_buffer.fill_up_with_zeros();
   99|       |
  100|       |         // Replace a bunch of the right-most zero-padding with the counter bytes.
  101|      4|         const uint64_t bit_count = m_count * 8;
  102|      4|         const auto last_bytes = m_buffer.directly_modify_last(sizeof(bit_count));
  103|      4|         if constexpr(MD::byte_endianness == MD_Endian::Big) {
  104|      4|            store_be(bit_count, last_bytes.data());
  105|       |         } else {
  106|       |            store_le(bit_count, last_bytes.data());
  107|       |         }
  108|       |
  109|       |         // Compress the very last block.
  110|      4|         MD::compress_n(m_digest, m_buffer.consume(), 1);
  111|      4|      }
_ZN5Botan18MerkleDamgard_HashINS_7SHA_256EE11copy_outputENSt3__14spanIhLm18446744073709551615EEE:
  113|      4|      void copy_output(std::span<uint8_t> output) {
  114|      4|         BOTAN_ASSERT_NOMSG(output.size() >= MD::output_bytes);
  ------------------
  |  |   84|      4|   do {                                                                     \
  |  |   85|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      4|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
  115|       |
  116|      4|         if constexpr(MD::byte_endianness == MD_Endian::Big) {
  117|      4|            copy_out_be(output.first(MD::output_bytes), m_digest);
  118|       |         } else {
  119|       |            copy_out_le(output.first(MD::output_bytes), m_digest);
  120|       |         }
  121|      4|      }

_ZN5Botan14zeroize_bufferITkNSt3__117unsigned_integralEmEEvPT_m:
   37|   396k|inline void zeroize_buffer(T buf[], size_t n) {
   38|   396k|   if(n > 0) {
  ------------------
  |  Branch (38:7): [True: 371k, False: 24.2k]
  ------------------
   39|   371k|      std::memset(buf, 0, sizeof(T) * n);
   40|   371k|   }
   41|   396k|}
_ZN5Botan21unchecked_copy_memoryITkNSt3__117unsigned_integralEmEEvPT_PKS2_m:
   44|  24.2k|inline void unchecked_copy_memory(T* out, const T* in, size_t n) {
   45|  24.2k|   if(in != nullptr && out != nullptr && n > 0) {
  ------------------
  |  Branch (45:7): [True: 24.2k, False: 0]
  |  Branch (45:24): [True: 24.2k, False: 0]
  |  Branch (45:42): [True: 24.2k, False: 0]
  ------------------
   46|  24.2k|      std::memmove(out, in, sizeof(T) * n);
   47|  24.2k|   }
   48|  24.2k|}
_ZN5Botan14zeroize_bufferITkNSt3__117unsigned_integralEhEEvPT_m:
   37|     11|inline void zeroize_buffer(T buf[], size_t n) {
   38|     11|   if(n > 0) {
  ------------------
  |  Branch (38:7): [True: 11, False: 0]
  ------------------
   39|     11|      std::memset(buf, 0, sizeof(T) * n);
   40|     11|   }
   41|     11|}

_ZNK5Botan17Montgomery_Params1pEv:
   41|   356k|      const BigInt& p() const { return m_data->p(); }
_ZNK5Botan17Montgomery_Params2R1Ev:
   43|  1.87k|      const BigInt& R1() const { return m_data->r1(); }
_ZNK5Botan17Montgomery_Params2R2Ev:
   45|  1.84k|      const BigInt& R2() const { return m_data->r2(); }
_ZNK5Botan17Montgomery_Params6p_dashEv:
   49|   347k|      word p_dash() const { return m_data->p_dash(); }
_ZNK5Botan17Montgomery_Params7p_wordsEv:
   51|   187k|      size_t p_words() const { return m_data->p_size(); }
_ZNK5Botan17Montgomery_Params4Data1pEv:
   76|   356k|            const BigInt& p() const { return m_p; }
_ZNK5Botan17Montgomery_Params4Data2r1Ev:
   78|  1.87k|            const BigInt& r1() const { return m_r1; }
_ZNK5Botan17Montgomery_Params4Data2r2Ev:
   80|  1.84k|            const BigInt& r2() const { return m_r2; }
_ZNK5Botan17Montgomery_Params4Data6p_dashEv:
   84|   347k|            word p_dash() const { return m_p_dash; }
_ZNK5Botan17Montgomery_Params4Data6p_sizeEv:
   86|   187k|            size_t p_size() const { return m_p_words; }
_ZNK5Botan14Montgomery_Int4reprEv:
  143|  43.7k|      const secure_vector<word>& repr() const { return m_v; }
_ZNK5Botan14Montgomery_Int18_const_time_poisonEv:
  180|    688|      void _const_time_poison() const { CT::poison(m_v); }
_ZNK5Botan14Montgomery_Int20_const_time_unpoisonEv:
  182|  1.84k|      void _const_time_unpoison() const { CT::unpoison(m_v); }
_ZNK5Botan14Montgomery_Int7_paramsEv:
  184|  1.84k|      const Montgomery_Params& _params() const { return m_params; }

_ZN5Botan17monty_exp_vartimeERKNS_17Montgomery_ParamsERKNS_6BigIntES5_:
   79|  1.80k|inline Montgomery_Int monty_exp_vartime(const Montgomery_Params& params_p, const BigInt& g, const BigInt& k) {
   80|  1.80k|   const auto precomputed = monty_precompute(params_p, g, 4, false);
   81|  1.80k|   return monty_execute_vartime(*precomputed, k);
   82|  1.80k|}
_ZN5Botan31Montgomery_Exponentiation_StateC2Ev:
   41|  1.84k|      Montgomery_Exponentiation_State() = default;
_ZN5Botan31Montgomery_Exponentiation_StateD2Ev:
   22|  1.84k|      virtual ~Montgomery_Exponentiation_State() = default;

_ZN5Botan10word_madd2ITkNS_8WordTypeEmEET_S1_S1_PS1_:
   90|  90.6k|inline constexpr auto word_madd2(W a, W b, W* c) -> W {
   91|  90.6k|#if defined(BOTAN_MP_USE_X86_64_ASM)
   92|  90.6k|   if constexpr(std::same_as<W, uint64_t>) {
   93|  90.6k|      if(!std::is_constant_evaluated()) {
  ------------------
  |  Branch (93:10): [True: 90.6k, Folded]
  ------------------
   94|  90.6k|         asm(R"(
   95|  90.6k|            mulq %[b]
   96|  90.6k|            addq %[c],%[a]
   97|  90.6k|            adcq $0,%[carry]
   98|  90.6k|            )"
   99|  90.6k|             : [a] "=a"(a), [b] "=rm"(b), [carry] "=&d"(*c)
  100|  90.6k|             : "0"(a), "1"(b), [c] "g"(*c)
  101|  90.6k|             : "cc");
  102|       |
  103|  90.6k|         return a;
  104|  90.6k|      }
  105|  90.6k|   }
  106|       |#elif defined(BOTAN_MP_USE_AARCH64_ASM)
  107|       |   if constexpr(std::same_as<W, uint64_t>) {
  108|       |      if(!std::is_constant_evaluated()) {
  109|       |         W lo = 0;
  110|       |         W hi = 0;
  111|       |         asm(R"(
  112|       |            mul  %[lo], %[a], %[b]
  113|       |            umulh %[hi], %[a], %[b]
  114|       |            adds %[lo], %[lo], %[c]
  115|       |            adc  %[hi], %[hi], xzr
  116|       |            )"
  117|       |             : [lo] "=&r"(lo), [hi] "=&r"(hi)
  118|       |             : [a] "r"(a), [b] "r"(b), [c] "r"(*c)
  119|       |             : "cc");
  120|       |
  121|       |         *c = hi;
  122|       |         return lo;
  123|       |      }
  124|       |   }
  125|       |#endif
  126|       |
  127|      0|   typedef typename WordInfo<W>::dword dword;
  128|  90.6k|   const dword s = dword(a) * b + *c;
  129|  90.6k|   *c = static_cast<W>(s >> WordInfo<W>::bits);
  130|  90.6k|   return static_cast<W>(s);
  131|  90.6k|}
_ZN5Botan8word_addITkNS_8WordTypeEmEET_S1_S1_PS1_:
  239|  45.0k|inline constexpr auto word_add(W x, W y, W* carry) -> W {
  240|  45.0k|#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_addc)
  241|  45.0k|   if(!std::is_constant_evaluated()) {
  ------------------
  |  Branch (241:7): [True: 45.0k, Folded]
  ------------------
  242|       |      if constexpr(std::same_as<W, unsigned int>) {
  243|       |         return __builtin_addc(x, y, *carry & 1, carry);
  244|  45.0k|      } else if constexpr(std::same_as<W, unsigned long>) {
  245|  45.0k|         return __builtin_addcl(x, y, *carry & 1, carry);
  246|       |      } else if constexpr(std::same_as<W, unsigned long long>) {
  247|       |         return __builtin_addcll(x, y, *carry & 1, carry);
  248|       |      }
  249|  45.0k|   }
  250|      0|#endif
  251|       |
  252|       |   if constexpr(WordInfo<W>::dword_is_native && use_dword_for_word_add) {
  253|       |      /*
  254|       |      TODO(Botan4) this is largely a performance hack for GCCs that don't
  255|       |      support __builtin_addc, if we increase the minimum supported version of
  256|       |      GCC to GCC 14 then we can remove this and not worry about it
  257|       |      */
  258|       |      const W cb = *carry & 1;
  259|       |      const auto s = typename WordInfo<W>::dword(x) + y + cb;
  260|       |      *carry = static_cast<W>(s >> WordInfo<W>::bits);
  261|       |      return static_cast<W>(s);
  262|  45.0k|   } else {
  263|  45.0k|      const W cb = *carry & 1;
  264|  45.0k|      W z = x + y;
  265|  45.0k|      W c1 = (z < x);
  266|  45.0k|      z += cb;
  267|  45.0k|      *carry = c1 | (z < cb);
  268|  45.0k|      return z;
  269|  45.0k|   }
  270|  45.0k|}
_ZN5Botan8word_subITkNS_8WordTypeEmEET_S1_S1_PS1_:
  332|  1.65M|inline constexpr auto word_sub(W x, W y, W* carry) -> W {
  333|  1.65M|#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_subc)
  334|  1.65M|   if(!std::is_constant_evaluated()) {
  ------------------
  |  Branch (334:7): [True: 1.65M, Folded]
  ------------------
  335|       |      if constexpr(std::same_as<W, unsigned int>) {
  336|       |         return __builtin_subc(x, y, *carry & 1, carry);
  337|  1.65M|      } else if constexpr(std::same_as<W, unsigned long>) {
  338|  1.65M|         return __builtin_subcl(x, y, *carry & 1, carry);
  339|       |      } else if constexpr(std::same_as<W, unsigned long long>) {
  340|       |         return __builtin_subcll(x, y, *carry & 1, carry);
  341|       |      }
  342|  1.65M|   }
  343|      0|#endif
  344|       |
  345|      0|   const W cb = *carry & 1;
  346|  1.65M|   W t0 = x - y;
  347|  1.65M|   W c1 = (t0 > x);
  348|  1.65M|   W z = t0 - cb;
  349|  1.65M|   *carry = c1 | (z > t0);
  350|  1.65M|   return z;
  351|  1.65M|}
_ZN5Botan5word3ImEC2Ev:
  478|   347k|      constexpr word3() : m_w(0) {}
_ZN5Botan5word3ImE3mulEmm:
  480|  5.55M|      inline constexpr void mul(W x, W y) { m_w += static_cast<W3>(x) * y; }
_ZN5Botan5word3ImE7extractEv:
  486|  1.73M|      inline constexpr W extract() {
  487|  1.73M|         W r = static_cast<W>(m_w);
  488|  1.73M|         m_w >>= WordInfo<W>::bits;
  489|  1.73M|         return r;
  490|  1.73M|      }
_ZN5Botan5word3ImE3addEm:
  484|  2.77M|      inline constexpr void add(W x) { m_w += x; }
_ZN5Botan5word3ImE10monty_stepEmm:
  492|  1.38M|      inline constexpr W monty_step(W p0, W p_dash) {
  493|  1.38M|         const W w0 = static_cast<W>(m_w);
  494|  1.38M|         const W r = w0 * p_dash;
  495|  1.38M|         mul(r, p0);
  496|  1.38M|         m_w >>= WordInfo<W>::bits;
  497|  1.38M|         return r;
  498|  1.38M|      }

_ZNK5Botan14divide_precompImE14divmod_2to1_ctEmm:
  731|  28.4k|      inline constexpr std::pair<W, W> divmod_2to1_ct(W n1, W n0) const {
  732|       |         /*
  733|       |         * Scale the numerator to match the normalized divisor; the scaling cancels
  734|       |         * in the quotient and is removed from the remainder by the final shift.
  735|       |         */
  736|  28.4k|         n1 <<= m_shift;
  737|  28.4k|         const size_t rshift = WordInfo<W>::bits - m_shift;
  738|       |         /*
  739|       |         * We can't just `n0 >> rshift` because m_shift may be 0 (high bit divisor)
  740|       |         * in which case rshift will be the maximum bit length, and >> by the maximum
  741|       |         * bitlength is undefined behavior despite having an entirely obvious meaning.
  742|       |         *
  743|       |         * However we know m_shift is not equal to the bit length of the word, because
  744|       |         * that would imply that the divisor is 0. Thus rshift must be >= 1. So split
  745|       |         * the shift into two phases (first rshift-1, then 1)
  746|       |         */
  747|  28.4k|         n1 |= (n0 >> 1) >> (rshift - 1);
  748|  28.4k|         n0 <<= m_shift;
  749|       |
  750|  28.4k|         const auto [q, scaled_r] = div2by1_preinv(n1, n0, m_norm_divisor, m_reciprocal);
  751|  28.4k|         const W r = scaled_r >> m_shift;
  752|  28.4k|         return std::make_pair(q, r);
  753|  28.4k|      }
_ZN5Botan14divide_precompImE14div2by1_preinvEmmmm:
  782|  28.4k|      static constexpr std::pair<W, W> div2by1_preinv(W u1, W u0, W D, W v) {
  783|       |         // Steps 1-3: <q1,q0> = v*u1; <q1,q0> += <u1,u0>; q1 += 1
  784|  28.4k|         W q1 = u0;
  785|  28.4k|         const W q0 = word_madd2(u1, v, &q1);  // <q1,q0> = u1*v + u0
  786|  28.4k|         q1 += u1 + 1;
  787|       |
  788|       |         // Step 4
  789|  28.4k|         W r = u0 - q1 * D;
  790|       |
  791|       |         // Steps 5-7: If r >= q0 { q1 -= 1; r += d; }
  792|  28.4k|         const auto fix_down = CT::Mask<W>::is_gt(r, q0);
  793|  28.4k|         q1 -= fix_down.if_set_return(1);
  794|  28.4k|         r += fix_down.if_set_return(D);
  795|       |
  796|       |         // Steps 8-10: if r >= D { q1 += 1; r -= D; }
  797|  28.4k|         const auto fix_up = CT::Mask<W>::is_gte(r, D);
  798|  28.4k|         q1 += fix_up.if_set_return(1);
  799|  28.4k|         r -= fix_up.if_set_return(D);
  800|       |
  801|       |         // Step 11
  802|  28.4k|         return std::make_pair(q1, r);
  803|  28.4k|      }
_ZN5Botan17bigint_monty_redcEPmPKmS2_mmS0_m:
 1077|   347k|   word r[], const word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size) {
 1078|   347k|   const size_t z_size = 2 * p_size;
 1079|       |
 1080|   347k|   BOTAN_ARG_CHECK(ws_size >= p_size, "Montgomery reduction workspace too small");
  ------------------
  |  |   35|   347k|   do {                                                          \
  |  |   36|   347k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|   347k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 347k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|   347k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 347k]
  |  |  ------------------
  ------------------
 1081|       |
 1082|   347k|   if(p_size == 4) {
  ------------------
  |  Branch (1082:7): [True: 347k, False: 0]
  ------------------
 1083|   347k|      bigint_monty_redc_4(r, z, p, p_dash, ws);
 1084|   347k|   } else if(p_size == 6) {
  ------------------
  |  Branch (1084:14): [True: 0, False: 0]
  ------------------
 1085|      0|      bigint_monty_redc_6(r, z, p, p_dash, ws);
 1086|      0|   } else if(p_size == 8) {
  ------------------
  |  Branch (1086:14): [True: 0, False: 0]
  ------------------
 1087|      0|      bigint_monty_redc_8(r, z, p, p_dash, ws);
 1088|      0|   } else if(p_size == 12) {
  ------------------
  |  Branch (1088:14): [True: 0, False: 0]
  ------------------
 1089|      0|      bigint_monty_redc_12(r, z, p, p_dash, ws);
 1090|      0|   } else if(p_size == 16) {
  ------------------
  |  Branch (1090:14): [True: 0, False: 0]
  ------------------
 1091|      0|      bigint_monty_redc_16(r, z, p, p_dash, ws);
 1092|      0|   } else if(p_size == 24) {
  ------------------
  |  Branch (1092:14): [True: 0, False: 0]
  ------------------
 1093|      0|      bigint_monty_redc_24(r, z, p, p_dash, ws);
 1094|      0|   } else if(p_size == 32) {
  ------------------
  |  Branch (1094:14): [True: 0, False: 0]
  ------------------
 1095|      0|      bigint_monty_redc_32(r, z, p, p_dash, ws);
 1096|      0|   } else {
 1097|      0|      bigint_monty_redc_generic(r, z, z_size, p, p_size, p_dash, ws);
 1098|      0|   }
 1099|   347k|}
_ZN5Botan25bigint_monty_redc_inplaceEPmPKmmmS0_m:
 1101|  1.80k|inline void bigint_monty_redc_inplace(word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size) {
 1102|  1.80k|   bigint_monty_redc(z, z, p, p_size, p_dash, ws, ws_size);
 1103|  1.80k|   zeroize_buffer(z + p_size, p_size);
 1104|  1.80k|}
_ZN5Botan18reciprocal_word_ctITkNS_8WordTypeEmEET_S1_:
  649|  5.63k|constexpr W reciprocal_word_ct(W D) {
  650|  5.63k|   BOTAN_DEBUG_ASSERT((D & WordInfo<W>::top_bit) != 0);
  ------------------
  |  |  137|  5.63k|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|  5.63k|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 5.63k]
  |  |  ------------------
  ------------------
  651|       |
  652|       |   // Bit serial long division of ((~D) || (2^b - 1)) / D, with all of the
  653|       |   // conditional logic computed via masks
  654|  5.63k|   W remainder = static_cast<W>(~D);
  655|  5.63k|   W quotient = 0;
  656|       |
  657|   366k|   for(size_t i = 0; i != WordInfo<W>::bits; ++i) {
  ------------------
  |  Branch (657:22): [True: 360k, False: 5.63k]
  ------------------
  658|   360k|      const auto carry = CT::Mask<W>::expand_top_bit(remainder);
  659|   360k|      remainder = static_cast<W>((remainder << 1) | 1);
  660|   360k|      quotient <<= 1;
  661|       |
  662|   360k|      const auto sub = carry | CT::Mask<W>::is_gte(remainder, D);
  663|   360k|      remainder -= sub.if_set_return(D);
  664|   360k|      quotient |= sub.if_set_return(1);
  665|   360k|   }
  666|       |
  667|  5.63k|   return quotient;
  668|  5.63k|}
_ZN5Botan14divide_precompImE5setupEm:
  694|  5.63k|      static constexpr divide_precomp setup(W divisor) {
  695|  5.63k|         const size_t shift = WordInfo<W>::bits - high_bit(divisor);
  696|  5.63k|         const W norm_divisor = divisor << shift;
  697|  5.63k|         const W reciprocal = reciprocal_word_ct(norm_divisor);
  698|  5.63k|         return divide_precomp(divisor, shift, norm_divisor, reciprocal);
  699|  5.63k|      }
_ZN5Botan11bigint_add2ITkNS_8WordTypeEmEET_PS1_mPKS1_m:
   97|     97|inline constexpr auto bigint_add2(W x[], size_t x_size, const W y[], size_t y_size) -> W {
   98|     97|   W carry = 0;
   99|       |
  100|     97|   BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
  ------------------
  |  |   71|     97|   do {                                                                                 \
  |  |   72|     97|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|     97|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 97]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|     97|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 97]
  |  |  ------------------
  ------------------
  101|       |
  102|     97|   const size_t blocks = y_size - (y_size % 8);
  103|       |
  104|     97|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (104:22): [True: 0, False: 97]
  ------------------
  105|      0|      carry = word8_add2(x + i, y + i, carry);
  106|      0|   }
  107|       |
  108|    194|   for(size_t i = blocks; i != y_size; ++i) {
  ------------------
  |  Branch (108:27): [True: 97, False: 97]
  ------------------
  109|     97|      x[i] = word_add(x[i], y[i], &carry);
  110|     97|   }
  111|       |
  112|    679|   for(size_t i = y_size; i != x_size; ++i) {
  ------------------
  |  Branch (112:27): [True: 582, False: 97]
  ------------------
  113|    582|      x[i] = word_add(x[i], static_cast<W>(0), &carry);
  114|    582|   }
  115|       |
  116|     97|   return carry;
  117|     97|}
_ZN5Botan10bigint_cmpITkNS_8WordTypeEmEEiPKT_mS3_m:
  462|  51.6k|inline constexpr int32_t bigint_cmp(const W x[], size_t x_size, const W y[], size_t y_size) {
  463|  51.6k|   static_assert(sizeof(W) >= sizeof(uint32_t), "Size assumption");
  464|       |
  465|  51.6k|   const W LT = static_cast<W>(-1);
  466|  51.6k|   const W EQ = 0;
  467|  51.6k|   const W GT = 1;
  468|       |
  469|  51.6k|   const size_t common_elems = std::min(x_size, y_size);
  470|       |
  471|  51.6k|   W result = EQ;  // until found otherwise
  472|       |
  473|   149k|   for(size_t i = 0; i != common_elems; i++) {
  ------------------
  |  Branch (473:22): [True: 97.4k, False: 51.6k]
  ------------------
  474|  97.4k|      const auto is_eq = CT::Mask<W>::is_equal(x[i], y[i]);
  475|  97.4k|      const auto is_lt = CT::Mask<W>::is_lt(x[i], y[i]);
  476|       |
  477|  97.4k|      result = is_eq.select(result, is_lt.select(LT, GT));
  478|  97.4k|   }
  479|       |
  480|  51.6k|   if(x_size < y_size) {
  ------------------
  |  Branch (480:7): [True: 63, False: 51.6k]
  ------------------
  481|     63|      W mask = 0;
  482|    126|      for(size_t i = x_size; i != y_size; i++) {
  ------------------
  |  Branch (482:30): [True: 63, False: 63]
  ------------------
  483|     63|         mask |= y[i];
  484|     63|      }
  485|       |
  486|       |      // If any bits were set in high part of y, then x < y
  487|     63|      result = CT::Mask<W>::is_zero(mask).select(result, LT);
  488|  51.6k|   } else if(y_size < x_size) {
  ------------------
  |  Branch (488:14): [True: 1.21k, False: 50.4k]
  ------------------
  489|  1.21k|      W mask = 0;
  490|  5.32k|      for(size_t i = y_size; i != x_size; i++) {
  ------------------
  |  Branch (490:30): [True: 4.11k, False: 1.21k]
  ------------------
  491|  4.11k|         mask |= x[i];
  492|  4.11k|      }
  493|       |
  494|       |      // If any bits were set in high part of x, then x > y
  495|  1.21k|      result = CT::Mask<W>::is_zero(mask).select(result, GT);
  496|  1.21k|   }
  497|       |
  498|  51.6k|   CT::unpoison(result);
  499|  51.6k|   BOTAN_DEBUG_ASSERT(result == LT || result == GT || result == EQ);
  ------------------
  |  |  137|  51.6k|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|  51.6k|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 51.6k]
  |  |  ------------------
  ------------------
  500|  51.6k|   return static_cast<int32_t>(result);
  501|  51.6k|}
_ZN5Botan11bigint_sub2ITkNS_8WordTypeEmEET_PS1_mPKS1_m:
  151|  8.88k|inline constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W {
  152|  8.88k|   W borrow = 0;
  153|       |
  154|  8.88k|   BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
  ------------------
  |  |   71|  8.88k|   do {                                                                                 \
  |  |   72|  8.88k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|  8.88k|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 8.88k]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|  8.88k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 8.88k]
  |  |  ------------------
  ------------------
  155|       |
  156|  8.88k|   const size_t blocks = y_size - (y_size % 8);
  157|       |
  158|  8.88k|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (158:22): [True: 0, False: 8.88k]
  ------------------
  159|      0|      borrow = word8_sub2(x + i, y + i, borrow);
  160|      0|   }
  161|       |
  162|  59.5k|   for(size_t i = blocks; i != y_size; ++i) {
  ------------------
  |  Branch (162:27): [True: 50.6k, False: 8.88k]
  ------------------
  163|  50.6k|      x[i] = word_sub(x[i], y[i], &borrow);
  164|  50.6k|   }
  165|       |
  166|  10.4k|   for(size_t i = y_size; i != x_size; ++i) {
  ------------------
  |  Branch (166:27): [True: 1.58k, False: 8.88k]
  ------------------
  167|  1.58k|      x[i] = word_sub(x[i], static_cast<W>(0), &borrow);
  168|  1.58k|   }
  169|       |
  170|  8.88k|   return borrow;
  171|  8.88k|}
_ZN5Botan15bigint_sub2_revITkNS_8WordTypeEmEEvPT_PKS1_m:
  177|      2|inline constexpr void bigint_sub2_rev(W x[], const W y[], size_t y_size) {
  178|      2|   W borrow = 0;
  179|       |
  180|      4|   for(size_t i = 0; i != y_size; ++i) {
  ------------------
  |  Branch (180:22): [True: 2, False: 2]
  ------------------
  181|      2|      x[i] = word_sub(y[i], x[i], &borrow);
  182|      2|   }
  183|       |
  184|      2|   BOTAN_ASSERT(borrow == 0, "y must be greater than x");
  ------------------
  |  |   71|      2|   do {                                                                                 \
  |  |   72|      2|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|      2|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 2]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|      2|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 2]
  |  |  ------------------
  ------------------
  185|      2|}
_ZN5Botan11bigint_sub3ITkNS_8WordTypeEmEET_PS1_PKS1_mS4_m:
  195|  17.3k|inline constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W {
  196|  17.3k|   W borrow = 0;
  197|       |
  198|  17.3k|   BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
  ------------------
  |  |   71|  17.3k|   do {                                                                                 \
  |  |   72|  17.3k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|  17.3k|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 17.3k]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|  17.3k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 17.3k]
  |  |  ------------------
  ------------------
  199|       |
  200|  17.3k|   const size_t blocks = y_size - (y_size % 8);
  201|       |
  202|  17.3k|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (202:22): [True: 0, False: 17.3k]
  ------------------
  203|      0|      borrow = word8_sub3(z + i, x + i, y + i, borrow);
  204|      0|   }
  205|       |
  206|  84.8k|   for(size_t i = blocks; i != y_size; ++i) {
  ------------------
  |  Branch (206:27): [True: 67.5k, False: 17.3k]
  ------------------
  207|  67.5k|      z[i] = word_sub(x[i], y[i], &borrow);
  208|  67.5k|   }
  209|       |
  210|  35.8k|   for(size_t i = y_size; i != x_size; ++i) {
  ------------------
  |  Branch (210:27): [True: 18.4k, False: 17.3k]
  ------------------
  211|  18.4k|      z[i] = word_sub(x[i], static_cast<W>(0), &borrow);
  212|  18.4k|   }
  213|       |
  214|  17.3k|   return borrow;
  215|  17.3k|}
_ZN5Botan11bigint_add3ITkNS_8WordTypeEmEET_PS1_PKS1_mS4_m:
  123|  3.86k|inline constexpr auto bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W {
  124|  3.86k|   if(x_size < y_size) {
  ------------------
  |  Branch (124:7): [True: 43, False: 3.82k]
  ------------------
  125|     43|      return bigint_add3(z, y, y_size, x, x_size);
  126|     43|   }
  127|       |
  128|  3.82k|   W carry = 0;
  129|       |
  130|  3.82k|   const size_t blocks = y_size - (y_size % 8);
  131|       |
  132|  3.82k|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (132:22): [True: 0, False: 3.82k]
  ------------------
  133|      0|      carry = word8_add3(z + i, x + i, y + i, carry);
  134|      0|   }
  135|       |
  136|  17.5k|   for(size_t i = blocks; i != y_size; ++i) {
  ------------------
  |  Branch (136:27): [True: 13.7k, False: 3.82k]
  ------------------
  137|  13.7k|      z[i] = word_add(x[i], y[i], &carry);
  138|  13.7k|   }
  139|       |
  140|  5.34k|   for(size_t i = y_size; i != x_size; ++i) {
  ------------------
  |  Branch (140:27): [True: 1.52k, False: 3.82k]
  ------------------
  141|  1.52k|      z[i] = word_add(x[i], static_cast<W>(0), &carry);
  142|  1.52k|   }
  143|       |
  144|  3.82k|   return carry;
  145|  3.86k|}
_ZN5Botan14bigint_cnd_addITkNS_8WordTypeEmEET_S1_PS1_PKS1_m:
   48|  9.78k|inline constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size) {
   49|  9.78k|   const auto mask = CT::Mask<W>::expand(cnd).value();
   50|       |
   51|  9.78k|   W carry = 0;
   52|       |
   53|  38.8k|   for(size_t i = 0; i != size; ++i) {
  ------------------
  |  Branch (53:22): [True: 29.1k, False: 9.78k]
  ------------------
   54|  29.1k|      x[i] = word_add(x[i], y[i] & mask, &carry);
   55|  29.1k|   }
   56|       |
   57|  9.78k|   return (mask & carry);
   58|  9.78k|}
_ZN5Botan14divide_precompImE13setup_vartimeEm:
  686|  16.1k|      static constexpr divide_precomp setup_vartime(W divisor) {
  687|  16.1k|         const size_t shift = WordInfo<W>::bits - high_bit(divisor);
  688|  16.1k|         const W norm_divisor = divisor << shift;
  689|  16.1k|         const W reciprocal = reciprocal_word(norm_divisor);
  690|  16.1k|         return divide_precomp(divisor, shift, norm_divisor, reciprocal);
  691|  16.1k|      }
_ZN5Botan15reciprocal_wordITkNS_8WordTypeEmEET_S1_:
  577|  16.1k|constexpr W reciprocal_word(W D) {
  578|  16.1k|   BOTAN_DEBUG_ASSERT((D & WordInfo<W>::top_bit) != 0);
  ------------------
  |  |  137|  16.1k|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|  16.1k|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 16.1k]
  |  |  ------------------
  ------------------
  579|       |
  580|       |   /*
  581|       |   * Subtracting 2^b*D from the numerator gives
  582|       |   * v = floor(((~D)*2^b + (2^b - 1)) / D). Since D is normalized, ~D < D
  583|       |   * and the quotient fits in a word. See the first part of Section III A
  584|       |   * in the paper.
  585|       |   */
  586|       |   if constexpr(sizeof(W) == 4) {
  587|       |      const auto nD = ~D;  // Work around spurious MSVC warning
  588|       |      const typename WordInfo<W>::dword n =
  589|       |         (static_cast<typename WordInfo<W>::dword>(nD) << WordInfo<W>::bits) | WordInfo<W>::max;
  590|       |      return static_cast<W>(n / D);
  591|  16.1k|   } else {
  592|  16.1k|      if(!std::is_constant_evaluated()) {
  ------------------
  |  Branch (592:10): [True: 16.1k, Folded]
  ------------------
  593|  16.1k|#if defined(BOTAN_MP_USE_X86_64_ASM)
  594|  16.1k|         W quotient = 0;
  595|  16.1k|         W remainder = 0;
  596|       |         // NOLINTNEXTLINE(*-no-assembler)
  597|  16.1k|         asm("divq %[d]"
  598|  16.1k|             : "=a"(quotient), "=d"(remainder)
  599|  16.1k|             : [d] "r"(D), "a"(WordInfo<W>::max), "d"(static_cast<W>(~D))
  600|  16.1k|             : "cc");
  601|  16.1k|         return quotient;
  602|       |#elif !defined(BOTAN_BUILD_COMPILER_IS_CLANGCL)
  603|       |         /* clang-cl has a bug where on encountering a 128/64 division it emits
  604|       |         * a call to __udivti3() but then fails to link the relevant builtin into
  605|       |         * the binary, causing a link failure. Work around this by simply omitting
  606|       |         * such code for clang-cl
  607|       |         *
  608|       |         * See https://github.com/llvm/llvm-project/issues/25679
  609|       |         */
  610|       |         if constexpr(WordInfo<W>::dword_is_native) {
  611|       |            typename WordInfo<W>::dword n =
  612|       |               (static_cast<typename WordInfo<W>::dword>(~D) << WordInfo<W>::bits) | WordInfo<W>::max;
  613|       |            return static_cast<W>(n / D);
  614|       |         }
  615|       |#endif
  616|  16.1k|      }
  617|       |
  618|       |      // Algorithm 2 of Möller and Granlund
  619|      0|      const W d0 = D & 1;
  620|      0|      const W d9 = D >> 55;
  621|      0|      const W d40 = (D >> 24) + 1;
  622|      0|      const W d63 = (D >> 1) + d0;  // ceil(D/2)
  623|       |
  624|       |      // This division is done with a table lookup in the paper
  625|      0|      const W v0 = ((W(1) << 19) - (W(3) << 8)) / d9;
  626|      0|      const W v1 = (v0 << 11) - ((v0 * v0 * d40) >> 40) - 1;
  627|      0|      const W v2 = (v1 << 13) + ((v1 * ((W(1) << 60) - v1 * d40)) >> 47);
  628|       |
  629|      0|      const W e = W(0) - v2 * d63 + (v2 >> 1) * d0;
  630|       |
  631|      0|      W product_hi = 0;
  632|      0|      word_madd2(v2, e, &product_hi);
  633|      0|      const W v3 = (v2 << 31) + (product_hi >> 1);
  634|       |
  635|       |      // Compute floor((v3 + 2^64 + 1) * D / 2^64) modulo 2^64
  636|      0|      product_hi = D;
  637|      0|      word_madd2(v3, D, &product_hi);
  638|      0|      return v3 - D - product_hi;
  639|  16.1k|   }
  640|  16.1k|}
_ZN5Botan14divide_precompImEC2Emmmm:
  771|  21.8k|            m_divisor(divisor), m_shift(shift), m_norm_divisor(norm_divisor), m_reciprocal(reciprocal) {}
_ZNK5Botan14divide_precompImE8mod_2to1Emm:
  767|  19.4k|      inline constexpr W mod_2to1(W n1, W n0) const { return this->divmod_2to1_vartime(n1, n0).second; }
_ZNK5Botan14divide_precompImE19divmod_2to1_vartimeEmm:
  709|  19.4k|      inline constexpr std::pair<W, W> divmod_2to1_vartime(W n1, W n0) const {
  710|  19.4k|         if(m_divisor == WordInfo<W>::max) {
  ------------------
  |  Branch (710:13): [True: 4, False: 19.4k]
  ------------------
  711|      4|            const W q = div_2to1_max_d(n1, n0);
  712|      4|            const W r = static_cast<W>(n0 + q);
  713|      4|            return std::make_pair(q, r);
  714|      4|         }
  715|       |
  716|  19.4k|         if(m_divisor == WordInfo<W>::top_bit) {
  ------------------
  |  Branch (716:13): [True: 0, False: 19.4k]
  ------------------
  717|       |            // Simply a shift by N-1 bits
  718|      0|            const W q = (n1 << 1) | (n0 >> (WordInfo<W>::bits - 1));
  719|      0|            const W r = static_cast<W>(n0 & (WordInfo<W>::top_bit - 1));
  720|      0|            return std::make_pair(q, r);
  721|      0|         }
  722|       |
  723|  19.4k|         return divmod_2to1_ct(n1, n0);
  724|  19.4k|      }
_ZN5Botan14divide_precompImE14div_2to1_max_dEmm:
  809|      4|      static inline constexpr W div_2to1_max_d(W n1, W n0) {
  810|       |         /*
  811|       |         Use k to refer to WordInfo<W>::bits
  812|       |
  813|       |         We are dividing n = (n1 * 2^k) + n0 by 2^k - 1
  814|       |
  815|       |         Recall that 2^k = 1 (mod 2^k - 1)
  816|       |
  817|       |         Rewrite n = n1*2^k + n0 as n1*(2^k - 1) + n1 + n0
  818|       |
  819|       |         The result of dividing n by (2^k - 1) will be equal to
  820|       |         (n1*(2^k-1) + n1 + n0) / (2^k-1) =
  821|       |         n1 + ((n1 + n0) / (2^k-1)
  822|       |
  823|       |         Use c to refer to ((n1 + n0) / (2^k-1))
  824|       |
  825|       |         If (n1 + n0) < (2^k - 1) then c is 0
  826|       |         If (n1 + n0) >= (2^k - 1) then c is 1
  827|       |
  828|       |         Since n1 < 2^k - 1 [*] and n0 <= 2^k - 1 it is impossible for (n1 + n0) / (2^k -1)
  829|       |         to be greater than 1.
  830|       |
  831|       |         [*] We require n1 be strictly less than the divisor to ensure that the
  832|       |         output fits in a single word; this is checked at the start of divmod_2to1.
  833|       |
  834|       |         And since n1 + 1 <= 2^k - 1, c == 1 exactly when n0 + (n1 + 1) carries out.
  835|       |         */
  836|       |
  837|      4|         const W s = n0 + n1 + 1;
  838|      4|         const W c = CT::Mask<W>::is_lt(s, n0).if_set_return(1);
  839|      4|         return n1 + c;
  840|      4|      }
_ZN5Botan11bigint_shr1ITkNS_8WordTypeEmEEvPT_mm:
  334|  23.2k|inline constexpr void bigint_shr1(W x[], size_t x_size, size_t shift) {
  335|  23.2k|   const size_t word_shift = shift / WordInfo<W>::bits;
  336|  23.2k|   const size_t bit_shift = shift % WordInfo<W>::bits;
  337|       |
  338|  23.2k|   const size_t top = x_size >= word_shift ? (x_size - word_shift) : 0;
  ------------------
  |  Branch (338:23): [True: 23.2k, False: 0]
  ------------------
  339|       |
  340|  23.2k|   if(top > 0) {
  ------------------
  |  Branch (340:7): [True: 23.2k, False: 0]
  ------------------
  341|  23.2k|      unchecked_copy_memory(x, x + word_shift, top);
  342|  23.2k|   }
  343|  23.2k|   zeroize_buffer(x + top, std::min(word_shift, x_size));
  344|       |
  345|  23.2k|   const auto carry_mask = CT::Mask<W>::expand(bit_shift);
  346|  23.2k|   const W carry_shift = carry_mask.if_set_return(WordInfo<W>::bits - bit_shift);
  347|       |
  348|  23.2k|   W carry = 0;
  349|       |
  350|   180k|   for(size_t i = 0; i != top; ++i) {
  ------------------
  |  Branch (350:22): [True: 156k, False: 23.2k]
  ------------------
  351|   156k|      const W w = x[top - i - 1];
  352|   156k|      x[top - i - 1] = (w >> bit_shift) | carry;
  353|   156k|      carry = carry_mask.if_set_return(w << carry_shift);
  354|   156k|   }
  355|  23.2k|}
_ZN5Botan11bigint_shl2ITkNS_8WordTypeEmEEvPT_mPKS1_mm:
  358|    463|inline constexpr void bigint_shl2(W y[], size_t y_size, const W x[], size_t x_size, size_t shift) {
  359|    463|   const size_t word_shift = shift / WordInfo<W>::bits;
  360|    463|   const size_t bit_shift = shift % WordInfo<W>::bits;
  361|       |
  362|    463|   BOTAN_ASSERT_NOMSG(word_shift <= y_size);
  ------------------
  |  |   84|    463|   do {                                                                     \
  |  |   85|    463|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    463|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 463]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    463|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 463]
  |  |  ------------------
  ------------------
  363|    463|   BOTAN_ASSERT_NOMSG(x_size < y_size - word_shift);
  ------------------
  |  |   84|    463|   do {                                                                     \
  |  |   85|    463|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    463|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 463]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    463|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 463]
  |  |  ------------------
  ------------------
  364|       |
  365|    463|   unchecked_copy_memory(y + word_shift, x, x_size);
  366|    463|   zeroize_buffer(y, word_shift);
  367|    463|   zeroize_buffer(y + word_shift + x_size, y_size - word_shift - x_size);
  368|       |
  369|    463|   const auto carry_mask = CT::Mask<W>::expand(bit_shift);
  370|    463|   const W carry_shift = carry_mask.if_set_return(WordInfo<W>::bits - bit_shift);
  371|       |
  372|    463|   W carry = 0;
  373|  2.77k|   for(size_t i = word_shift; i != x_size + word_shift + 1; ++i) {
  ------------------
  |  Branch (373:31): [True: 2.31k, False: 463]
  ------------------
  374|  2.31k|      const W w = y[i];
  375|  2.31k|      y[i] = (w << bit_shift) | carry;
  376|  2.31k|      carry = carry_mask.if_set_return(w >> carry_shift);
  377|  2.31k|   }
  378|    463|}
_ZN5Botan11bigint_shr2ITkNS_8WordTypeEmEEvPT_mPKS1_mm:
  381|    544|inline constexpr void bigint_shr2(W y[], size_t y_size, const W x[], size_t x_size, size_t shift) {
  382|    544|   const size_t word_shift = shift / WordInfo<W>::bits;
  383|    544|   const size_t bit_shift = shift % WordInfo<W>::bits;
  384|    544|   const size_t new_size = x_size < word_shift ? 0 : (x_size - word_shift);
  ------------------
  |  Branch (384:28): [True: 0, False: 544]
  ------------------
  385|       |
  386|    544|   BOTAN_ASSERT_NOMSG(new_size <= y_size);
  ------------------
  |  |   84|    544|   do {                                                                     \
  |  |   85|    544|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    544|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 544]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    544|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 544]
  |  |  ------------------
  ------------------
  387|       |
  388|    544|   if(new_size > 0) {
  ------------------
  |  Branch (388:7): [True: 544, False: 0]
  ------------------
  389|    544|      unchecked_copy_memory(y, x + word_shift, new_size);
  390|    544|   }
  391|    544|   zeroize_buffer(y + new_size, y_size - new_size);
  392|       |
  393|    544|   const auto carry_mask = CT::Mask<W>::expand(bit_shift);
  394|    544|   const W carry_shift = carry_mask.if_set_return(WordInfo<W>::bits - bit_shift);
  395|       |
  396|    544|   W carry = 0;
  397|  2.72k|   for(size_t i = new_size; i > 0; --i) {
  ------------------
  |  Branch (397:29): [True: 2.17k, False: 544]
  ------------------
  398|  2.17k|      W w = y[i - 1];
  399|  2.17k|      y[i - 1] = (w >> bit_shift) | carry;
  400|  2.17k|      carry = carry_mask.if_set_return(w << carry_shift);
  401|  2.17k|   }
  402|    544|}
_ZN5Botan15bigint_ct_is_eqITkNS_8WordTypeEmEENS_2CT4MaskIT_EEPKS3_mS6_m:
  542|    530|inline constexpr auto bigint_ct_is_eq(const W x[], size_t x_size, const W y[], size_t y_size) -> CT::Mask<W> {
  543|    530|   const size_t common_elems = std::min(x_size, y_size);
  544|       |
  545|    530|   W diff = 0;
  546|       |
  547|  6.89k|   for(size_t i = 0; i != common_elems; i++) {
  ------------------
  |  Branch (547:22): [True: 6.36k, False: 530]
  ------------------
  548|  6.36k|      diff |= (x[i] ^ y[i]);
  549|  6.36k|   }
  550|       |
  551|       |   // If any bits were set in high part of x/y, then they are not equal
  552|    530|   if(x_size < y_size) {
  ------------------
  |  Branch (552:7): [True: 0, False: 530]
  ------------------
  553|      0|      for(size_t i = x_size; i != y_size; i++) {
  ------------------
  |  Branch (553:30): [True: 0, False: 0]
  ------------------
  554|      0|         diff |= y[i];
  555|      0|      }
  556|    530|   } else if(y_size < x_size) {
  ------------------
  |  Branch (556:14): [True: 0, False: 530]
  ------------------
  557|      0|      for(size_t i = y_size; i != x_size; i++) {
  ------------------
  |  Branch (557:30): [True: 0, False: 0]
  ------------------
  558|      0|         diff |= x[i];
  559|      0|      }
  560|      0|   }
  561|       |
  562|    530|   return CT::Mask<W>::is_zero(diff);
  563|    530|}
_ZN5Botan15bigint_ct_is_ltITkNS_8WordTypeEmEENS_2CT4MaskIT_EEPKS3_mS6_mb:
  510|  37.8k|   -> CT::Mask<W> {
  511|  37.8k|   const size_t common_elems = std::min(x_size, y_size);
  512|       |
  513|  37.8k|   auto is_lt = CT::Mask<W>::expand(lt_or_equal);
  514|       |
  515|   267k|   for(size_t i = 0; i != common_elems; i++) {
  ------------------
  |  Branch (515:22): [True: 229k, False: 37.8k]
  ------------------
  516|   229k|      const auto eq = CT::Mask<W>::is_equal(x[i], y[i]);
  517|   229k|      const auto lt = CT::Mask<W>::is_lt(x[i], y[i]);
  518|   229k|      is_lt = eq.select_mask(is_lt, lt);
  519|   229k|   }
  520|       |
  521|  37.8k|   if(x_size < y_size) {
  ------------------
  |  Branch (521:7): [True: 333, False: 37.5k]
  ------------------
  522|    333|      W mask = 0;
  523|  2.32k|      for(size_t i = x_size; i != y_size; i++) {
  ------------------
  |  Branch (523:30): [True: 1.99k, False: 333]
  ------------------
  524|  1.99k|         mask |= y[i];
  525|  1.99k|      }
  526|       |      // If any bits were set in high part of y, then is_lt should be forced true
  527|    333|      is_lt |= CT::Mask<W>::expand(mask);
  528|  37.5k|   } else if(y_size < x_size) {
  ------------------
  |  Branch (528:14): [True: 13.4k, False: 24.1k]
  ------------------
  529|  13.4k|      W mask = 0;
  530|  94.7k|      for(size_t i = y_size; i != x_size; i++) {
  ------------------
  |  Branch (530:30): [True: 81.3k, False: 13.4k]
  ------------------
  531|  81.3k|         mask |= x[i];
  532|  81.3k|      }
  533|       |
  534|       |      // If any bits were set in high part of x, then is_lt should be false
  535|  13.4k|      is_lt &= CT::Mask<W>::is_zero(mask);
  536|  13.4k|   }
  537|       |
  538|  37.8k|   return is_lt;
  539|  37.8k|}
_ZN5Botan13bigint_submulITkNS_8WordTypeEmEET_PS1_PKS1_mS1_:
  442|  9.02k|inline constexpr auto bigint_submul(W z[], const W y[], size_t N, W q) -> W {
  443|  9.02k|   W mul_carry = 0;
  444|  9.02k|   W borrow = 0;
  445|       |
  446|  35.0k|   for(size_t i = 0; i != N; ++i) {
  ------------------
  |  Branch (446:22): [True: 26.0k, False: 9.02k]
  ------------------
  447|  26.0k|      const W t = word_madd2(y[i], q, &mul_carry);
  448|  26.0k|      z[i] = word_sub(z[i], t, &borrow);
  449|  26.0k|   }
  450|       |
  451|       |   // Both mul_carry <= W_max - 1 and borrow <= 1, so this cannot overflow
  452|  9.02k|   return mul_carry + borrow;
  453|  9.02k|}
_ZN5Botan14bigint_sub_absITkNS_8WordTypeEmEENS_2CT4MaskIT_EEPS3_PKS3_S7_mS5_:
  282|  8.35k|inline constexpr auto bigint_sub_abs(W z[], const W x[], const W y[], size_t N, W ws[]) -> CT::Mask<W> {
  283|       |   // Subtract in both direction then conditional copy out the result
  284|       |
  285|  8.35k|   W* ws0 = ws;
  286|  8.35k|   W* ws1 = ws + N;
  287|       |
  288|  8.35k|   W borrow0 = 0;
  289|  8.35k|   W borrow1 = 0;
  290|       |
  291|  8.35k|   const size_t blocks = N - (N % 8);
  292|       |
  293|  8.35k|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (293:22): [True: 0, False: 8.35k]
  ------------------
  294|      0|      borrow0 = word8_sub3(ws0 + i, x + i, y + i, borrow0);
  295|      0|      borrow1 = word8_sub3(ws1 + i, y + i, x + i, borrow1);
  296|      0|   }
  297|       |
  298|  50.1k|   for(size_t i = blocks; i != N; ++i) {
  ------------------
  |  Branch (298:27): [True: 41.7k, False: 8.35k]
  ------------------
  299|  41.7k|      ws0[i] = word_sub(x[i], y[i], &borrow0);
  300|  41.7k|      ws1[i] = word_sub(y[i], x[i], &borrow1);
  301|  41.7k|   }
  302|       |
  303|  8.35k|   return CT::conditional_copy_mem(borrow0, z, ws1, ws0, N);
  304|  8.35k|}
_ZN5Botan13monty_inverseITkNS_8WordTypeEmEET_S1_:
  856|    544|inline constexpr auto monty_inverse(W a) -> W {
  857|    544|   BOTAN_ARG_CHECK(a % 2 == 1, "Cannot compute Montgomery inverse of an even integer");
  ------------------
  |  |   35|    544|   do {                                                          \
  |  |   36|    544|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    544|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 544]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    544|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 544]
  |  |  ------------------
  ------------------
  858|       |
  859|       |   // Newton's Method, following https://lemire.me/blog/2017/09/18/computing-the-inverse-of-odd-integers/
  860|       |
  861|    544|   constexpr size_t iter = WordInfo<W>::bits == 64 ? 4 : 3;
  ------------------
  |  Branch (861:28): [True: 0, Folded]
  ------------------
  862|       |
  863|       |   // Initial guess provides 5 bits of accuracy
  864|    544|   W r = (3 * a) ^ 2;
  865|       |
  866|       |   // Each iteration doubles the accuracy
  867|  2.72k|   for(size_t i = 0; i != iter; ++i) {
  ------------------
  |  Branch (867:22): [True: 2.17k, False: 544]
  ------------------
  868|  2.17k|      r = r * (2 - r * a);
  869|  2.17k|   }
  870|       |
  871|       |   // Now invert in addition space
  872|    544|   r = (WordInfo<W>::max - r) + 1;
  873|       |
  874|    544|   return r;
  875|    544|}
_ZN5Botan22bigint_monty_maybe_subITkNS_8WordTypeEmEEvmPT_S1_PKS1_S4_:
  228|  3.31k|inline constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[]) {
  229|  3.31k|   W borrow = 0;
  230|       |
  231|  3.31k|   const size_t blocks = N - (N % 8);
  232|       |
  233|  3.31k|   for(size_t i = 0; i != blocks; i += 8) {
  ------------------
  |  Branch (233:22): [True: 0, False: 3.31k]
  ------------------
  234|      0|      borrow = word8_sub3(z + i, x + i, p + i, borrow);
  235|      0|   }
  236|       |
  237|  16.5k|   for(size_t i = blocks; i != N; ++i) {
  ------------------
  |  Branch (237:27): [True: 13.2k, False: 3.31k]
  ------------------
  238|  13.2k|      z[i] = word_sub(x[i], p[i], &borrow);
  239|  13.2k|   }
  240|       |
  241|  3.31k|   borrow = (x0 - borrow) > x0;
  242|       |
  243|  3.31k|   CT::conditional_assign_mem(borrow, z, x, N);
  244|  3.31k|}
_ZN5Botan22bigint_monty_maybe_subILm4ETkNS_8WordTypeEmEEvPT0_S1_PKS1_S4_:
  257|   347k|inline constexpr void bigint_monty_maybe_sub(W z[N], W x0, const W x[N], const W y[N]) {
  258|   347k|   W borrow = 0;
  259|       |
  260|  1.73M|   for(size_t i = 0; i != N; ++i) {
  ------------------
  |  Branch (260:22): [True: 1.38M, False: 347k]
  ------------------
  261|  1.38M|      z[i] = word_sub(x[i], y[i], &borrow);
  262|  1.38M|   }
  263|       |
  264|   347k|   borrow = (x0 - borrow) > x0;
  265|       |
  266|   347k|   CT::conditional_assign_mem(borrow, z, x, N);
  267|   347k|}

_ZN5Botan14use_mulx_montyEm:
   33|   345k|inline bool use_mulx_monty(size_t p_size) {
   34|   345k|   return p_size >= MulxMontyMinWords && CPUID::has(CPUID::Feature::BMI, CPUID::Feature::ADX);
  ------------------
  |  Branch (34:11): [True: 0, False: 345k]
  |  Branch (34:42): [True: 0, False: 0]
  ------------------
   35|   345k|}

_ZNK5Botan7SHA_25613output_lengthEv:
   75|      9|      size_t output_length() const override { return output_bytes; }
_ZNK5Botan7SHA_25615hash_block_sizeEv:
   77|      1|      size_t hash_block_size() const override { return block_bytes; }
_ZN5Botan7SHA_2565clearEv:
   83|      2|      void clear() override { m_md.clear(); }

_ZNK5Botan9SIMD_4x323rawEv:
  964|  2.06k|      native_simd_type BOTAN_FN_ISA_SIMD_4X32 raw() const noexcept { return m_simd; }
_ZN5Botan9SIMD_4x32C2EDv2_x:
  966|  1.20k|      explicit BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32(native_simd_type x) noexcept : m_simd(x) {}
_ZN5Botan9SIMD_4x327load_leEPKv:
  183|    180|      static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_le(const void* in) noexcept {
  184|    180|         if constexpr(std::endian::native == std::endian::little) {
  185|    180|            return SIMD_4x32::load_native(in);
  186|       |         } else {
  187|       |            return SIMD_4x32::load_native(in).bswap();
  188|       |         }
  189|    180|      }
_ZN5Botan9SIMD_4x3211load_nativeEPKv:
  166|    220|      static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_native(const void* in) noexcept {
  167|    220|#if defined(BOTAN_SIMD_USE_SSSE3)
  168|    220|         return SIMD_4x32(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
  169|       |#elif defined(BOTAN_SIMD_USE_VSX)
  170|       |         return SIMD_4x32(reinterpret_cast<native_simd_type>(vec_xl(0, static_cast<const unsigned char*>(in))));
  171|       |#elif defined(BOTAN_SIMD_USE_NEON)
  172|       |         return SIMD_4x32(vld1q_u32(static_cast<const uint32_t*>(in)));
  173|       |#elif defined(BOTAN_SIMD_USE_LSX)
  174|       |         return SIMD_4x32(__lsx_vld(in, 0));
  175|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  176|       |         return SIMD_4x32(wasm_v128_load(in));
  177|       |#endif
  178|    220|      }
_ZNK5Botan9SIMD_4x328store_leEPh:
  242|     20|      void BOTAN_FN_ISA_SIMD_4X32 store_le(uint8_t out[]) const noexcept {
  243|     20|         if constexpr(std::endian::native == std::endian::little) {
  244|     20|            this->store_native(out);
  245|       |         } else {
  246|       |            this->bswap().store_native(out);
  247|       |         }
  248|     20|      }
_ZNK5Botan9SIMD_4x3212store_nativeEPv:
  225|     20|      void BOTAN_FN_ISA_SIMD_4X32 store_native(void* out) const noexcept {
  226|     20|#if defined(BOTAN_SIMD_USE_SSSE3)
  227|     20|         _mm_storeu_si128(static_cast<__m128i*>(out), raw());
  228|       |#elif defined(BOTAN_SIMD_USE_VSX)
  229|       |         vec_xst(reinterpret_cast<__vector unsigned char>(m_simd), 0, static_cast<unsigned char*>(out));
  230|       |#elif defined(BOTAN_SIMD_USE_NEON)
  231|       |         vst1q_u32(static_cast<uint32_t*>(out), m_simd);
  232|       |#elif defined(BOTAN_SIMD_USE_LSX)
  233|       |         __lsx_vst(raw(), out, 0);
  234|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  235|       |         wasm_v128_store(out, m_simd);
  236|       |#endif
  237|     20|      }
_ZN5Botan9SIMD_4x327load_beEPKv:
  194|     40|      static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_be(const void* in) noexcept {
  195|       |         if constexpr(std::endian::native == std::endian::big) {
  196|       |            return SIMD_4x32::load_native(in);
  197|     40|         } else {
  198|     40|            return SIMD_4x32::load_native(in).bswap();
  199|     40|         }
  200|     40|      }
_ZNK5Botan9SIMD_4x328store_leEPj:
  210|     20|      void BOTAN_FN_ISA_SIMD_4X32 store_le(uint32_t out[4]) const noexcept {
  211|     20|         this->store_le(reinterpret_cast<uint8_t*>(out));
  212|     20|      }
_ZNK5Botan9SIMD_4x32plERKS0_:
  352|    160|      SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 operator+(const SIMD_4x32& other) const noexcept {
  353|    160|         SIMD_4x32 retval(*this);
  354|    160|         retval += other;
  355|    160|         return retval;
  356|    160|      }
_ZN5Botan9SIMD_4x32pLERKS0_:
  394|    300|      void BOTAN_FN_ISA_SIMD_4X32 operator+=(const SIMD_4x32& other) noexcept {
  395|    300|#if defined(BOTAN_SIMD_USE_SSSE3)
  396|    300|         m_simd = _mm_add_epi32(m_simd, other.m_simd);
  397|       |#elif defined(BOTAN_SIMD_USE_VSX)
  398|       |         m_simd = vec_add(m_simd, other.m_simd);
  399|       |#elif defined(BOTAN_SIMD_USE_NEON)
  400|       |         m_simd = vaddq_u32(m_simd, other.m_simd);
  401|       |#elif defined(BOTAN_SIMD_USE_LSX)
  402|       |         m_simd = __lsx_vadd_w(m_simd, other.m_simd);
  403|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  404|       |         m_simd = wasm_i32x4_add(m_simd, other.m_simd);
  405|       |#endif
  406|    300|      }
_ZNK5Botan9SIMD_4x325bswapEv:
  544|     40|      BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 bswap() const noexcept {
  545|     40|#if defined(BOTAN_SIMD_USE_SSSE3)
  546|     40|         const auto idx = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
  547|       |
  548|     40|         return SIMD_4x32(_mm_shuffle_epi8(raw(), idx));
  549|       |#elif defined(BOTAN_SIMD_USE_VSX)
  550|       |         return SIMD_4x32(vec_revb(m_simd));
  551|       |
  552|       |#elif defined(BOTAN_SIMD_USE_NEON)
  553|       |         return SIMD_4x32(vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(m_simd))));
  554|       |#elif defined(BOTAN_SIMD_USE_LSX)
  555|       |         return SIMD_4x32(__lsx_vshuf4i_b(m_simd, 0b00011011));
  556|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  557|       |         return SIMD_4x32(wasm_i8x16_shuffle(m_simd, m_simd, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12));
  558|       |#endif
  559|     40|      }
_ZN5Botan9SIMD_4x327alignr4ERKS0_S2_:
  865|    120|      static inline SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 alignr4(const SIMD_4x32& a, const SIMD_4x32& b) {
  866|    120|#if defined(BOTAN_SIMD_USE_SSSE3)
  867|    120|         return SIMD_4x32(_mm_alignr_epi8(a.raw(), b.raw(), 4));
  868|       |#elif defined(BOTAN_SIMD_USE_NEON)
  869|       |         return SIMD_4x32(vextq_u32(b.raw(), a.raw(), 1));
  870|       |#elif defined(BOTAN_SIMD_USE_VSX)
  871|       |         const __vector unsigned char mask = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
  872|       |         return SIMD_4x32(vec_perm(b.raw(), a.raw(), mask));
  873|       |#elif defined(BOTAN_SIMD_USE_LSX)
  874|       |         const auto mask = SIMD_4x32(0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x13121110);
  875|       |         return SIMD_4x32(__lsx_vshuf_b(a.raw(), b.raw(), mask.raw()));
  876|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  877|       |         return SIMD_4x32(
  878|       |            wasm_i8x16_shuffle(b.raw(), a.raw(), 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19));
  879|       |#endif
  880|    120|      }
_ZN5Botan9SIMD_4x327alignr8ERKS0_S2_:
  882|     20|      static inline SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 alignr8(const SIMD_4x32& a, const SIMD_4x32& b) {
  883|     20|#if defined(BOTAN_SIMD_USE_SSSE3)
  884|     20|         return SIMD_4x32(_mm_alignr_epi8(a.raw(), b.raw(), 8));
  885|       |#elif defined(BOTAN_SIMD_USE_NEON)
  886|       |         return SIMD_4x32(vextq_u32(b.raw(), a.raw(), 2));
  887|       |#elif defined(BOTAN_SIMD_USE_VSX)
  888|       |         const __vector unsigned char mask = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
  889|       |         return SIMD_4x32(vec_perm(b.raw(), a.raw(), mask));
  890|       |#elif defined(BOTAN_SIMD_USE_LSX)
  891|       |         return SIMD_4x32(__lsx_vshuf4i_d(a.raw(), b.raw(), 0b0011));
  892|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  893|       |         return SIMD_4x32(
  894|       |            wasm_i8x16_shuffle(b.raw(), a.raw(), 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23));
  895|       |#endif
  896|     20|      }
_ZNK5Botan9SIMD_4x3217shift_elems_rightILm2EEES0_vQleT_Li3E:
  601|    160|      {
  602|    160|#if defined(BOTAN_SIMD_USE_SSSE3)
  603|    160|         return SIMD_4x32(_mm_srli_si128(raw(), 4 * I));
  604|       |#elif defined(BOTAN_SIMD_USE_NEON)
  605|       |         return SIMD_4x32(vextq_u32(raw(), vdupq_n_u32(0), I));
  606|       |#elif defined(BOTAN_SIMD_USE_VSX)
  607|       |         const __vector unsigned int zero = vec_splat_u32(0);
  608|       |
  609|       |         const __vector unsigned char shuf[3] = {
  610|       |            {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
  611|       |            {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
  612|       |            {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
  613|       |         };
  614|       |
  615|       |         return SIMD_4x32(vec_perm(raw(), zero, shuf[I - 1]));
  616|       |#elif defined(BOTAN_SIMD_USE_LSX)
  617|       |         return SIMD_4x32(__lsx_vbsrl_v(raw(), 4 * I));
  618|       |#elif defined(BOTAN_SIMD_USE_SIMD128)
  619|       |         if constexpr(I == 0) {
  620|       |            return SIMD_4x32(m_simd);
  621|       |         }
  622|       |
  623|       |         const auto zero = wasm_u32x4_const_splat(0);
  624|       |         if constexpr(I == 1) {
  625|       |            return SIMD_4x32(
  626|       |               wasm_i8x16_shuffle(m_simd, zero, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16));
  627|       |         }
  628|       |         if constexpr(I == 2) {
  629|       |            return SIMD_4x32(
  630|       |               wasm_i8x16_shuffle(m_simd, zero, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16));
  631|       |         }
  632|       |
  633|       |         return SIMD_4x32(
  634|       |            wasm_i8x16_shuffle(m_simd, zero, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16));
  635|       |#endif
  636|    160|      }

_ZN5Botan9SIMD_8x32C2Ejjjjjjjj:
   46|      5|                         uint32_t B7) noexcept {
   47|       |         // NOLINTNEXTLINE(*-prefer-member-initializer)
   48|      5|         m_avx2 = _mm256_set_epi32(B7, B6, B5, B4, B3, B2, B1, B0);
   49|      5|      }
_ZN5Botan9SIMD_8x325splatEj:
   58|    155|      static SIMD_8x32 splat(uint32_t B) noexcept { return SIMD_8x32(_mm256_set1_epi32(B)); }
_ZNK5Botan9SIMD_8x328store_leEPh:
   94|     80|      void store_le(uint8_t out[]) const noexcept { _mm256_storeu_si256(reinterpret_cast<__m256i*>(out), m_avx2); }
_ZNK5Botan9SIMD_8x32plERKS0_:
  174|      5|      SIMD_8x32 operator+(const SIMD_8x32& other) const noexcept {
  175|      5|         SIMD_8x32 retval(*this);
  176|      5|         retval += other;
  177|      5|         return retval;
  178|      5|      }
_ZNK5Botan9SIMD_8x32miERKS0_:
  181|      5|      SIMD_8x32 operator-(const SIMD_8x32& other) const noexcept {
  182|      5|         SIMD_8x32 retval(*this);
  183|      5|         retval -= other;
  184|      5|         return retval;
  185|      5|      }
_ZN5Botan9SIMD_8x32pLERKS0_:
  209|  1.68k|      void operator+=(const SIMD_8x32& other) { m_avx2 = _mm256_add_epi32(m_avx2, other.m_avx2); }
_ZN5Botan9SIMD_8x32mIERKS0_:
  212|      5|      void operator-=(const SIMD_8x32& other) { m_avx2 = _mm256_sub_epi32(m_avx2, other.m_avx2); }
_ZN5Botan9SIMD_8x32eOERKS0_:
  215|  1.60k|      void operator^=(const SIMD_8x32& other) { m_avx2 = _mm256_xor_si256(m_avx2, other.m_avx2); }
_ZN5Botan9SIMD_8x329transposeERS0_S1_S1_S1_:
  274|     20|      static void transpose(SIMD_8x32& B0, SIMD_8x32& B1, SIMD_8x32& B2, SIMD_8x32& B3) noexcept {
  275|     20|         const __m256i T0 = _mm256_unpacklo_epi32(B0.m_avx2, B1.m_avx2);
  276|     20|         const __m256i T1 = _mm256_unpacklo_epi32(B2.m_avx2, B3.m_avx2);
  277|     20|         const __m256i T2 = _mm256_unpackhi_epi32(B0.m_avx2, B1.m_avx2);
  278|     20|         const __m256i T3 = _mm256_unpackhi_epi32(B2.m_avx2, B3.m_avx2);
  279|       |
  280|     20|         B0.m_avx2 = _mm256_unpacklo_epi64(T0, T1);
  281|     20|         B1.m_avx2 = _mm256_unpackhi_epi64(T0, T1);
  282|     20|         B2.m_avx2 = _mm256_unpacklo_epi64(T2, T3);
  283|     20|         B3.m_avx2 = _mm256_unpackhi_epi64(T2, T3);
  284|     20|      }
_ZN5Botan9SIMD_8x329transposeERS0_S1_S1_S1_S1_S1_S1_S1_:
  312|     10|                            SIMD_8x32& B7) noexcept {
  313|     10|         transpose(B0, B1, B2, B3);
  314|     10|         transpose(B4, B5, B6, B7);
  315|       |
  316|     10|         swap_tops(B0, B4);
  317|     10|         swap_tops(B1, B5);
  318|     10|         swap_tops(B2, B6);
  319|     10|         swap_tops(B3, B7);
  320|     10|      }
_ZNK5Botan9SIMD_8x3211unsigned_ltERKS0_:
  327|      5|      SIMD_8x32 BOTAN_FN_ISA_SIMD_8X32 unsigned_lt(const SIMD_8x32& other) const noexcept {
  328|       |         // No unsigned comparison before AVX-512; bias into the signed domain
  329|      5|         const __m256i bias = _mm256_set1_epi32(static_cast<int32_t>(0x80000000));
  330|      5|         return SIMD_8x32(_mm256_cmpgt_epi32(_mm256_xor_si256(other.raw(), bias), _mm256_xor_si256(raw(), bias)));
  331|      5|      }
_ZN5Botan9SIMD_8x3215reset_registersEv:
  385|      5|      static void reset_registers() noexcept { _mm256_zeroupper(); }
_ZN5Botan9SIMD_8x3214zero_registersEv:
  388|      5|      static void zero_registers() noexcept { _mm256_zeroall(); }
_ZNK5Botan9SIMD_8x323rawEv:
  390|    170|      __m256i BOTAN_FN_ISA_SIMD_8X32 raw() const noexcept { return m_avx2; }
_ZN5Botan9SIMD_8x32C2EDv4_x:
  393|  1.84k|      explicit SIMD_8x32(__m256i x) noexcept : m_avx2(x) {}
_ZN5Botan9SIMD_8x329swap_topsERS0_S1_:
  397|     40|      static void swap_tops(SIMD_8x32& A, SIMD_8x32& B) {
  398|     40|         const auto T0 = SIMD_8x32(_mm256_permute2x128_si256(A.raw(), B.raw(), 0 + (2 << 4)));
  399|       |         const auto T1 = SIMD_8x32(_mm256_permute2x128_si256(A.raw(), B.raw(), 1 + (3 << 4)));
  400|     40|         A = T0;
  401|     40|         B = T1;
  402|     40|      }
_ZNK5Botan9SIMD_8x324rotlILm7EEES0_vQaagtT_Li0EltT_Li32E:
  128|    400|      {
  129|       |#if defined(__AVX512VL__)
  130|       |         return SIMD_8x32(_mm256_rol_epi32(m_avx2, ROT));
  131|       |#else
  132|       |         if constexpr(ROT == 8) {
  133|       |            const __m256i shuf_rotl_8 =
  134|       |               _mm256_set_epi64x(0x0e0d0c0f'0a09080b, 0x06050407'02010003, 0x0e0d0c0f'0a09080b, 0x06050407'02010003);
  135|       |
  136|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_8));
  137|       |         } else if constexpr(ROT == 16) {
  138|       |            const __m256i shuf_rotl_16 =
  139|       |               _mm256_set_epi64x(0x0d0c0f0e'09080b0a, 0x05040706'01000302, 0x0d0c0f0e'09080b0a, 0x05040706'01000302);
  140|       |
  141|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_16));
  142|       |         } else if constexpr(ROT == 24) {
  143|       |            const __m256i shuf_rotl_24 =
  144|       |               _mm256_set_epi64x(0x0c0f0e0d'080b0a09, 0x04070605'00030201, 0x0c0f0e0d'080b0a09, 0x04070605'00030201);
  145|       |
  146|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_24));
  147|    400|         } else {
  148|    400|            return SIMD_8x32(_mm256_xor_si256(_mm256_slli_epi32(m_avx2, static_cast<int>(ROT)),
  149|    400|                                              _mm256_srli_epi32(m_avx2, static_cast<int>(32 - ROT))));
  150|    400|         }
  151|    400|#endif
  152|    400|      }
_ZNK5Botan9SIMD_8x324rotlILm16EEES0_vQaagtT_Li0EltT_Li32E:
  128|    400|      {
  129|       |#if defined(__AVX512VL__)
  130|       |         return SIMD_8x32(_mm256_rol_epi32(m_avx2, ROT));
  131|       |#else
  132|       |         if constexpr(ROT == 8) {
  133|       |            const __m256i shuf_rotl_8 =
  134|       |               _mm256_set_epi64x(0x0e0d0c0f'0a09080b, 0x06050407'02010003, 0x0e0d0c0f'0a09080b, 0x06050407'02010003);
  135|       |
  136|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_8));
  137|    400|         } else if constexpr(ROT == 16) {
  138|    400|            const __m256i shuf_rotl_16 =
  139|    400|               _mm256_set_epi64x(0x0d0c0f0e'09080b0a, 0x05040706'01000302, 0x0d0c0f0e'09080b0a, 0x05040706'01000302);
  140|       |
  141|    400|            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_16));
  142|       |         } else if constexpr(ROT == 24) {
  143|       |            const __m256i shuf_rotl_24 =
  144|       |               _mm256_set_epi64x(0x0c0f0e0d'080b0a09, 0x04070605'00030201, 0x0c0f0e0d'080b0a09, 0x04070605'00030201);
  145|       |
  146|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_24));
  147|       |         } else {
  148|       |            return SIMD_8x32(_mm256_xor_si256(_mm256_slli_epi32(m_avx2, static_cast<int>(ROT)),
  149|       |                                              _mm256_srli_epi32(m_avx2, static_cast<int>(32 - ROT))));
  150|       |         }
  151|    400|#endif
  152|    400|      }
_ZNK5Botan9SIMD_8x324rotlILm12EEES0_vQaagtT_Li0EltT_Li32E:
  128|    400|      {
  129|       |#if defined(__AVX512VL__)
  130|       |         return SIMD_8x32(_mm256_rol_epi32(m_avx2, ROT));
  131|       |#else
  132|       |         if constexpr(ROT == 8) {
  133|       |            const __m256i shuf_rotl_8 =
  134|       |               _mm256_set_epi64x(0x0e0d0c0f'0a09080b, 0x06050407'02010003, 0x0e0d0c0f'0a09080b, 0x06050407'02010003);
  135|       |
  136|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_8));
  137|       |         } else if constexpr(ROT == 16) {
  138|       |            const __m256i shuf_rotl_16 =
  139|       |               _mm256_set_epi64x(0x0d0c0f0e'09080b0a, 0x05040706'01000302, 0x0d0c0f0e'09080b0a, 0x05040706'01000302);
  140|       |
  141|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_16));
  142|       |         } else if constexpr(ROT == 24) {
  143|       |            const __m256i shuf_rotl_24 =
  144|       |               _mm256_set_epi64x(0x0c0f0e0d'080b0a09, 0x04070605'00030201, 0x0c0f0e0d'080b0a09, 0x04070605'00030201);
  145|       |
  146|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_24));
  147|    400|         } else {
  148|    400|            return SIMD_8x32(_mm256_xor_si256(_mm256_slli_epi32(m_avx2, static_cast<int>(ROT)),
  149|    400|                                              _mm256_srli_epi32(m_avx2, static_cast<int>(32 - ROT))));
  150|    400|         }
  151|    400|#endif
  152|    400|      }
_ZNK5Botan9SIMD_8x324rotlILm8EEES0_vQaagtT_Li0EltT_Li32E:
  128|    400|      {
  129|       |#if defined(__AVX512VL__)
  130|       |         return SIMD_8x32(_mm256_rol_epi32(m_avx2, ROT));
  131|       |#else
  132|    400|         if constexpr(ROT == 8) {
  133|    400|            const __m256i shuf_rotl_8 =
  134|    400|               _mm256_set_epi64x(0x0e0d0c0f'0a09080b, 0x06050407'02010003, 0x0e0d0c0f'0a09080b, 0x06050407'02010003);
  135|       |
  136|    400|            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_8));
  137|       |         } else if constexpr(ROT == 16) {
  138|       |            const __m256i shuf_rotl_16 =
  139|       |               _mm256_set_epi64x(0x0d0c0f0e'09080b0a, 0x05040706'01000302, 0x0d0c0f0e'09080b0a, 0x05040706'01000302);
  140|       |
  141|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_16));
  142|       |         } else if constexpr(ROT == 24) {
  143|       |            const __m256i shuf_rotl_24 =
  144|       |               _mm256_set_epi64x(0x0c0f0e0d'080b0a09, 0x04070605'00030201, 0x0c0f0e0d'080b0a09, 0x04070605'00030201);
  145|       |
  146|       |            return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_24));
  147|       |         } else {
  148|       |            return SIMD_8x32(_mm256_xor_si256(_mm256_slli_epi32(m_avx2, static_cast<int>(ROT)),
  149|       |                                              _mm256_srli_epi32(m_avx2, static_cast<int>(32 - ROT))));
  150|       |         }
  151|    400|#endif
  152|    400|      }

_ZN5Botan2CT13value_barrierITkNSt3__117unsigned_integralEmQntsr3stdE7same_asIbT_EEES3_S3_:
   43|  11.5M|constexpr inline T value_barrier(T x) {
   44|  11.5M|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (44:7): [Folded, False: 11.5M]
  ------------------
   45|      0|      return x;
   46|  11.5M|   } else {
   47|  11.5M|#if defined(BOTAN_CT_VALUE_BARRIER_USE_ASM)
   48|       |      /*
   49|       |      * We may want a "stronger" statement such as
   50|       |      *     asm volatile("" : "+r,m"(x) : : "memory);
   51|       |      * (see https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html)
   52|       |      * however the current approach seems sufficient with current compilers,
   53|       |      * and is minimally damaging with regards to degrading code generation.
   54|       |      */
   55|  11.5M|      asm("" : "+r"(x) : /* no input */);  // NOLINT(*-no-assembler)
   56|  11.5M|      return x;
   57|       |#elif defined(BOTAN_CT_VALUE_BARRIER_USE_VOLATILE)
   58|       |      volatile T vx = x;
   59|       |      return vx;
   60|       |#else
   61|       |      return x;
   62|       |#endif
   63|  11.5M|   }
   64|  11.5M|}
_ZN5Botan2CT13value_barrierITkNSt3__117unsigned_integralEhQntsr3stdE7same_asIbT_EEES3_S3_:
   43|  25.4k|constexpr inline T value_barrier(T x) {
   44|  25.4k|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (44:7): [Folded, False: 25.4k]
  ------------------
   45|      0|      return x;
   46|  25.4k|   } else {
   47|  25.4k|#if defined(BOTAN_CT_VALUE_BARRIER_USE_ASM)
   48|       |      /*
   49|       |      * We may want a "stronger" statement such as
   50|       |      *     asm volatile("" : "+r,m"(x) : : "memory);
   51|       |      * (see https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html)
   52|       |      * however the current approach seems sufficient with current compilers,
   53|       |      * and is minimally damaging with regards to degrading code generation.
   54|       |      */
   55|  25.4k|      asm("" : "+r"(x) : /* no input */);  // NOLINT(*-no-assembler)
   56|  25.4k|      return x;
   57|       |#elif defined(BOTAN_CT_VALUE_BARRIER_USE_VOLATILE)
   58|       |      volatile T vx = x;
   59|       |      return vx;
   60|       |#else
   61|       |      return x;
   62|       |#endif
   63|  25.4k|   }
   64|  25.4k|}

_ZN5Botan13ignore_paramsIJPKmmEEEvDpRKT_:
  149|   289k|constexpr void ignore_params([[maybe_unused]] const T&... args) {}

_ZN5Botan6BigIntD2Ev:
  185|  93.0k|      ~BigInt() { _const_time_unpoison(); }
_ZN5BotangtERKNS_6BigIntEm:
 1423|  3.00k|inline bool operator>(const BigInt& a, word b) {
 1424|  3.00k|   return (a.cmp_word(b) > 0);
 1425|  3.00k|}
_ZN5BotanneERKNS_6BigIntES2_:
 1323|    530|inline bool operator!=(const BigInt& a, const BigInt& b) {
 1324|    530|   return !a.is_equal(b);
 1325|    530|}
_ZN5Botan6BigInt4zeroEv:
   50|     45|      static BigInt zero() { return BigInt(); }
_ZN5Botan6BigIntC2EOS0_:
  183|  22.0k|      BigInt(BigInt&& other) noexcept { this->swap(other); }
_ZN5Botan6BigIntaSEOS0_:
  190|  91.4k|      BigInt& operator=(BigInt&& other) noexcept {
  191|  91.4k|         if(this != &other) {
  ------------------
  |  Branch (191:13): [True: 91.4k, False: 0]
  ------------------
  192|  91.4k|            this->swap(other);
  193|  91.4k|         }
  194|       |
  195|  91.4k|         return (*this);
  196|  91.4k|      }
_ZN5Botan6BigInt4swapERS0_:
  207|   113k|      void swap(BigInt& other) noexcept {
  208|   113k|         m_data.swap(other.m_data);
  209|   113k|         std::swap(m_signedness, other.m_signedness);
  210|   113k|      }
_ZN5Botan6BigIntpLEm:
  233|     97|      BigInt& operator+=(word y) { return add(&y, 1, Positive); }
_ZN5Botan6BigIntmIEm:
  245|    531|      BigInt& operator-=(word y) { return sub(&y, 1, Positive); }
_ZN5Botan6BigInt3subEPKmmNS0_4SignE:
  358|    531|      BigInt& sub(const word y[], size_t y_words, Sign sign) {
  359|    531|         return add(y, y_words, sign == Positive ? Negative : Positive);
  ------------------
  |  Branch (359:33): [True: 531, False: 0]
  ------------------
  360|    531|      }
_ZN5Botan6BigInt5clearEv:
  441|    866|      void clear() {
  442|    866|         m_data.set_to_zero();
  443|    866|         m_signedness = Positive;
  444|    866|      }
_ZNK5Botan6BigInt7is_evenEv:
  481|    575|      bool is_even() const { return !get_bit(0); }
_ZNK5Botan6BigInt6is_oddEv:
  487|  23.5k|      bool is_odd() const { return get_bit(0); }
_ZNK5Botan6BigInt6signumEv:
  493|   291k|      int signum() const {
  494|   291k|         if(sig_words() == 0) {
  ------------------
  |  Branch (494:13): [True: 393, False: 291k]
  ------------------
  495|    393|            return 0;
  496|    393|         }
  497|   291k|         return (sign() == Negative) ? -1 : 1;
  ------------------
  |  Branch (497:17): [True: 287, False: 290k]
  ------------------
  498|   291k|      }
_ZNK5Botan6BigInt7is_zeroEv:
  510|  26.8k|      bool is_zero() const { return sig_words() == 0; }
_ZN5Botan6BigInt7set_bitEm:
  516|  1.90k|      void set_bit(size_t n) { conditionally_set_bit(n, true); }
_ZN5Botan6BigInt21conditionally_set_bitEmb:
  526|  1.90k|      void conditionally_set_bit(size_t n, bool set_it) {
  527|  1.90k|         const size_t which = n / (sizeof(word) * 8);
  528|  1.90k|         const word mask = static_cast<word>(set_it) << (n % (sizeof(word) * 8));
  529|  1.90k|         m_data.set_word_at(which, word_at(which) | mask);
  530|  1.90k|      }
_ZNK5Botan6BigInt7get_bitEm:
  549|  24.3k|      bool get_bit(size_t n) const { return ((word_at(n / (sizeof(word) * 8)) >> (n % (sizeof(word) * 8))) & 1) == 1; }
_ZNK5Botan6BigInt7word_atEm:
  601|   324k|      word word_at(size_t n) const { return m_data.get_word_at(n); }
_ZN5Botan6BigInt11set_word_atEmm:
  608|  17.3k|      BOTAN_DEPRECATED("Deprecated no replacement") void set_word_at(size_t i, word w) { m_data.set_word_at(i, w); }
_ZNK5Botan6BigInt4signEv:
  641|   338k|      Sign sign() const { return (m_signedness); }
_ZNK5Botan6BigInt12reverse_signEv:
  647|    326|      Sign reverse_sign() const {
  648|    326|         if(sign() == Positive) {
  ------------------
  |  Branch (648:13): [True: 326, False: 0]
  ------------------
  649|    326|            return Negative;
  650|    326|         }
  651|      0|         return Positive;
  652|    326|      }
_ZN5Botan6BigInt9flip_signEv:
  657|    281|      BOTAN_DEPRECATED("Deprecated no replacement") void flip_sign() { set_sign(reverse_sign()); }
_ZN5Botan6BigInt8set_signENS0_4SignE:
  663|  7.54k|      void set_sign(Sign sign) {
  664|  7.54k|         if(sign == Negative && is_zero()) {
  ------------------
  |  Branch (664:13): [True: 287, False: 7.25k]
  |  Branch (664:33): [True: 2, False: 285]
  ------------------
  665|      2|            sign = Positive;
  666|      2|         }
  667|       |
  668|  7.54k|         m_signedness = sign;
  669|  7.54k|      }
_ZNK5Botan6BigInt4sizeEv:
  681|   289k|      size_t size() const { return m_data.size(); }
_ZNK5Botan6BigInt9sig_wordsEv:
  687|   486k|      size_t sig_words() const { return m_data.sig_words(); }
_ZN5Botan6BigInt12mutable_dataEv:
  712|  3.33k|      BOTAN_DEPRECATED("Deprecated no replacement") word* mutable_data() { return m_data.mutable_data(); }
_ZNK5Botan6BigInt4dataEv:
  718|  1.17k|      BOTAN_DEPRECATED("Deprecated no replacement") const word* data() const { return m_data.const_data(); }
_ZNK5Botan6BigInt7grow_toEm:
  738|  4.89k|      BOTAN_DEPRECATED("Deprecated no replacement") void grow_to(size_t n) const { m_data.grow_to(n); }
_ZN5Botan6BigInt10power_of_2Em:
  906|  1.90k|      static BigInt power_of_2(size_t n) {
  907|  1.90k|         BigInt b;
  908|  1.90k|         b.set_bit(n);
  909|  1.90k|         return b;
  910|  1.90k|      }
_ZNK5Botan6BigInt8_as_spanEv:
 1023|  6.64k|      std::span<const word> _as_span() const { return m_data.const_span(); }
_ZNK5Botan6BigInt5_dataEv:
 1033|   555k|      const word* _data() const { return m_data.const_data(); }
_ZN5Botan6BigInt11_from_wordsERNSt3__16vectorImNS_16secure_allocatorImEEEE:
 1052|  21.4k|      static BigInt _from_words(secure_vector<word>& words) {
 1053|  21.4k|         BigInt bn;
 1054|  21.4k|         bn.m_data.swap(words);
 1055|  21.4k|         return bn;
 1056|  21.4k|      }
_ZN5Botan6BigInt4Data12mutable_dataEv:
 1083|  26.5k|            word* mutable_data() {
 1084|  26.5k|               invalidate_sig_words();
 1085|  26.5k|               return m_reg.data();
 1086|  26.5k|            }
_ZNK5Botan6BigInt4Data10const_dataEv:
 1088|   649k|            const word* const_data() const { return m_reg.data(); }
_ZNK5Botan6BigInt4Data10const_spanEv:
 1090|  6.64k|            std::span<const word> const_span() const { return std::span{m_reg}; }
_ZNK5Botan6BigInt4Data11get_word_atEm:
 1099|   324k|            word get_word_at(size_t n) const {
 1100|   324k|               if(n < m_reg.size()) {
  ------------------
  |  Branch (1100:19): [True: 322k, False: 1.90k]
  ------------------
 1101|   322k|                  return m_reg[n];
 1102|   322k|               }
 1103|  1.90k|               return 0;
 1104|   324k|            }
_ZN5Botan6BigInt4Data11set_word_atEmm:
 1106|  19.5k|            void set_word_at(size_t i, word w) {
 1107|  19.5k|               invalidate_sig_words();
 1108|  19.5k|               if(i >= m_reg.size()) {
  ------------------
  |  Branch (1108:19): [True: 19.5k, False: 3]
  ------------------
 1109|  19.5k|                  if(w == 0) {
  ------------------
  |  Branch (1109:22): [True: 1, False: 19.5k]
  ------------------
 1110|      1|                     return;
 1111|      1|                  }
 1112|  19.5k|                  grow_to(i + 1);
 1113|  19.5k|               }
 1114|  19.5k|               m_reg[i] = w;
 1115|  19.5k|            }
_ZNK5Botan6BigInt4Data7grow_toEm:
 1126|  24.4k|            void grow_to(size_t n) const {
 1127|  24.4k|               if(n > size()) {
  ------------------
  |  Branch (1127:19): [True: 22.7k, False: 1.70k]
  ------------------
 1128|  22.7k|                  if(n <= m_reg.capacity()) {
  ------------------
  |  Branch (1128:22): [True: 0, False: 22.7k]
  ------------------
 1129|      0|                     m_reg.resize(n);
 1130|  22.7k|                  } else {
 1131|  22.7k|                     m_reg.resize(n + (8 - (n % 8)));
 1132|  22.7k|                  }
 1133|  22.7k|               }
 1134|  24.4k|            }
_ZNK5Botan6BigInt4Data4sizeEv:
 1136|   430k|            size_t size() const { return m_reg.size(); }
_ZN5Botan6BigInt4Data4swapERS1_:
 1151|   113k|            void swap(Data& other) noexcept {
 1152|   113k|               m_reg.swap(other.m_reg);
 1153|   113k|               std::swap(m_sig_words, other.m_sig_words);
 1154|   113k|            }
_ZN5Botan6BigInt4Data4swapERNSt3__16vectorImNS_16secure_allocatorImEEEE:
 1156|  22.3k|            void swap(secure_vector<word>& reg) noexcept {
 1157|  22.3k|               m_reg.swap(reg);
 1158|  22.3k|               invalidate_sig_words();
 1159|  22.3k|            }
_ZNK5Botan6BigInt4Data20invalidate_sig_wordsEv:
 1161|  68.3k|            void invalidate_sig_words() const noexcept { m_sig_words = sig_words_npos; }
_ZNK5Botan6BigInt4Data9sig_wordsEv:
 1163|   486k|            size_t sig_words() const {
 1164|   486k|               if(m_sig_words == sig_words_npos) {
  ------------------
  |  Branch (1164:19): [True: 59.5k, False: 426k]
  ------------------
 1165|  59.5k|                  m_sig_words = calc_sig_words();
 1166|  59.5k|               }
 1167|   486k|               return m_sig_words;
 1168|   486k|            }
_ZN5BotanplERKNS_6BigIntES2_:
 1189|     43|inline BigInt operator+(const BigInt& x, const BigInt& y) {
 1190|     43|   return BigInt::add2(x, y._data(), y.sig_words(), y.sign());
 1191|     43|}
_ZN5BotanplERKNS_6BigIntEm:
 1199|    464|inline BigInt operator+(const BigInt& x, word y) {
 1200|    464|   return BigInt::add2(x, &y, 1, BigInt::Positive);
 1201|    464|}
_ZN5BotanmiERKNS_6BigIntES2_:
 1219|     45|inline BigInt operator-(const BigInt& x, const BigInt& y) {
 1220|     45|   return BigInt::add2(x, y._data(), y.sig_words(), y.reverse_sign());
 1221|     45|}
_ZN5BotanmiERKNS_6BigIntEm:
 1229|    544|inline BigInt operator-(const BigInt& x, word y) {
 1230|    544|   return BigInt::add2(x, &y, 1, BigInt::Negative);
 1231|    544|}
_ZN5BotanleERKNS_6BigIntES2_:
 1333|     86|inline bool operator<=(const BigInt& a, const BigInt& b) {
 1334|     86|   return (a.cmp(b) <= 0);
 1335|     86|}
_ZN5BotangeERKNS_6BigIntES2_:
 1343|  1.79k|inline bool operator>=(const BigInt& a, const BigInt& b) {
 1344|  1.79k|   return (a.cmp(b) >= 0);
 1345|  1.79k|}
_ZN5BotanltERKNS_6BigIntES2_:
 1353|  27.3k|inline bool operator<(const BigInt& a, const BigInt& b) {
 1354|  27.3k|   return a.is_less_than(b);
 1355|  27.3k|}
_ZN5BotaneqERKNS_6BigIntEm:
 1373|  48.5k|inline bool operator==(const BigInt& a, word b) {
 1374|  48.5k|   return (a.cmp_word(b) == 0);
 1375|  48.5k|}
_ZN5BotanneERKNS_6BigIntEm:
 1383|  2.45k|inline bool operator!=(const BigInt& a, word b) {
 1384|  2.45k|   return (a.cmp_word(b) != 0);
 1385|  2.45k|}
_ZN5BotanleERKNS_6BigIntEm:
 1393|    813|inline bool operator<=(const BigInt& a, word b) {
 1394|    813|   return (a.cmp_word(b) <= 0);
 1395|    813|}
_ZN5BotangeERKNS_6BigIntEm:
 1403|  2.56k|inline bool operator>=(const BigInt& a, word b) {
 1404|  2.56k|   return (a.cmp_word(b) >= 0);
 1405|  2.56k|}
_ZN5BotanltERKNS_6BigIntEm:
 1413|  2.30k|inline bool operator<(const BigInt& a, word b) {
 1414|  2.30k|   return (a.cmp_word(b) < 0);
 1415|  2.30k|}
_ZN5Botan6BigIntC2ERKS0_:
   88|  3.38k|      BigInt(const BigInt& other) = default;
_ZN5Botan6BigIntC2Ev:
   45|  67.3k|      BigInt() = default;
_ZN5Botan6BigIntaSERKS0_:
  201|  1.35k|      BigInt& operator=(const BigInt&) = default;

_ZN5Botan20Buffered_Computation6updateENSt3__14spanIKhLm18446744073709551615EEE:
   41|     10|      void update(std::span<const uint8_t> in) { add_data(in); }
_ZN5Botan20Buffered_Computation5finalITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEET_v:
  104|      2|      T final() {
  105|      2|         T output(output_length());
  106|      2|         final_result(output);
  107|      2|         return output;
  108|      2|      }
_ZN5Botan20Buffered_ComputationD2Ev:
  169|      2|      virtual ~Buffered_Computation() = default;

_ZNK5Botan10ChaCha_RNG31max_number_of_bytes_per_requestEv:
  120|     53|      size_t max_number_of_bytes_per_request() const override { return 0; }

_ZN5Botan11clear_bytesEPvm:
  101|  20.3k|inline constexpr void clear_bytes(void* ptr, size_t bytes) {
  102|  20.3k|   if(bytes > 0) {
  ------------------
  |  Branch (102:7): [True: 19.4k, False: 866]
  ------------------
  103|  19.4k|      std::memset(ptr, 0, bytes);
  104|  19.4k|   }
  105|  20.3k|}
_ZN5Botan9clear_memImEEvPT_m:
  118|  11.9k|inline constexpr void clear_mem(T* ptr, size_t n) {
  119|  11.9k|   clear_bytes(ptr, sizeof(T) * n);
  120|  11.9k|}
_ZN5Botan8copy_memImQsr3stdE12is_trivial_vIu7__decayIT_EEEEvPS1_PKS1_m:
  144|  8.86k|inline constexpr void copy_mem(T* out, const T* in, size_t n) {
  145|  8.86k|   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
  ------------------
  |  |  110|  8.86k|   do {                                                                                          \
  |  |  111|  8.86k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                              \
  |  |  112|  17.7k|      if((expr1) && !(expr2)) {                                                                  \
  |  |  ------------------
  |  |  |  Branch (112:10): [True: 8.86k, False: 0]
  |  |  |  Branch (112:23): [True: 8.86k, False: 0]
  |  |  |  Branch (112:23): [True: 8.86k, False: 0]
  |  |  ------------------
  |  |  113|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                                     \
  |  |  114|      0|         Botan::assertion_failure(#expr1 " implies " #expr2, msg, __func__, __FILE__, __LINE__); \
  |  |  115|      0|      }                                                                                          \
  |  |  116|  8.86k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (116:12): [Folded, False: 8.86k]
  |  |  ------------------
  ------------------
  146|       |
  147|  8.86k|   if(in != nullptr && out != nullptr && n > 0) {
  ------------------
  |  Branch (147:7): [True: 8.86k, False: 0]
  |  Branch (147:24): [True: 8.86k, False: 0]
  |  Branch (147:42): [True: 8.86k, False: 0]
  ------------------
  148|  8.86k|      std::memmove(out, in, sizeof(T) * n);
  149|  8.86k|   }
  150|  8.86k|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeERKNSt3__14spanIhLm8EEEmQaaaasr3stdE23is_trivially_copyable_vIT0_Entsr3std6rangesE5rangeIS7_Esr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEEEvOSC_RKS7_:
  199|      4|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromT& in) {
  200|      4|   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
  201|      4|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeERKNSt3__14spanIhLm8EEETkNS1_16contiguous_rangeENS3_IKmLm1EEEQaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISG_EESH_E4type10value_typeEEsr3stdE23is_trivially_copyable_vINS9_IXsr21__is_primary_templateINSA_Iu14__remove_cvrefIDTclL_ZNSC_5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENSI_ISQ_EESR_E4type10value_typeEEEEvOSN_RKSD_:
  176|      4|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromR& in) {
  177|      4|   ranges::assert_equal_byte_lengths(out, in);
  178|      4|   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  179|      4|}
_ZN5Botan13typecast_copyImTkNS_6ranges16contiguous_rangeENSt3__14spanIKhLm8EEEQaaaasr3stdE26is_default_constructible_vIT_Esr3stdE23is_trivially_copyable_vIS6_Esr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEEES6_RKSB_:
  210|    843|inline constexpr ToT typecast_copy(const FromR& src) {
  211|    843|   ToT dst;  // NOLINT(*-member-init)
  212|    843|   typecast_copy(dst, src);
  213|    843|   return dst;
  214|    843|}
_ZN5Botan13typecast_copyImTkNS_6ranges16contiguous_rangeENSt3__14spanIKhLm8EEEQaaaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISD_EESE_E4type10value_typeEEsr3stdE23is_trivially_copyable_vIT_Entsr3std6rangesE5rangeISK_EEEvRSK_RKSA_:
  188|    843|inline constexpr void typecast_copy(ToT& out, const FromR& in) {
  189|    843|   typecast_copy(std::span<ToT, 1>(&out, 1), in);
  190|    843|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeENSt3__14spanImLm1EEETkNS1_16contiguous_rangeENS3_IKhLm8EEEQaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEsr3stdE23is_trivially_copyable_vINS7_IXsr21__is_primary_templateINS8_Iu14__remove_cvrefIDTclL_ZNSA_5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENSG_ISO_EESP_E4type10value_typeEEEEvOSL_RKSB_:
  176|    843|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromR& in) {
  177|    843|   ranges::assert_equal_byte_lengths(out, in);
  178|    843|   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  179|    843|}
_ZN5Botan8copy_memITkNS_6ranges23contiguous_output_rangeENSt3__14spanIhLm18446744073709551615EEETkNS1_16contiguous_rangeENS3_IKhLm18446744073709551615EEEQaasr3stdE9is_same_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISE_EESF_E4type10value_typeENS7_IXsr21__is_primary_templateINS8_Iu14__remove_cvrefIDTclL_ZNSA_5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENSG_ISO_EESP_E4type10value_typeEEsr3stdE23is_trivially_copyable_vIST_EEEvOSB_RKSL_:
  160|    593|inline constexpr void copy_mem(OutR&& out /* NOLINT(*-std-forward) */, const InR& in) {
  161|    593|   ranges::assert_equal_byte_lengths(out, in);
  162|    593|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (162:7): [Folded, False: 593]
  ------------------
  163|      0|      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
  164|    593|   } else if(ranges::size_bytes(out) > 0) {
  ------------------
  |  Branch (164:14): [True: 593, False: 0]
  ------------------
  165|    593|      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  166|    593|   }
  167|    593|}
_ZN5Botan13typecast_copyImTkNS_6ranges16contiguous_rangeENSt3__14spanIhLm8EEEQaaaasr3stdE26is_default_constructible_vIT_Esr3stdE23is_trivially_copyable_vIS5_Esr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISD_EESE_E4type10value_typeEEEES5_RKSA_:
  210|    591|inline constexpr ToT typecast_copy(const FromR& src) {
  211|    591|   ToT dst;  // NOLINT(*-member-init)
  212|    591|   typecast_copy(dst, src);
  213|    591|   return dst;
  214|    591|}
_ZN5Botan13typecast_copyImTkNS_6ranges16contiguous_rangeENSt3__14spanIhLm8EEEQaaaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISC_EESD_E4type10value_typeEEsr3stdE23is_trivially_copyable_vIT_Entsr3std6rangesE5rangeISJ_EEEvRSJ_RKS9_:
  188|    591|inline constexpr void typecast_copy(ToT& out, const FromR& in) {
  189|    591|   typecast_copy(std::span<ToT, 1>(&out, 1), in);
  190|    591|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeENSt3__14spanImLm1EEETkNS1_16contiguous_rangeENS3_IhLm8EEEQaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISD_EESE_E4type10value_typeEEsr3stdE23is_trivially_copyable_vINS6_IXsr21__is_primary_templateINS7_Iu14__remove_cvrefIDTclL_ZNS9_5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENSF_ISN_EESO_E4type10value_typeEEEEvOSK_RKSA_:
  176|    591|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromR& in) {
  177|    591|   ranges::assert_equal_byte_lengths(out, in);
  178|    591|   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  179|    591|}
_ZN5Botan9clear_memITkNS_6ranges23contiguous_output_rangeENSt3__14spanImLm18446744073709551615EEEEEvOT_Qsr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRS5_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISD_EESE_E4type10value_typeEE:
  132|  8.35k|{
  133|  8.35k|   clear_bytes(std::ranges::data(mem), ranges::size_bytes(mem));
  134|  8.35k|}
_ZN5Botan8copy_memITkNS_6ranges23contiguous_output_rangeENSt3__14spanImLm18446744073709551615EEETkNS1_16contiguous_rangeENS3_IKmLm18446744073709551615EEEQaasr3stdE9is_same_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISE_EESF_E4type10value_typeENS7_IXsr21__is_primary_templateINS8_Iu14__remove_cvrefIDTclL_ZNSA_5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENSG_ISO_EESP_E4type10value_typeEEsr3stdE23is_trivially_copyable_vIST_EEEvOSB_RKSL_:
  160|  3.69k|inline constexpr void copy_mem(OutR&& out /* NOLINT(*-std-forward) */, const InR& in) {
  161|  3.69k|   ranges::assert_equal_byte_lengths(out, in);
  162|  3.69k|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (162:7): [Folded, False: 3.69k]
  ------------------
  163|      0|      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
  164|  3.69k|   } else if(ranges::size_bytes(out) > 0) {
  ------------------
  |  Branch (164:14): [True: 3.69k, False: 0]
  ------------------
  165|  3.69k|      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  166|  3.69k|   }
  167|  3.69k|}
_ZN5Botan9clear_memIhEEvPT_m:
  118|      4|inline constexpr void clear_mem(T* ptr, size_t n) {
  119|      4|   clear_bytes(ptr, sizeof(T) * n);
  120|      4|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeERKNSt3__14spanIhLm4EEEjQaaaasr3stdE23is_trivially_copyable_vIT0_Entsr3std6rangesE5rangeIS7_Esr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEEEvOSC_RKS7_:
  199|     32|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromT& in) {
  200|     32|   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
  201|     32|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeERKNSt3__14spanIhLm4EEETkNS1_16contiguous_rangeENS3_IKjLm1EEEQaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISG_EESH_E4type10value_typeEEsr3stdE23is_trivially_copyable_vINS9_IXsr21__is_primary_templateINSA_Iu14__remove_cvrefIDTclL_ZNSC_5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENSI_ISQ_EESR_E4type10value_typeEEEEvOSN_RKSD_:
  176|     32|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromR& in) {
  177|     32|   ranges::assert_equal_byte_lengths(out, in);
  178|     32|   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  179|     32|}
_ZN5Botan8copy_memIhQsr3stdE12is_trivial_vIu7__decayIT_EEEEvPS1_PKS1_m:
  144|     57|inline constexpr void copy_mem(T* out, const T* in, size_t n) {
  145|     57|   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
  ------------------
  |  |  110|     57|   do {                                                                                          \
  |  |  111|     57|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                              \
  |  |  112|    108|      if((expr1) && !(expr2)) {                                                                  \
  |  |  ------------------
  |  |  |  Branch (112:10): [True: 54, False: 3]
  |  |  |  Branch (112:23): [True: 54, False: 0]
  |  |  |  Branch (112:23): [True: 54, False: 0]
  |  |  ------------------
  |  |  113|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                                     \
  |  |  114|      0|         Botan::assertion_failure(#expr1 " implies " #expr2, msg, __func__, __FILE__, __LINE__); \
  |  |  115|      0|      }                                                                                          \
  |  |  116|     57|   } while(0)
  |  |  ------------------
  |  |  |  Branch (116:12): [Folded, False: 57]
  |  |  ------------------
  ------------------
  146|       |
  147|     57|   if(in != nullptr && out != nullptr && n > 0) {
  ------------------
  |  Branch (147:7): [True: 57, False: 0]
  |  Branch (147:24): [True: 57, False: 0]
  |  Branch (147:42): [True: 54, False: 3]
  ------------------
  148|     54|      std::memmove(out, in, sizeof(T) * n);
  149|     54|   }
  150|     57|}
_ZN5Botan9clear_memIjEEvPT_m:
  118|      6|inline constexpr void clear_mem(T* ptr, size_t n) {
  119|      6|   clear_bytes(ptr, sizeof(T) * n);
  120|      6|}
_ZN5Botan13typecast_copyITkNS_6ranges23contiguous_output_rangeERNSt3__14spanIjLm18446744073709551615EEETkNS1_16contiguous_rangeENS3_IKhLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRT0_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISF_EESG_E4type10value_typeEEsr3stdE23is_trivially_copyable_vINS8_IXsr21__is_primary_templateINS9_Iu14__remove_cvrefIDTclL_ZNSB_5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENSH_ISP_EESQ_E4type10value_typeEEEEvOSM_RKSC_:
  176|      2|inline constexpr void typecast_copy(ToR&& out /* NOLINT(*-std-forward) */, const FromR& in) {
  177|      2|   ranges::assert_equal_byte_lengths(out, in);
  178|      2|   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
  179|      2|}

_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJNS3_IKhLm18446744073709551615EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|    593|{
  101|    593|   const std::span s0{r0};
  102|       |
  103|       |   if constexpr(statically_spanable_range<R0>) {
  104|       |      constexpr size_t expected_size = s0.size_bytes();
  105|       |      (assert_exact_byte_length<expected_size>(rs), ...);
  106|    593|   } else {
  107|    593|      const size_t expected_size = s0.size_bytes();
  108|    593|      const bool correct_size =
  109|    593|         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|    593|      if(!correct_size) {
  ------------------
  |  Branch (111:10): [True: 0, False: 593]
  ------------------
  112|      0|         memory_region_size_violation();
  113|      0|      }
  114|    593|   }
  115|    593|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeENSt3__14spanIhLm8EEEEEvRKT0_:
   77|    595|inline constexpr void assert_exact_byte_length(const R& r) {
   78|    595|   const std::span s{r};
   79|    595|   if constexpr(statically_spanable_range<R>) {
   80|    595|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|    595|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanIhLm8EEETpTkNS0_14spanable_rangeEJNS3_IKmLm1EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|      4|{
  101|      4|   const std::span s0{r0};
  102|       |
  103|      4|   if constexpr(statically_spanable_range<R0>) {
  104|      4|      constexpr size_t expected_size = s0.size_bytes();
  105|      4|      (assert_exact_byte_length<expected_size>(rs), ...);
  106|       |   } else {
  107|       |      const size_t expected_size = s0.size_bytes();
  108|       |      const bool correct_size =
  109|       |         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|       |      if(!correct_size) {
  112|       |         memory_region_size_violation();
  113|       |      }
  114|       |   }
  115|      4|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeENSt3__14spanIKmLm1EEEEEvRKT0_:
   77|      4|inline constexpr void assert_exact_byte_length(const R& r) {
   78|      4|   const std::span s{r};
   79|      4|   if constexpr(statically_spanable_range<R>) {
   80|      4|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|      4|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanIhLm8EEEEEmRKT_:
   59|      4|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|      4|   return std::span{r}.size_bytes();
   61|      4|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeENSt3__14spanIKhLm8EEEEEvRKT0_:
   77|  1.68k|inline constexpr void assert_exact_byte_length(const R& r) {
   78|  1.68k|   const std::span s{r};
   79|  1.68k|   if constexpr(statically_spanable_range<R>) {
   80|  1.68k|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|  1.68k|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanImLm1EEETpTkNS0_14spanable_rangeEJNS3_IKhLm8EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|    843|{
  101|    843|   const std::span s0{r0};
  102|       |
  103|    843|   if constexpr(statically_spanable_range<R0>) {
  104|    843|      constexpr size_t expected_size = s0.size_bytes();
  105|    843|      (assert_exact_byte_length<expected_size>(rs), ...);
  106|       |   } else {
  107|       |      const size_t expected_size = s0.size_bytes();
  108|       |      const bool correct_size =
  109|       |         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|       |      if(!correct_size) {
  112|       |         memory_region_size_violation();
  113|       |      }
  114|       |   }
  115|    843|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanImLm1EEEEEmRKT_:
   59|  1.43k|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|  1.43k|   return std::span{r}.size_bytes();
   61|  1.43k|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanIhLm18446744073709551615EEEEEmRKT_:
   59|  1.18k|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|  1.18k|   return std::span{r}.size_bytes();
   61|  1.18k|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeENSt3__15arrayIhLm8EEEEEvRKT0_:
   77|    591|inline constexpr void assert_exact_byte_length(const R& r) {
   78|    591|   const std::span s{r};
   79|    591|   if constexpr(statically_spanable_range<R>) {
   80|    591|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|    591|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanImLm1EEETpTkNS0_14spanable_rangeEJNS3_IhLm8EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|    591|{
  101|    591|   const std::span s0{r0};
  102|       |
  103|    591|   if constexpr(statically_spanable_range<R0>) {
  104|    591|      constexpr size_t expected_size = s0.size_bytes();
  105|    591|      (assert_exact_byte_length<expected_size>(rs), ...);
  106|       |   } else {
  107|       |      const size_t expected_size = s0.size_bytes();
  108|       |      const bool correct_size =
  109|       |         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|       |      if(!correct_size) {
  112|       |         memory_region_size_violation();
  113|       |      }
  114|       |   }
  115|    591|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanImLm18446744073709551615EEEEEmRKT_:
   59|  15.7k|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|  15.7k|   return std::span{r}.size_bytes();
   61|  15.7k|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanImLm18446744073709551615EEETpTkNS0_14spanable_rangeEJNS3_IKmLm18446744073709551615EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|  3.69k|{
  101|  3.69k|   const std::span s0{r0};
  102|       |
  103|       |   if constexpr(statically_spanable_range<R0>) {
  104|       |      constexpr size_t expected_size = s0.size_bytes();
  105|       |      (assert_exact_byte_length<expected_size>(rs), ...);
  106|  3.69k|   } else {
  107|  3.69k|      const size_t expected_size = s0.size_bytes();
  108|  3.69k|      const bool correct_size =
  109|  3.69k|         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|  3.69k|      if(!correct_size) {
  ------------------
  |  Branch (111:10): [True: 0, False: 3.69k]
  ------------------
  112|      0|         memory_region_size_violation();
  113|      0|      }
  114|  3.69k|   }
  115|  3.69k|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeENSt3__14spanIhLm4EEEEEvRKT0_:
   77|     64|inline constexpr void assert_exact_byte_length(const R& r) {
   78|     64|   const std::span s{r};
   79|     64|   if constexpr(statically_spanable_range<R>) {
   80|     64|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|     64|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanIhLm4EEETpTkNS0_14spanable_rangeEJNS3_IKjLm1EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|     32|{
  101|     32|   const std::span s0{r0};
  102|       |
  103|     32|   if constexpr(statically_spanable_range<R0>) {
  104|     32|      constexpr size_t expected_size = s0.size_bytes();
  105|     32|      (assert_exact_byte_length<expected_size>(rs), ...);
  106|       |   } else {
  107|       |      const size_t expected_size = s0.size_bytes();
  108|       |      const bool correct_size =
  109|       |         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|       |      if(!correct_size) {
  112|       |         memory_region_size_violation();
  113|       |      }
  114|       |   }
  115|     32|}
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeENSt3__14spanIKjLm1EEEEEvRKT0_:
   77|     32|inline constexpr void assert_exact_byte_length(const R& r) {
   78|     32|   const std::span s{r};
   79|     32|   if constexpr(statically_spanable_range<R>) {
   80|     32|      static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths");
   81|       |   } else {
   82|       |      if(s.size_bytes() != expected) {
   83|       |         memory_region_size_violation();
   84|       |      }
   85|       |   }
   86|     32|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanIhLm4EEEEEmRKT_:
   59|     32|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|     32|   return std::span{r}.size_bytes();
   61|     32|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanIjLm18446744073709551615EEETpTkNS0_14spanable_rangeEJNS3_IKhLm18446744073709551615EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|      4|{
  101|      4|   const std::span s0{r0};
  102|       |
  103|       |   if constexpr(statically_spanable_range<R0>) {
  104|       |      constexpr size_t expected_size = s0.size_bytes();
  105|       |      (assert_exact_byte_length<expected_size>(rs), ...);
  106|      4|   } else {
  107|      4|      const size_t expected_size = s0.size_bytes();
  108|      4|      const bool correct_size =
  109|      4|         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|      4|      if(!correct_size) {
  ------------------
  |  Branch (111:10): [True: 0, False: 4]
  ------------------
  112|      0|         memory_region_size_violation();
  113|      0|      }
  114|      4|   }
  115|      4|}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeENSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJNS3_IKjLm18446744073709551615EEEEEEvRKT_DpRKT0_QgtsZT0_Li0E:
  100|      4|{
  101|      4|   const std::span s0{r0};
  102|       |
  103|       |   if constexpr(statically_spanable_range<R0>) {
  104|       |      constexpr size_t expected_size = s0.size_bytes();
  105|       |      (assert_exact_byte_length<expected_size>(rs), ...);
  106|      4|   } else {
  107|      4|      const size_t expected_size = s0.size_bytes();
  108|      4|      const bool correct_size =
  109|      4|         ((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...);
  110|       |
  111|      4|      if(!correct_size) {
  ------------------
  |  Branch (111:10): [True: 0, False: 4]
  ------------------
  112|      0|         memory_region_size_violation();
  113|      0|      }
  114|      4|   }
  115|      4|}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanIjLm18446744073709551615EEEEEmRKT_:
   59|      2|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|      2|   return std::span{r}.size_bytes();
   61|      2|}

_ZN5Botan21RandomNumberGenerator9randomizeENSt3__14spanIhLm18446744073709551615EEE:
   86|     53|      void randomize(std::span<uint8_t> output) { this->fill_bytes_with_input(output, {}); }
_ZN5Botan21RandomNumberGenerator11add_entropyENSt3__14spanIKhLm18446744073709551615EEE:
  121|      1|      void add_entropy(std::span<const uint8_t> input) { this->accept_seed_material(input); }
_ZN5Botan21RandomNumberGenerator10random_vecENSt3__14spanIhLm18446744073709551615EEE:
  254|     53|      void random_vec(std::span<uint8_t> v) { this->randomize(v); }
_ZN5Botan21RandomNumberGeneratorC2Ev:
   57|      1|      RandomNumberGenerator() = default;
_ZN5Botan21RandomNumberGeneratorD2Ev:
   52|      1|      virtual ~RandomNumberGenerator() = default;
_ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEQsr3stdE21default_initializableIT_EEES8_m:
  280|     53|      T random_vec(size_t bytes) {
  281|     53|         T result;
  282|     53|         random_vec(result, bytes);
  283|     53|         return result;
  284|     53|      }
_ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEEvRT_m:
  265|     53|      void random_vec(T& v, size_t bytes) {
  266|     53|         v.resize(bytes);
  267|     53|         random_vec(v);
  268|     53|      }

_ZN5Botan16secure_allocatorIhE8allocateEm:
   95|     60|      T* allocate(std::size_t n) { return static_cast<T*>(allocate_memory(n, sizeof(T))); }
_ZN5Botan16secure_allocatorIhE10deallocateEPhm:
  102|     60|      void deallocate(T* p, std::size_t n) { deallocate_memory(p, n, sizeof(T)); }
_ZN5Botan16secure_allocatorImE10deallocateEPmm:
  102|   124k|      void deallocate(T* p, std::size_t n) { deallocate_memory(p, n, sizeof(T)); }
_ZN5Botan16secure_allocatorImE8allocateEm:
   95|   124k|      T* allocate(std::size_t n) { return static_cast<T*>(allocate_memory(n, sizeof(T))); }
_ZN5Botan16secure_allocatorIjE10deallocateEPjm:
  102|      3|      void deallocate(T* p, std::size_t n) { deallocate_memory(p, n, sizeof(T)); }
_ZN5Botan16secure_allocatorIjE8allocateEm:
   95|      3|      T* allocate(std::size_t n) { return static_cast<T*>(allocate_memory(n, sizeof(T))); }

_ZN5Botan12StreamCipher15write_keystreamENSt3__14spanIhLm18446744073709551615EEE:
   88|     54|      void write_keystream(std::span<uint8_t> out) { generate_keystream(out.data(), out.size()); }
_ZN5Botan12StreamCipher6set_ivEPKhm:
  168|      2|      void set_iv(const uint8_t iv[], size_t iv_len) { set_iv_bytes(iv, iv_len); }
_ZN5Botan12StreamCipher15keystream_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEET_m:
   98|      1|      T keystream_bytes(size_t bytes) {
   99|      1|         T out(bytes);
  100|      1|         write_keystream(out);
  101|      1|         return out;
  102|      1|      }

_ZN5Botan18unwrap_strong_typeIRmEEDcOT_:
  119|      4|[[nodiscard]] constexpr decltype(auto) unwrap_strong_type(T&& t) {
  120|      4|   if constexpr(!concepts::strong_type<std::remove_cvref_t<T>>) {
  121|       |      // If the parameter type isn't a strong type, return it as is.
  122|      4|      return std::forward<T>(t);
  123|       |   } else {
  124|       |      // Unwrap the strong type and return the underlying value.
  125|       |      return std::forward<T>(t).get();
  126|       |   }
  127|      4|}
_ZN5Botan16wrap_strong_typeImRmQoosr3stdE18constructible_fromIT_T0_Eaasr8conceptsE11strong_typeIS2_Esr3stdE18constructible_fromINS2_12wrapped_typeES3_EEEDcOS3_:
  144|  1.43k|[[nodiscard]] constexpr decltype(auto) wrap_strong_type(ParamT&& t) {
  145|  1.43k|   if constexpr(std::same_as<std::remove_cvref_t<ParamT>, T>) {
  146|       |      // Noop, if the parameter type already is the desired return type.
  147|  1.43k|      return std::forward<ParamT>(t);
  148|       |   } else if constexpr(std::constructible_from<T, ParamT>) {
  149|       |      // Implicit conversion from the parameter type to the return type.
  150|       |      return T{std::forward<ParamT>(t)};
  151|       |   } else {
  152|       |      // Explicitly calling the wrapped type's constructor to support
  153|       |      // implicit conversions on types that mark their constructors as explicit.
  154|       |      static_assert(concepts::strong_type<T> && std::constructible_from<typename T::wrapped_type, ParamT>);
  155|       |      return T{typename T::wrapped_type{std::forward<ParamT>(t)}};
  156|       |   }
  157|  1.43k|}
_ZN5Botan18unwrap_strong_typeIRjEEDcOT_:
  119|     32|[[nodiscard]] constexpr decltype(auto) unwrap_strong_type(T&& t) {
  120|     32|   if constexpr(!concepts::strong_type<std::remove_cvref_t<T>>) {
  121|       |      // If the parameter type isn't a strong type, return it as is.
  122|     32|      return std::forward<T>(t);
  123|       |   } else {
  124|       |      // Unwrap the strong type and return the underlying value.
  125|       |      return std::forward<T>(t).get();
  126|       |   }
  127|     32|}

_ZN5Botan24Key_Length_SpecificationC2Emmm:
   37|      4|            m_min_keylen(min_k), m_max_keylen(max_k > 0 ? max_k : min_k), m_keylen_mod(k_mod) {}
  ------------------
  |  Branch (37:47): [True: 4, False: 0]
  ------------------
_ZNK5Botan24Key_Length_Specification15valid_keylengthEm:
   44|      4|      bool valid_keylength(size_t length) const {
   45|      4|         return ((length >= m_min_keylen) && (length <= m_max_keylen) && (length % m_keylen_mod == 0));
  ------------------
  |  Branch (45:18): [True: 4, False: 0]
  |  Branch (45:46): [True: 4, False: 0]
  |  Branch (45:74): [True: 4, False: 0]
  ------------------
   46|      4|      }
_ZNK5Botan18SymmetricAlgorithm15valid_keylengthEm:
  143|      4|      bool valid_keylength(size_t length) const { return key_spec().valid_keylength(length); }
_ZNK5Botan18SymmetricAlgorithm23assert_key_material_setEv:
  180|     59|      void assert_key_material_set() const { assert_key_material_set(has_keying_material()); }
_ZNK5Botan18SymmetricAlgorithm23assert_key_material_setEb:
  186|     59|      void assert_key_material_set(bool predicate) const {
  187|     59|         if(!predicate) {
  ------------------
  |  Branch (187:13): [True: 0, False: 59]
  ------------------
  188|      0|            throw_key_not_set_error();
  189|      0|         }
  190|     59|      }
_ZN5Botan18SymmetricAlgorithmD2Ev:
   90|      2|      virtual ~SymmetricAlgorithm() = default;
_ZN5Botan18SymmetricAlgorithmC2Ev:
   88|      2|      SymmetricAlgorithm() = default;

LLVMFuzzerInitialize:
   28|      2|extern "C" int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) {
   29|       |   /*
   30|       |   * This disables the mlock pool, as overwrites within the pool are
   31|       |   * opaque to ASan or other instrumentation.
   32|       |   */
   33|      2|   ::setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1);
   34|      2|   return 0;
   35|      2|}
LLVMFuzzerTestOneInput:
   39|    849|extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
   40|    849|   if(len <= max_fuzzer_input_size) {
  ------------------
  |  Branch (40:7): [True: 839, False: 10]
  ------------------
   41|    839|      try {
   42|    839|         fuzz(std::span<const uint8_t>(in, len));
   43|    839|      } catch(const std::exception& e) {
   44|      0|         std::cerr << "Uncaught exception from fuzzer driver " << e.what() << "\n";
   45|      0|         abort();
   46|      0|      } catch(...) {
   47|      0|         std::cerr << "Uncaught exception from fuzzer driver (unknown type)\n";
   48|      0|         abort();
   49|      0|      }
   50|    839|   }
   51|    849|   return 0;
   52|    849|}
_Z10fuzzer_rngv:
   62|      1|inline Botan::RandomNumberGenerator& fuzzer_rng() {
   63|      1|   return *fuzzer_rng_as_shared();
   64|      1|}
_Z20fuzzer_rng_as_sharedv:
   56|      1|inline std::shared_ptr<Botan::RandomNumberGenerator> fuzzer_rng_as_shared() {
   57|      1|   static const std::shared_ptr<Botan::ChaCha_RNG> rng =
   58|      1|      std::make_shared<Botan::ChaCha_RNG>(Botan::secure_vector<uint8_t>(32));
   59|      1|   return rng;
   60|      1|}

_Z4fuzzNSt3__14spanIKhLm18446744073709551615EEE:
   12|    839|void fuzz(std::span<const uint8_t> in) {
   13|       |   // Ressol is mostly used for ECC point decompression so best to test smaller sizes
   14|    839|   static const size_t p_bits = 256;
   15|       |   // Use p == 1 mod 4 since sqrt modulo p == 3 mod 4 is a fast case
   16|    839|   static const Botan::BigInt p = random_prime(fuzzer_rng(), p_bits, 0, 1, 4);
   17|    839|   static auto mod_p = Botan::Barrett_Reduction::for_public_modulus(p);
   18|       |
   19|    839|   if(in.size() > p_bits / 8) {
  ------------------
  |  Branch (19:7): [True: 26, False: 813]
  ------------------
   20|     26|      return;
   21|     26|   }
   22|       |
   23|    813|   try {
   24|    813|      const Botan::BigInt a = Botan::BigInt::from_bytes(in);
   25|    813|      const Botan::BigInt a_sqrt = Botan::sqrt_modulo_prime(a, p);
   26|       |
   27|    813|      if(a_sqrt > 0) {
  ------------------
  |  Branch (27:10): [True: 530, False: 283]
  ------------------
   28|    530|         const Botan::BigInt a_redc = mod_p.reduce(a);
   29|    530|         const Botan::BigInt z = mod_p.square(a_sqrt);
   30|       |
   31|    530|         if(z != a_redc) {
  ------------------
  |  Branch (31:13): [True: 0, False: 530]
  ------------------
   32|      0|            FUZZER_WRITE_AND_CRASH("A = " << a.to_hex_string() << "\n"
  ------------------
  |  |   70|      0|   do {                                                                                                       \
  |  |   71|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; /* NOLINT(*-macro-paren*) */ \
  |  |   72|      0|      abort();                                                                                                \
  |  |   73|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (73:12): [Folded, False: 0]
  |  |  ------------------
  ------------------
   33|      0|                                          << "P = " << p.to_hex_string() << "\n"
   34|      0|                                          << "R = " << a_sqrt.to_hex_string() << "\n"
   35|      0|                                          << "Z = " << z.to_hex_string() << "\n");
   36|      0|         }
   37|    530|      }
   38|    813|   } catch(const Botan::Exception& e) {}
   39|    813|}

_ZN5Botan20Buffered_Computation5finalENSt3__14spanIhLm18446744073709551615EEE:
   54|      4|void Buffered_Computation::final(std::span<uint8_t> out) {
   55|      4|   BOTAN_ARG_CHECK(out.size() >= output_length(), "Output buffer has insufficient capacity");
  ------------------
  |  |   35|      4|   do {                                                          \
  |  |   36|      4|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      4|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 4]
  |  |  ------------------
  ------------------
   56|       |   // Pass exactly output_length() bytes so that an oversized buffer has the
   57|       |   // result written to its leading bytes with the remainder left untouched.
   58|      4|   final_result(out.first(output_length()));
   59|      4|}

_ZN5Botan18SymmetricAlgorithm7set_keyENSt3__14spanIKhLm18446744073709551615EEE:
   22|      4|void SymmetricAlgorithm::set_key(std::span<const uint8_t> key) {
   23|      4|   if(!valid_keylength(key.size())) {
  ------------------
  |  Branch (23:7): [True: 0, False: 4]
  ------------------
   24|      0|      throw Invalid_Key_Length(name(), key.size());
   25|      0|   }
   26|      4|   key_schedule(key);
   27|      4|}

_ZN5Botan12HashFunction6createENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_:
  112|      1|std::unique_ptr<HashFunction> HashFunction::create(std::string_view algo_spec, std::string_view provider) {
  113|       |#if defined(BOTAN_HAS_COMMONCRYPTO)
  114|       |   if(provider.empty() || provider == "commoncrypto") {
  115|       |      if(auto hash = make_commoncrypto_hash(algo_spec))
  116|       |         return hash;
  117|       |
  118|       |      if(!provider.empty())
  119|       |         return nullptr;
  120|       |   }
  121|       |#endif
  122|       |
  123|      1|   if(provider.empty() == false && provider != "base") {
  ------------------
  |  Branch (123:7): [True: 0, False: 1]
  |  Branch (123:36): [True: 0, False: 0]
  ------------------
  124|      0|      return nullptr;  // unknown provider
  125|      0|   }
  126|       |
  127|      1|#if defined(BOTAN_HAS_SHA1)
  128|      1|   if(algo_spec == "SHA-1") {
  ------------------
  |  Branch (128:7): [True: 0, False: 1]
  ------------------
  129|      0|      return std::make_unique<SHA_1>();
  130|      0|   }
  131|      1|#endif
  132|       |
  133|      1|#if defined(BOTAN_HAS_SHA2_32)
  134|      1|   if(algo_spec == "SHA-224") {
  ------------------
  |  Branch (134:7): [True: 0, False: 1]
  ------------------
  135|      0|      return std::make_unique<SHA_224>();
  136|      0|   }
  137|       |
  138|      1|   if(algo_spec == "SHA-256") {
  ------------------
  |  Branch (138:7): [True: 1, False: 0]
  ------------------
  139|      1|      return std::make_unique<SHA_256>();
  140|      1|   }
  141|      0|#endif
  142|       |
  143|      0|#if defined(BOTAN_HAS_SHA2_64)
  144|      0|   if(algo_spec == "SHA-384") {
  ------------------
  |  Branch (144:7): [True: 0, False: 0]
  ------------------
  145|      0|      return std::make_unique<SHA_384>();
  146|      0|   }
  147|       |
  148|      0|   if(algo_spec == "SHA-512") {
  ------------------
  |  Branch (148:7): [True: 0, False: 0]
  ------------------
  149|      0|      return std::make_unique<SHA_512>();
  150|      0|   }
  151|       |
  152|      0|   if(algo_spec == "SHA-512-256") {
  ------------------
  |  Branch (152:7): [True: 0, False: 0]
  ------------------
  153|      0|      return std::make_unique<SHA_512_256>();
  154|      0|   }
  155|      0|#endif
  156|       |
  157|      0|#if defined(BOTAN_HAS_RIPEMD_160)
  158|      0|   if(algo_spec == "RIPEMD-160") {
  ------------------
  |  Branch (158:7): [True: 0, False: 0]
  ------------------
  159|      0|      return std::make_unique<RIPEMD_160>();
  160|      0|   }
  161|      0|#endif
  162|       |
  163|      0|#if defined(BOTAN_HAS_WHIRLPOOL)
  164|      0|   if(algo_spec == "Whirlpool") {
  ------------------
  |  Branch (164:7): [True: 0, False: 0]
  ------------------
  165|      0|      return std::make_unique<Whirlpool>();
  166|      0|   }
  167|      0|#endif
  168|       |
  169|      0|#if defined(BOTAN_HAS_MD5)
  170|      0|   if(algo_spec == "MD5") {
  ------------------
  |  Branch (170:7): [True: 0, False: 0]
  ------------------
  171|      0|      return std::make_unique<MD5>();
  172|      0|   }
  173|      0|#endif
  174|       |
  175|      0|#if defined(BOTAN_HAS_MD4)
  176|      0|   if(algo_spec == "MD4") {
  ------------------
  |  Branch (176:7): [True: 0, False: 0]
  ------------------
  177|      0|      return std::make_unique<MD4>();
  178|      0|   }
  179|      0|#endif
  180|       |
  181|      0|#if defined(BOTAN_HAS_GOST_34_11)
  182|      0|   if(algo_spec == "GOST-R-34.11-94" || algo_spec == "GOST-34.11") {
  ------------------
  |  Branch (182:7): [True: 0, False: 0]
  |  Branch (182:41): [True: 0, False: 0]
  ------------------
  183|      0|      return std::make_unique<GOST_34_11>();
  184|      0|   }
  185|      0|#endif
  186|       |
  187|      0|#if defined(BOTAN_HAS_ADLER32)
  188|      0|   if(algo_spec == "Adler32") {
  ------------------
  |  Branch (188:7): [True: 0, False: 0]
  ------------------
  189|      0|      return std::make_unique<Adler32>();
  190|      0|   }
  191|      0|#endif
  192|       |
  193|      0|#if defined(BOTAN_HAS_ASCON_HASH256)
  194|      0|   if(algo_spec == "Ascon-Hash256") {
  ------------------
  |  Branch (194:7): [True: 0, False: 0]
  ------------------
  195|      0|      return std::make_unique<Ascon_Hash256>();
  196|      0|   }
  197|      0|#endif
  198|       |
  199|      0|#if defined(BOTAN_HAS_CRC24)
  200|      0|   if(algo_spec == "CRC24") {
  ------------------
  |  Branch (200:7): [True: 0, False: 0]
  ------------------
  201|      0|      return std::make_unique<CRC24>();
  202|      0|   }
  203|      0|#endif
  204|       |
  205|      0|#if defined(BOTAN_HAS_CRC32)
  206|      0|   if(algo_spec == "CRC32") {
  ------------------
  |  Branch (206:7): [True: 0, False: 0]
  ------------------
  207|      0|      return std::make_unique<CRC32>();
  208|      0|   }
  209|      0|#endif
  210|       |
  211|      0|#if defined(BOTAN_HAS_STREEBOG)
  212|      0|   if(algo_spec == "Streebog-256") {
  ------------------
  |  Branch (212:7): [True: 0, False: 0]
  ------------------
  213|      0|      return std::make_unique<Streebog>(256);
  214|      0|   }
  215|      0|   if(algo_spec == "Streebog-512") {
  ------------------
  |  Branch (215:7): [True: 0, False: 0]
  ------------------
  216|      0|      return std::make_unique<Streebog>(512);
  217|      0|   }
  218|      0|#endif
  219|       |
  220|      0|#if defined(BOTAN_HAS_SM3)
  221|      0|   if(algo_spec == "SM3") {
  ------------------
  |  Branch (221:7): [True: 0, False: 0]
  ------------------
  222|      0|      return std::make_unique<SM3>();
  223|      0|   }
  224|      0|#endif
  225|       |
  226|      0|   const AlgorithmSpec req(algo_spec);
  227|       |
  228|      0|#if defined(BOTAN_HAS_SKEIN_512)
  229|      0|   if(auto m = req.match("Skein-512({bits:int=512},{personalization:str=})")) {
  ------------------
  |  Branch (229:12): [True: 0, False: 0]
  ------------------
  230|      0|      return std::make_unique<Skein_512>(m->integer("bits"), m->str("personalization"));
  231|      0|   }
  232|      0|#endif
  233|       |
  234|      0|#if defined(BOTAN_HAS_BLAKE2B)
  235|      0|   if(auto m = req.match("BLAKE2b|Blake2b({bits:int=512})")) {
  ------------------
  |  Branch (235:12): [True: 0, False: 0]
  ------------------
  236|      0|      return std::make_unique<BLAKE2b>(m->integer("bits"));
  237|      0|   }
  238|      0|#endif
  239|       |
  240|      0|#if defined(BOTAN_HAS_BLAKE2S)
  241|      0|   if(auto m = req.match("BLAKE2s|Blake2s({bits:int=256})")) {
  ------------------
  |  Branch (241:12): [True: 0, False: 0]
  ------------------
  242|      0|      return std::make_unique<BLAKE2s>(m->integer("bits"));
  243|      0|   }
  244|      0|#endif
  245|       |
  246|      0|#if defined(BOTAN_HAS_KECCAK)
  247|      0|   if(auto m = req.match("Keccak-1600({bits:int=512})")) {
  ------------------
  |  Branch (247:12): [True: 0, False: 0]
  ------------------
  248|      0|      return std::make_unique<Keccak_1600>(m->integer("bits"));
  249|      0|   }
  250|      0|#endif
  251|       |
  252|      0|#if defined(BOTAN_HAS_SHA3)
  253|      0|   if(auto m = req.match("SHA-3({bits:int=512})")) {
  ------------------
  |  Branch (253:12): [True: 0, False: 0]
  ------------------
  254|      0|      return std::make_unique<SHA_3>(m->integer("bits"));
  255|      0|   }
  256|      0|#endif
  257|       |
  258|      0|#if defined(BOTAN_HAS_SHAKE)
  259|      0|   if(auto m = req.match("SHAKE-128({bits:int})")) {
  ------------------
  |  Branch (259:12): [True: 0, False: 0]
  ------------------
  260|      0|      return std::make_unique<SHAKE_128>(m->integer("bits"));
  261|      0|   }
  262|      0|   if(auto m = req.match("SHAKE-256({bits:int})")) {
  ------------------
  |  Branch (262:12): [True: 0, False: 0]
  ------------------
  263|      0|      return std::make_unique<SHAKE_256>(m->integer("bits"));
  264|      0|   }
  265|      0|#endif
  266|       |
  267|      0|#if defined(BOTAN_HAS_PARALLEL_HASH)
  268|      0|   if(auto m = req.match("Parallel({hash}...)")) {
  ------------------
  |  Branch (268:12): [True: 0, False: 0]
  ------------------
  269|      0|      std::vector<std::unique_ptr<HashFunction>> hashes;
  270|       |
  271|      0|      for(const auto& hash_spec : m->rest("hash")) {
  ------------------
  |  Branch (271:33): [True: 0, False: 0]
  ------------------
  272|      0|         auto h = HashFunction::create(hash_spec.to_string());
  273|      0|         if(!h) {
  ------------------
  |  Branch (273:13): [True: 0, False: 0]
  ------------------
  274|      0|            return nullptr;
  275|      0|         }
  276|      0|         hashes.push_back(std::move(h));
  277|      0|      }
  278|       |
  279|      0|      return std::make_unique<Parallel>(hashes);
  280|      0|   }
  281|      0|#endif
  282|       |
  283|      0|#if defined(BOTAN_HAS_TRUNCATED_HASH)
  284|      0|   if(auto m = req.match("Truncated({hash},{bits:int})")) {
  ------------------
  |  Branch (284:12): [True: 0, False: 0]
  ------------------
  285|      0|      auto hash = HashFunction::create(m->str("hash"));
  286|      0|      if(!hash) {
  ------------------
  |  Branch (286:10): [True: 0, False: 0]
  ------------------
  287|      0|         return nullptr;
  288|      0|      }
  289|       |
  290|      0|      return std::make_unique<Truncated_Hash>(std::move(hash), m->integer("bits"));
  291|      0|   }
  292|      0|#endif
  293|       |
  294|      0|#if defined(BOTAN_HAS_COMB4P)
  295|      0|   if(auto m = req.match("Comb4P({hash1},{hash2})")) {
  ------------------
  |  Branch (295:12): [True: 0, False: 0]
  ------------------
  296|      0|      auto h1 = HashFunction::create(m->str("hash1"));
  297|      0|      auto h2 = HashFunction::create(m->str("hash2"));
  298|       |
  299|      0|      if(h1 && h2) {
  ------------------
  |  Branch (299:10): [True: 0, False: 0]
  |  Branch (299:16): [True: 0, False: 0]
  ------------------
  300|      0|         return std::make_unique<Comb4P>(std::move(h1), std::move(h2));
  301|      0|      }
  302|      0|   }
  303|      0|#endif
  304|       |
  305|      0|   BOTAN_UNUSED(req);
  ------------------
  |  |  151|      0|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
  306|       |
  307|      0|   return nullptr;
  308|      0|}

_ZN5Botan7SHA_25615compress_digestERNSt3__16vectorIjNS_16secure_allocatorIjEEEENS1_4spanIKhLm18446744073709551615EEEm:
   59|     10|                                                             size_t blocks) {
   60|     10|#if defined(BOTAN_HAS_SHA2_32_X86)
   61|     10|   if(CPUID::has(CPUID::Feature::SHA)) {
  ------------------
  |  Branch (61:7): [True: 10, False: 0]
  ------------------
   62|     10|      return SHA_256::compress_digest_x86(digest, input, blocks);
   63|     10|   }
   64|      0|#endif
   65|       |
   66|       |#if defined(BOTAN_HAS_SHA2_32_ARMV8)
   67|       |   if(CPUID::has(CPUID::Feature::SHA2)) {
   68|       |      return SHA_256::compress_digest_armv8(digest, input, blocks);
   69|       |   }
   70|       |#endif
   71|       |
   72|      0|#if defined(BOTAN_HAS_SHA2_32_X86_AVX2)
   73|      0|   if(CPUID::has(CPUID::Feature::AVX2, CPUID::Feature::BMI)) {
  ------------------
  |  Branch (73:7): [True: 0, False: 0]
  ------------------
   74|      0|      return SHA_256::compress_digest_x86_avx2(digest, input, blocks);
   75|      0|   }
   76|      0|#endif
   77|       |
   78|      0|#if defined(BOTAN_HAS_SHA2_32_SIMD)
   79|      0|   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
  ------------------
  |  Branch (79:7): [True: 0, False: 0]
  ------------------
   80|      0|      return SHA_256::compress_digest_x86_simd(digest, input, blocks);
   81|      0|   }
   82|      0|#endif
   83|       |
   84|      0|   uint32_t A = digest[0];
   85|      0|   uint32_t B = digest[1];
   86|      0|   uint32_t C = digest[2];
   87|      0|   uint32_t D = digest[3];
   88|      0|   uint32_t E = digest[4];
   89|      0|   uint32_t F = digest[5];
   90|      0|   uint32_t G = digest[6];
   91|      0|   uint32_t H = digest[7];
   92|       |
   93|      0|   std::array<uint32_t, 16> W{};
   94|       |
   95|      0|   BufferSlicer in(input);
   96|       |
   97|      0|   for(size_t i = 0; i != blocks; ++i) {
  ------------------
  |  Branch (97:22): [True: 0, False: 0]
  ------------------
   98|      0|      load_be(W, in.take<block_bytes>());
   99|       |
  100|       |      // clang-format off
  101|       |
  102|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 0], W[14], W[ 9], W[ 1], SHA256_K[ 0]);
  103|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 1], W[15], W[10], W[ 2], SHA256_K[ 1]);
  104|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[ 2], W[ 0], W[11], W[ 3], SHA256_K[ 2]);
  105|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[ 3], W[ 1], W[12], W[ 4], SHA256_K[ 3]);
  106|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[ 4], W[ 2], W[13], W[ 5], SHA256_K[ 4]);
  107|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[ 5], W[ 3], W[14], W[ 6], SHA256_K[ 5]);
  108|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[ 6], W[ 4], W[15], W[ 7], SHA256_K[ 6]);
  109|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[ 7], W[ 5], W[ 0], W[ 8], SHA256_K[ 7]);
  110|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 8], W[ 6], W[ 1], W[ 9], SHA256_K[ 8]);
  111|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 9], W[ 7], W[ 2], W[10], SHA256_K[ 9]);
  112|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[10], W[ 8], W[ 3], W[11], SHA256_K[10]);
  113|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[11], W[ 9], W[ 4], W[12], SHA256_K[11]);
  114|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[12], W[10], W[ 5], W[13], SHA256_K[12]);
  115|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[13], W[11], W[ 6], W[14], SHA256_K[13]);
  116|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[14], W[12], W[ 7], W[15], SHA256_K[14]);
  117|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[15], W[13], W[ 8], W[ 0], SHA256_K[15]);
  118|       |
  119|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 0], W[14], W[ 9], W[ 1], SHA256_K[16]);
  120|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 1], W[15], W[10], W[ 2], SHA256_K[17]);
  121|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[ 2], W[ 0], W[11], W[ 3], SHA256_K[18]);
  122|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[ 3], W[ 1], W[12], W[ 4], SHA256_K[19]);
  123|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[ 4], W[ 2], W[13], W[ 5], SHA256_K[20]);
  124|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[ 5], W[ 3], W[14], W[ 6], SHA256_K[21]);
  125|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[ 6], W[ 4], W[15], W[ 7], SHA256_K[22]);
  126|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[ 7], W[ 5], W[ 0], W[ 8], SHA256_K[23]);
  127|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 8], W[ 6], W[ 1], W[ 9], SHA256_K[24]);
  128|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 9], W[ 7], W[ 2], W[10], SHA256_K[25]);
  129|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[10], W[ 8], W[ 3], W[11], SHA256_K[26]);
  130|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[11], W[ 9], W[ 4], W[12], SHA256_K[27]);
  131|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[12], W[10], W[ 5], W[13], SHA256_K[28]);
  132|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[13], W[11], W[ 6], W[14], SHA256_K[29]);
  133|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[14], W[12], W[ 7], W[15], SHA256_K[30]);
  134|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[15], W[13], W[ 8], W[ 0], SHA256_K[31]);
  135|       |
  136|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 0], W[14], W[ 9], W[ 1], SHA256_K[32]);
  137|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 1], W[15], W[10], W[ 2], SHA256_K[33]);
  138|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[ 2], W[ 0], W[11], W[ 3], SHA256_K[34]);
  139|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[ 3], W[ 1], W[12], W[ 4], SHA256_K[35]);
  140|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[ 4], W[ 2], W[13], W[ 5], SHA256_K[36]);
  141|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[ 5], W[ 3], W[14], W[ 6], SHA256_K[37]);
  142|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[ 6], W[ 4], W[15], W[ 7], SHA256_K[38]);
  143|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[ 7], W[ 5], W[ 0], W[ 8], SHA256_K[39]);
  144|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 8], W[ 6], W[ 1], W[ 9], SHA256_K[40]);
  145|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 9], W[ 7], W[ 2], W[10], SHA256_K[41]);
  146|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[10], W[ 8], W[ 3], W[11], SHA256_K[42]);
  147|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[11], W[ 9], W[ 4], W[12], SHA256_K[43]);
  148|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[12], W[10], W[ 5], W[13], SHA256_K[44]);
  149|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[13], W[11], W[ 6], W[14], SHA256_K[45]);
  150|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[14], W[12], W[ 7], W[15], SHA256_K[46]);
  151|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[15], W[13], W[ 8], W[ 0], SHA256_K[47]);
  152|       |
  153|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 0], W[14], W[ 9], W[ 1], SHA256_K[48]);
  154|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 1], W[15], W[10], W[ 2], SHA256_K[49]);
  155|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[ 2], W[ 0], W[11], W[ 3], SHA256_K[50]);
  156|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[ 3], W[ 1], W[12], W[ 4], SHA256_K[51]);
  157|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[ 4], W[ 2], W[13], W[ 5], SHA256_K[52]);
  158|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[ 5], W[ 3], W[14], W[ 6], SHA256_K[53]);
  159|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[ 6], W[ 4], W[15], W[ 7], SHA256_K[54]);
  160|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[ 7], W[ 5], W[ 0], W[ 8], SHA256_K[55]);
  161|      0|      SHA2_32_F(A, B, C, D, E, F, G, H, W[ 8], W[ 6], W[ 1], W[ 9], SHA256_K[56]);
  162|      0|      SHA2_32_F(H, A, B, C, D, E, F, G, W[ 9], W[ 7], W[ 2], W[10], SHA256_K[57]);
  163|      0|      SHA2_32_F(G, H, A, B, C, D, E, F, W[10], W[ 8], W[ 3], W[11], SHA256_K[58]);
  164|      0|      SHA2_32_F(F, G, H, A, B, C, D, E, W[11], W[ 9], W[ 4], W[12], SHA256_K[59]);
  165|      0|      SHA2_32_F(E, F, G, H, A, B, C, D, W[12], W[10], W[ 5], W[13], SHA256_K[60]);
  166|      0|      SHA2_32_F(D, E, F, G, H, A, B, C, W[13], W[11], W[ 6], W[14], SHA256_K[61]);
  167|      0|      SHA2_32_F(C, D, E, F, G, H, A, B, W[14], W[12], W[ 7], W[15], SHA256_K[62]);
  168|      0|      SHA2_32_F(B, C, D, E, F, G, H, A, W[15], W[13], W[ 8], W[ 0], SHA256_K[63]);
  169|       |
  170|       |      // clang-format on
  171|       |
  172|      0|      A = (digest[0] += A);
  173|      0|      B = (digest[1] += B);
  174|      0|      C = (digest[2] += C);
  175|      0|      D = (digest[3] += D);
  176|      0|      E = (digest[4] += E);
  177|      0|      F = (digest[5] += F);
  178|      0|      G = (digest[6] += G);
  179|      0|      H = (digest[7] += H);
  180|      0|   }
  181|      0|}
_ZN5Botan7SHA_25610compress_nERNSt3__16vectorIjNS_16secure_allocatorIjEEEENS1_4spanIKhLm18446744073709551615EEEm:
  215|     10|void SHA_256::compress_n(digest_type& digest, std::span<const uint8_t> input, size_t blocks) {
  216|     10|   SHA_256::compress_digest(digest, input, blocks);
  217|     10|}
_ZN5Botan7SHA_2564initERNSt3__16vectorIjNS_16secure_allocatorIjEEEE:
  219|      7|void SHA_256::init(digest_type& digest) {
  220|      7|   digest.assign({0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19});
  221|      7|}
_ZN5Botan7SHA_2568add_dataENSt3__14spanIKhLm18446744073709551615EEE:
  231|      9|void SHA_256::add_data(std::span<const uint8_t> input) {
  232|      9|   m_md.update(input);
  233|      9|}
_ZN5Botan7SHA_25612final_resultENSt3__14spanIhLm18446744073709551615EEE:
  235|      4|void SHA_256::final_result(std::span<uint8_t> output) {
  236|      4|   m_md.final(output);
  237|      4|}

_ZN5Botan7SHA_25619compress_digest_x86ERNSt3__16vectorIjNS_16secure_allocatorIjEEEENS1_4spanIKhLm18446744073709551615EEEm:
   59|     10|                                                                                    size_t blocks) {
   60|     10|   const uint8_t* input = input_span.data();
   61|       |
   62|     10|   SIMD_4x32 S0 = SIMD_4x32::load_le(&digest[0]);  // NOLINT(*container-data-pointer)
   63|     10|   SIMD_4x32 S1 = SIMD_4x32::load_le(&digest[4]);
   64|       |
   65|     10|   sha256_permute_state(S0, S1);
   66|       |
   67|     20|   while(blocks > 0) {
  ------------------
  |  Branch (67:10): [True: 10, False: 10]
  ------------------
   68|     10|      const auto S0_SAVE = S0;
   69|     10|      const auto S1_SAVE = S1;
   70|       |
   71|     10|      auto W0 = SIMD_4x32::load_be(input);
   72|     10|      auto W1 = SIMD_4x32::load_be(input + 16);
   73|     10|      auto W2 = SIMD_4x32::load_be(input + 32);
   74|     10|      auto W3 = SIMD_4x32::load_be(input + 48);
   75|       |
   76|     10|      sha256_rnds4(S0, S1, W0, SIMD_4x32::load_le(&SHA256_K[0]));
   77|     10|      sha256_rnds4(S0, S1, W1, SIMD_4x32::load_le(&SHA256_K[4]));
   78|     10|      sha256_rnds4(S0, S1, W2, SIMD_4x32::load_le(&SHA256_K[8]));
   79|     10|      sha256_rnds4(S0, S1, W3, SIMD_4x32::load_le(&SHA256_K[12]));
   80|       |
   81|     10|      W0 = SIMD_4x32(_mm_sha256msg1_epu32(W0.raw(), W1.raw()));
   82|     10|      W1 = SIMD_4x32(_mm_sha256msg1_epu32(W1.raw(), W2.raw()));
   83|       |
   84|     10|      sha256_msg_exp(W2, W3, W0, W1);
   85|       |
   86|     10|      sha256_rnds4(S0, S1, W0, SIMD_4x32::load_le(&SHA256_K[4 * 4]));
   87|     10|      sha256_rnds4(S0, S1, W1, SIMD_4x32::load_le(&SHA256_K[4 * 5]));
   88|       |
   89|     10|      sha256_msg_exp(W0, W1, W2, W3);
   90|       |
   91|     10|      sha256_rnds4(S0, S1, W2, SIMD_4x32::load_le(&SHA256_K[4 * 6]));
   92|     10|      sha256_rnds4(S0, S1, W3, SIMD_4x32::load_le(&SHA256_K[4 * 7]));
   93|       |
   94|     10|      sha256_msg_exp(W2, W3, W0, W1);
   95|       |
   96|     10|      sha256_rnds4(S0, S1, W0, SIMD_4x32::load_le(&SHA256_K[4 * 8]));
   97|     10|      sha256_rnds4(S0, S1, W1, SIMD_4x32::load_le(&SHA256_K[4 * 9]));
   98|       |
   99|     10|      sha256_msg_exp(W0, W1, W2, W3);
  100|       |
  101|     10|      sha256_rnds4(S0, S1, W2, SIMD_4x32::load_le(&SHA256_K[4 * 10]));
  102|     10|      sha256_rnds4(S0, S1, W3, SIMD_4x32::load_le(&SHA256_K[4 * 11]));
  103|       |
  104|     10|      sha256_msg_exp(W2, W3, W0, W1);
  105|       |
  106|     10|      sha256_rnds4(S0, S1, W0, SIMD_4x32::load_le(&SHA256_K[4 * 12]));
  107|     10|      sha256_rnds4(S0, S1, W1, SIMD_4x32::load_le(&SHA256_K[4 * 13]));
  108|       |
  109|     10|      sha256_msg_exp(W0, W1, W2, W3);
  110|       |
  111|     10|      sha256_rnds4(S0, S1, W2, SIMD_4x32::load_le(&SHA256_K[4 * 14]));
  112|     10|      sha256_rnds4(S0, S1, W3, SIMD_4x32::load_le(&SHA256_K[4 * 15]));
  113|       |
  114|       |      // Add values back to state
  115|     10|      S0 += S0_SAVE;
  116|     10|      S1 += S1_SAVE;
  117|       |
  118|     10|      input += 64;
  119|     10|      blocks--;
  120|     10|   }
  121|       |
  122|     10|   sha256_permute_state(S1, S0);
  123|       |
  124|     10|   S0.store_le(&digest[0]);  // NOLINT(*container-data-pointer)
  125|     10|   S1.store_le(&digest[4]);
  126|     10|}
sha2_32_x86.cpp:_ZN5Botan12_GLOBAL__N_120sha256_permute_stateERNS_9SIMD_4x32ES2_:
   44|     20|BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha256_permute_state(SIMD_4x32& S0, SIMD_4x32& S1) {
   45|     20|   S0 = SIMD_4x32(_mm_shuffle_epi32(S0.raw(), 0b10110001));  // CDAB
   46|     20|   S1 = SIMD_4x32(_mm_shuffle_epi32(S1.raw(), 0b00011011));  // EFGH
   47|       |
   48|     20|   const auto T = SIMD_4x32::alignr8(S0, S1);                  // ABEF
   49|       |   S1 = SIMD_4x32(_mm_blend_epi16(S1.raw(), S0.raw(), 0xF0));  // CDGH
   50|     20|   S0 = T;
   51|     20|}
sha2_32_x86.cpp:_ZN5Botan12_GLOBAL__N_112sha256_rnds4ERNS_9SIMD_4x32ES2_RKS1_S4_:
   28|    160|                                                        const SIMD_4x32& k) {
   29|    160|   const auto mk = msg + k;
   30|    160|   S1 = SIMD_4x32(_mm_sha256rnds2_epu32(S1.raw(), S0.raw(), mk.raw()));
   31|    160|   S0 = SIMD_4x32(_mm_sha256rnds2_epu32(S0.raw(), S1.raw(), mk.shift_elems_right<2>().raw()));
   32|    160|}
sha2_32_x86.cpp:_ZN5Botan12_GLOBAL__N_114sha256_msg_expERNS_9SIMD_4x32ES2_S2_S2_:
   34|     60|BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha256_msg_exp(SIMD_4x32& W0, SIMD_4x32& W1, SIMD_4x32& W2, SIMD_4x32& W3) {
   35|     60|   W2 += SIMD_4x32::alignr4(W1, W0);
   36|     60|   W0 = SIMD_4x32(_mm_sha256msg1_epu32(W0.raw(), W1.raw()));
   37|     60|   W2 = SIMD_4x32(_mm_sha256msg2_epu32(W2.raw(), W1.raw()));
   38|       |
   39|     60|   W3 += SIMD_4x32::alignr4(W2, W1);
   40|     60|   W1 = SIMD_4x32(_mm_sha256msg1_epu32(W1.raw(), W2.raw()));
   41|     60|   W3 = SIMD_4x32(_mm_sha256msg2_epu32(W3.raw(), W2.raw()));
   42|     60|}

_ZN5Botan4HMAC8add_dataENSt3__14spanIKhLm18446744073709551615EEE:
   21|      1|void HMAC::add_data(std::span<const uint8_t> input) {
   22|      1|   assert_key_material_set();
   23|      1|   m_hash->update(input);
   24|      1|}
_ZN5Botan4HMAC12final_resultENSt3__14spanIhLm18446744073709551615EEE:
   29|      2|void HMAC::final_result(std::span<uint8_t> mac) {
   30|      2|   assert_key_material_set();
   31|      2|   m_hash->final(mac);
   32|      2|   m_hash->update(m_okey);
   33|      2|   m_hash->update(mac.first(m_hash_output_length));
   34|      2|   m_hash->final(mac);
   35|      2|   m_hash->update(m_ikey);
   36|      2|}
_ZNK5Botan4HMAC8key_specEv:
   48|      2|Key_Length_Specification HMAC::key_spec() const {
   49|       |   // Support very long lengths for things like PBKDF2 and the TLS PRF
   50|      2|   return Key_Length_Specification(0, 8192);
   51|      2|}
_ZNK5Botan4HMAC13output_lengthEv:
   53|      4|size_t HMAC::output_length() const {
   54|      4|   return m_hash_output_length;
   55|      4|}
_ZNK5Botan4HMAC19has_keying_materialEv:
   57|      3|bool HMAC::has_keying_material() const {
   58|      3|   return !m_okey.empty();
   59|      3|}
_ZN5Botan4HMAC12key_scheduleENSt3__14spanIKhLm18446744073709551615EEE:
   64|      2|void HMAC::key_schedule(std::span<const uint8_t> key) {
   65|      2|   const uint8_t ipad = 0x36;
   66|      2|   const uint8_t opad = 0x5C;
   67|       |
   68|      2|   m_hash->clear();
   69|       |
   70|      2|   m_ikey.resize(m_hash_block_size);
   71|      2|   m_okey.resize(m_hash_block_size);
   72|       |
   73|      2|   clear_mem(m_ikey.data(), m_ikey.size());
   74|      2|   clear_mem(m_okey.data(), m_okey.size());
   75|       |
   76|       |   /*
   77|       |   * Sometimes the HMAC key length itself is sensitive, as with PBKDF2 where it
   78|       |   * reveals the length of the passphrase. Make some attempt to hide this to
   79|       |   * side channels. Clearly if the secret is longer than the block size then the
   80|       |   * branch to hash first reveals that. In addition, counting the number of
   81|       |   * compression functions executed reveals the size at the granularity of the
   82|       |   * hash function's block size.
   83|       |   *
   84|       |   * The greater concern is for smaller keys; being able to detect when a
   85|       |   * passphrase is say 4 bytes may assist choosing weaker targets. Even though
   86|       |   * the loop bounds are constant, we can only actually read key[0..length] so
   87|       |   * it doesn't seem possible to make this computation truly constant time.
   88|       |   *
   89|       |   * We don't mind leaking if the length is exactly zero since that's
   90|       |   * trivial to simply check.
   91|       |   */
   92|       |
   93|      2|   if(key.size() > m_hash_block_size) {
  ------------------
  |  Branch (93:7): [True: 0, False: 2]
  ------------------
   94|      0|      m_hash->update(key);
   95|      0|      m_hash->final(m_ikey.data());
   96|      2|   } else if(key.size() >= 20) {
  ------------------
  |  Branch (96:14): [True: 2, False: 0]
  ------------------
   97|       |      // For long keys we just leak the length either it is a cryptovariable
   98|       |      // or a long enough password that just the length is not a useful signal
   99|      2|      copy_mem(std::span{m_ikey}.first(key.size()), key);
  100|      2|   } else if(!key.empty()) {
  ------------------
  |  Branch (100:14): [True: 0, False: 0]
  ------------------
  101|      0|      for(size_t i = 0, i_mod_length = 0; i != m_hash_block_size; ++i) {
  ------------------
  |  Branch (101:43): [True: 0, False: 0]
  ------------------
  102|       |         /*
  103|       |         access key[i % length] but avoiding division due to variable
  104|       |         time computation on some processors.
  105|       |         */
  106|      0|         const auto needs_reduction = CT::Mask<size_t>::is_lte(key.size(), i_mod_length);
  107|      0|         i_mod_length = needs_reduction.select(0, i_mod_length);
  108|      0|         const uint8_t kb = key[i_mod_length];
  109|       |
  110|      0|         const auto in_range = CT::Mask<size_t>::is_lt(i, key.size());
  111|      0|         m_ikey[i] = static_cast<uint8_t>(in_range.if_set_return(kb));
  112|      0|         i_mod_length += 1;
  113|      0|      }
  114|      0|   }
  115|       |
  116|    130|   for(size_t i = 0; i != m_hash_block_size; ++i) {
  ------------------
  |  Branch (116:22): [True: 128, False: 2]
  ------------------
  117|    128|      m_ikey[i] ^= ipad;
  118|    128|      m_okey[i] = m_ikey[i] ^ ipad ^ opad;
  119|    128|   }
  120|       |
  121|      2|   m_hash->update(m_ikey);
  122|      2|}
_ZN5Botan4HMACC2ENSt3__110unique_ptrINS_12HashFunctionENS1_14default_deleteIS3_EEEE:
  151|      1|      m_hash(std::move(hash)),
  152|      1|      m_hash_output_length(m_hash->output_length()),
  153|      1|      m_hash_block_size(m_hash->hash_block_size()) {
  154|      1|   BOTAN_ARG_CHECK(m_hash_output_length >= 8, "HMAC is not compatible with this hash function");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      1|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
  155|      1|   BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length, "HMAC is not compatible with this hash function");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      1|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
  156|      1|}

_ZN5Botan25MessageAuthenticationCode6createENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_:
   52|      1|                                                                             std::string_view provider) {
   53|      1|   const AlgorithmSpec req(algo_spec);
   54|       |
   55|      1|#if defined(BOTAN_HAS_BLAKE2BMAC)
   56|      1|   if(auto m = req.match("BLAKE2b|Blake2b({bits:int=512})")) {
  ------------------
  |  Branch (56:12): [True: 0, False: 1]
  ------------------
   57|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (57:10): [True: 0, False: 0]
  |  Branch (57:30): [True: 0, False: 0]
  ------------------
   58|      0|         return std::make_unique<BLAKE2bMAC>(m->integer("bits"));
   59|      0|      }
   60|      0|   }
   61|      1|#endif
   62|       |
   63|      1|#if defined(BOTAN_HAS_GMAC)
   64|      1|   if(auto m = req.match("GMAC({cipher})")) {
  ------------------
  |  Branch (64:12): [True: 0, False: 1]
  ------------------
   65|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (65:10): [True: 0, False: 0]
  |  Branch (65:30): [True: 0, False: 0]
  ------------------
   66|      0|         if(auto bc = BlockCipher::create(m->str("cipher"))) {
  ------------------
  |  Branch (66:18): [True: 0, False: 0]
  ------------------
   67|      0|            return std::make_unique<GMAC>(std::move(bc));
   68|      0|         }
   69|      0|      }
   70|      0|   }
   71|      1|#endif
   72|       |
   73|      1|#if defined(BOTAN_HAS_HMAC)
   74|      1|   if(auto m = req.match("HMAC({hash})")) {
  ------------------
  |  Branch (74:12): [True: 1, False: 0]
  ------------------
   75|      1|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (75:10): [True: 1, False: 0]
  |  Branch (75:30): [True: 0, False: 0]
  ------------------
   76|      1|         if(auto hash = HashFunction::create(m->str("hash"))) {
  ------------------
  |  Branch (76:18): [True: 1, False: 0]
  ------------------
   77|      1|            return std::make_unique<HMAC>(std::move(hash));
   78|      1|         }
   79|      1|      }
   80|      1|   }
   81|      0|#endif
   82|       |
   83|      0|#if defined(BOTAN_HAS_POLY1305)
   84|      0|   if(req.matches("Poly1305")) {
  ------------------
  |  Branch (84:7): [True: 0, False: 0]
  ------------------
   85|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (85:10): [True: 0, False: 0]
  |  Branch (85:30): [True: 0, False: 0]
  ------------------
   86|      0|         return std::make_unique<Poly1305>();
   87|      0|      }
   88|      0|   }
   89|      0|#endif
   90|       |
   91|      0|#if defined(BOTAN_HAS_SIPHASH)
   92|      0|   if(auto m = req.match("SipHash({c:int=2},{d:int=4})")) {
  ------------------
  |  Branch (92:12): [True: 0, False: 0]
  ------------------
   93|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (93:10): [True: 0, False: 0]
  |  Branch (93:30): [True: 0, False: 0]
  ------------------
   94|      0|         return std::make_unique<SipHash>(m->integer("c"), m->integer("d"));
   95|      0|      }
   96|      0|   }
   97|      0|#endif
   98|       |
   99|      0|#if defined(BOTAN_HAS_CMAC)
  100|      0|   if(auto m = req.match("CMAC|OMAC({cipher})")) {
  ------------------
  |  Branch (100:12): [True: 0, False: 0]
  ------------------
  101|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (101:10): [True: 0, False: 0]
  |  Branch (101:30): [True: 0, False: 0]
  ------------------
  102|      0|         if(auto bc = BlockCipher::create(m->str("cipher"))) {
  ------------------
  |  Branch (102:18): [True: 0, False: 0]
  ------------------
  103|      0|            return std::make_unique<CMAC>(std::move(bc));
  104|      0|         }
  105|      0|      }
  106|      0|   }
  107|      0|#endif
  108|       |
  109|      0|#if defined(BOTAN_HAS_ANSI_X919_MAC)
  110|      0|   if(req.matches("X9.19-MAC")) {
  ------------------
  |  Branch (110:7): [True: 0, False: 0]
  ------------------
  111|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (111:10): [True: 0, False: 0]
  |  Branch (111:30): [True: 0, False: 0]
  ------------------
  112|      0|         return std::make_unique<ANSI_X919_MAC>();
  113|      0|      }
  114|      0|   }
  115|      0|#endif
  116|       |
  117|      0|#if defined(BOTAN_HAS_KMAC)
  118|      0|   if(auto m = req.match("KMAC-128({bits:int})")) {
  ------------------
  |  Branch (118:12): [True: 0, False: 0]
  ------------------
  119|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (119:10): [True: 0, False: 0]
  |  Branch (119:30): [True: 0, False: 0]
  ------------------
  120|      0|         return std::make_unique<KMAC128>(m->integer("bits"));
  121|      0|      }
  122|      0|   }
  123|       |
  124|      0|   if(auto m = req.match("KMAC-256({bits:int})")) {
  ------------------
  |  Branch (124:12): [True: 0, False: 0]
  ------------------
  125|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (125:10): [True: 0, False: 0]
  |  Branch (125:30): [True: 0, False: 0]
  ------------------
  126|      0|         return std::make_unique<KMAC256>(m->integer("bits"));
  127|      0|      }
  128|      0|   }
  129|      0|#endif
  130|       |
  131|      0|   BOTAN_UNUSED(req);
  ------------------
  |  |  151|      0|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
  132|      0|   BOTAN_UNUSED(provider);
  ------------------
  |  |  151|      0|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
  133|       |
  134|      0|   return nullptr;
  135|      0|}
_ZN5Botan25MessageAuthenticationCode15create_or_throwENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_:
  143|      1|                                                                                      std::string_view provider) {
  144|      1|   if(auto mac = MessageAuthenticationCode::create(algo, provider)) {
  ------------------
  |  Branch (144:12): [True: 1, False: 0]
  ------------------
  145|      1|      return mac;
  146|      1|   }
  147|      0|   throw Lookup_Error("MAC", algo, provider);
  148|      1|}

_ZN5Botan6BigInt3addEPKmmNS0_4SignE:
   32|    628|BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign) {
   33|    628|   const size_t x_sw = sig_words();
   34|       |
   35|    628|   grow_to(std::max(x_sw, y_words) + 1);
   36|       |
   37|    628|   if(sign() == y_sign) {
  ------------------
  |  Branch (37:7): [True: 97, False: 531]
  ------------------
   38|     97|      const word carry = bigint_add2(mutable_data(), size() - 1, y, y_words);
   39|     97|      mutable_data()[size() - 1] += carry;
   40|    531|   } else {
   41|    531|      const int32_t relative_size = bigint_cmp(_data(), x_sw, y, y_words);
   42|       |
   43|    531|      if(relative_size >= 0) {
  ------------------
  |  Branch (43:10): [True: 529, False: 2]
  ------------------
   44|       |         // *this >= y
   45|    529|         bigint_sub2(mutable_data(), x_sw, y, y_words);
   46|    529|      } else {
   47|       |         // *this < y: compute *this = y - *this
   48|      2|         bigint_sub2_rev(mutable_data(), y, y_words);
   49|      2|      }
   50|       |
   51|    531|      if(relative_size < 0) {
  ------------------
  |  Branch (51:10): [True: 2, False: 529]
  ------------------
   52|      2|         set_sign(y_sign);
   53|    529|      } else if(relative_size == 0) {
  ------------------
  |  Branch (53:17): [True: 0, False: 529]
  ------------------
   54|      0|         set_sign(Positive);
   55|      0|      }
   56|    531|   }
   57|       |
   58|    628|   return (*this);
   59|    628|}
_ZN5Botan6BigIntrMERKS0_:
  232|  20.9k|BigInt& BigInt::operator%=(const BigInt& mod) {
  233|  20.9k|   return (*this = (*this) % mod);
  234|  20.9k|}
_ZN5Botan6BigIntrSEm:
  287|  23.2k|BigInt& BigInt::operator>>=(size_t shift) {
  288|  23.2k|   bigint_shr1(m_data.mutable_data(), m_data.size(), shift);
  289|       |
  290|  23.2k|   if(sig_words() == 0 && m_signedness == Negative) {
  ------------------
  |  Branch (290:7): [True: 0, False: 23.2k]
  |  Branch (290:27): [True: 0, False: 0]
  ------------------
  291|      0|      m_signedness = Positive;
  292|      0|   }
  293|       |
  294|  23.2k|   return (*this);
  295|  23.2k|}

_ZN5Botan6BigInt4add2ERKS0_PKmmNS0_4SignE:
   20|  1.09k|BigInt BigInt::add2(const BigInt& x, const word y[], size_t y_size, BigInt::Sign y_sign) {
   21|  1.09k|   const size_t x_sw = x.sig_words();
   22|       |
   23|  1.09k|   BigInt z = BigInt::with_capacity(std::max(x_sw, y_size) + 1);
   24|       |
   25|  1.09k|   if(x.sign() == y_sign) {
  ------------------
  |  Branch (25:7): [True: 507, False: 589]
  ------------------
   26|    507|      const word carry = bigint_add3(z.mutable_data(), x._data(), x_sw, y, y_size);
   27|    507|      z.mutable_data()[std::max(x_sw, y_size)] += carry;
   28|    507|      z.set_sign(x.sign());
   29|    589|   } else {
   30|    589|      const int32_t relative_size = bigint_cmp(x.data(), x_sw, y, y_size);
   31|       |
   32|    589|      if(relative_size < 0) {
  ------------------
  |  Branch (32:10): [True: 0, False: 589]
  ------------------
   33|       |         // x < y so z = abs(y - x)
   34|       |         // NOLINTNEXTLINE(*-suspicious-call-argument) intentionally swapping x and y here
   35|      0|         bigint_sub3(z.mutable_data(), y, y_size, x.data(), x_sw);
   36|      0|         z.set_sign(y_sign);
   37|    589|      } else if(relative_size == 0) {
  ------------------
  |  Branch (37:17): [True: 0, False: 589]
  ------------------
   38|       |         // Positive zero (nothing to do in this case)
   39|    589|      } else {
   40|       |         /*
   41|       |         * We know at this point that x >= y so if y_size is larger than
   42|       |         * x_sw, we are guaranteed they are just leading zeros which can
   43|       |         * be ignored
   44|       |         */
   45|    589|         y_size = std::min(x_sw, y_size);
   46|    589|         bigint_sub3(z.mutable_data(), x.data(), x_sw, y, y_size);
   47|    589|         z.set_sign(x.sign());
   48|    589|      }
   49|    589|   }
   50|       |
   51|  1.09k|   return z;
   52|  1.09k|}
_ZN5BotanrmERKNS_6BigIntES2_:
  134|  20.9k|BigInt operator%(const BigInt& n, const BigInt& mod) {
  135|  20.9k|   if(mod.is_zero()) {
  ------------------
  |  Branch (135:7): [True: 0, False: 20.9k]
  ------------------
  136|      0|      throw Invalid_Argument("BigInt::operator% divide by zero");
  137|      0|   }
  138|  20.9k|   if(mod.signum() < 0) {
  ------------------
  |  Branch (138:7): [True: 0, False: 20.9k]
  ------------------
  139|      0|      throw Invalid_Argument("BigInt::operator% modulus must be > 0");
  140|      0|   }
  141|  20.9k|   if(n.signum() >= 0 && mod.signum() >= 0 && n < mod) {
  ------------------
  |  Branch (141:7): [True: 20.9k, False: 2]
  |  Branch (141:26): [True: 20.9k, False: 0]
  |  Branch (141:47): [True: 0, False: 20.9k]
  ------------------
  142|      0|      return n;
  143|      0|   }
  144|       |
  145|  20.9k|   if(mod.sig_words() == 1) {
  ------------------
  |  Branch (145:7): [True: 15.8k, False: 5.09k]
  ------------------
  146|  15.8k|      return BigInt::from_word(n % mod.word_at(0));
  147|  15.8k|   }
  148|       |
  149|  5.09k|   BigInt q;
  150|  5.09k|   BigInt r;
  151|  5.09k|   ct_divide(n, mod, q, r);
  152|  5.09k|   return r;
  153|  20.9k|}
_ZN5BotanrmERKNS_6BigIntEm:
  158|  27.2k|word operator%(const BigInt& n, word mod) {
  159|  27.2k|   if(mod == 0) {
  ------------------
  |  Branch (159:7): [True: 0, False: 27.2k]
  ------------------
  160|      0|      throw Invalid_Argument("BigInt::operator% divide by zero");
  161|      0|   }
  162|       |
  163|  27.2k|   if(mod == 1) {
  ------------------
  |  Branch (163:7): [True: 0, False: 27.2k]
  ------------------
  164|      0|      return 0;
  165|      0|   }
  166|       |
  167|  27.2k|   word remainder = 0;
  168|       |
  169|  27.2k|   if(n.signum() >= 0 && is_power_of_2(mod)) {
  ------------------
  |  Branch (169:7): [True: 27.2k, False: 0]
  |  Branch (169:26): [True: 11.3k, False: 15.8k]
  ------------------
  170|  11.3k|      remainder = (n.word_at(0) & (mod - 1));
  171|  15.8k|   } else {
  172|  15.8k|      const auto redc_mod = divide_precomp<word>::setup_vartime(mod);
  173|  15.8k|      const size_t sw = n.sig_words();
  174|  34.9k|      for(size_t i = sw; i > 0; --i) {
  ------------------
  |  Branch (174:26): [True: 19.0k, False: 15.8k]
  ------------------
  175|  19.0k|         remainder = redc_mod.mod_2to1(remainder, n.word_at(i - 1));
  176|  19.0k|      }
  177|  15.8k|   }
  178|       |
  179|  27.2k|   if(remainder != 0 && n.sign() == BigInt::Negative) {
  ------------------
  |  Branch (179:7): [True: 27.2k, False: 0]
  |  Branch (179:25): [True: 0, False: 27.2k]
  ------------------
  180|      0|      return mod - remainder;
  181|      0|   }
  182|  27.2k|   return remainder;
  183|  27.2k|}
_ZN5BotanlsERKNS_6BigIntEm:
  188|    463|BigInt operator<<(const BigInt& x, size_t shift) {
  189|    463|   if(shift >= 65536) {
  ------------------
  |  Branch (189:7): [True: 0, False: 463]
  ------------------
  190|      0|      throw Invalid_Argument("BigInt left shift count too large");
  191|      0|   }
  192|       |
  193|    463|   if(x.is_zero()) {
  ------------------
  |  Branch (193:7): [True: 0, False: 463]
  ------------------
  194|      0|      return BigInt::zero();
  195|      0|   }
  196|       |
  197|    463|   const size_t x_sw = x.sig_words();
  198|       |
  199|    463|   const size_t new_size = x_sw + shift / WordInfo<word>::bits + 1;
  200|    463|   BigInt y = BigInt::with_capacity(new_size);
  201|    463|   bigint_shl2(y.mutable_data(), new_size, x._data(), x_sw, shift);
  202|    463|   y.set_sign(x.sign());
  203|    463|   return y;
  204|    463|}
_ZN5BotanrsERKNS_6BigIntEm:
  209|    544|BigInt operator>>(const BigInt& x, size_t shift) {
  210|    544|   const size_t shift_words = shift / WordInfo<word>::bits;
  211|    544|   const size_t x_sw = x.sig_words();
  212|       |
  213|    544|   if(shift_words >= x_sw) {
  ------------------
  |  Branch (213:7): [True: 0, False: 544]
  ------------------
  214|      0|      return BigInt::zero();
  215|      0|   }
  216|       |
  217|    544|   const size_t new_size = x_sw - shift_words;
  218|    544|   BigInt y = BigInt::with_capacity(new_size);
  219|    544|   bigint_shr2(y.mutable_data(), new_size, x._data(), x_sw, shift);
  220|       |
  221|    544|   if(x.signum() < 0 && y.is_zero()) {
  ------------------
  |  Branch (221:7): [True: 0, False: 544]
  |  Branch (221:25): [True: 0, False: 0]
  ------------------
  222|      0|      y.set_sign(BigInt::Positive);
  223|    544|   } else {
  224|    544|      y.set_sign(x.sign());
  225|    544|   }
  226|       |
  227|    544|   return y;
  228|    544|}

_ZN5Botan6BigInt9randomizeERNS_21RandomNumberGeneratorEmb:
   20|     53|void BigInt::randomize(RandomNumberGenerator& rng, size_t bitsize, bool set_high_bit) {
   21|     53|   set_sign(Positive);
   22|       |
   23|     53|   if(bitsize == 0) {
  ------------------
  |  Branch (23:7): [True: 0, False: 53]
  ------------------
   24|      0|      clear();
   25|     53|   } else {
   26|     53|      secure_vector<uint8_t> array = rng.random_vec(ceil_tobytes(bitsize));
   27|       |
   28|       |      // Always cut unwanted bits
   29|     53|      if(bitsize % 8 > 0) {
  ------------------
  |  Branch (29:10): [True: 0, False: 53]
  ------------------
   30|      0|         array[0] &= 0xFF >> (8 - (bitsize % 8));
   31|      0|      }
   32|       |
   33|       |      // Set the highest bit if wanted
   34|     53|      if(set_high_bit) {
  ------------------
  |  Branch (34:10): [True: 1, False: 52]
  ------------------
   35|      1|         array[0] |= 0x80 >> ((bitsize % 8) > 0 ? (8 - bitsize % 8) : 0);
  ------------------
  |  Branch (35:31): [True: 0, False: 1]
  ------------------
   36|      1|      }
   37|       |
   38|     53|      assign_from_bytes(array);
   39|     53|   }
   40|     53|}
_ZN5Botan6BigInt14random_integerERNS_21RandomNumberGeneratorERKS0_S4_:
   45|     86|BigInt BigInt::random_integer(RandomNumberGenerator& rng, const BigInt& min, const BigInt& max) {
   46|     86|   if(min.signum() < 0 || max.signum() < 0 || max <= min) {
  ------------------
  |  Branch (46:7): [True: 0, False: 86]
  |  Branch (46:27): [True: 0, False: 86]
  |  Branch (46:47): [True: 0, False: 86]
  ------------------
   47|      0|      throw Invalid_Argument("BigInt::random_integer invalid range");
   48|      0|   }
   49|       |
   50|       |   /*
   51|       |   If min is > 1 then we generate a random number `r` in [0,max-min)
   52|       |   and return min + r.
   53|       |
   54|       |   This same logic could also be reasonably chosen for min == 1, but
   55|       |   that breaks certain tests which expect stability of this function
   56|       |   when generating within [1,n)
   57|       |   */
   58|     86|   if(min > 1) {
  ------------------
  |  Branch (58:7): [True: 43, False: 43]
  ------------------
   59|     43|      const BigInt diff = max - min;
   60|       |      // This call is recursive, but will not recurse further
   61|     43|      return min + BigInt::random_integer(rng, BigInt::zero(), diff);
   62|     43|   }
   63|       |
   64|     43|   BOTAN_DEBUG_ASSERT(min <= 1);
  ------------------
  |  |  137|     43|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|     43|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 43]
  |  |  ------------------
  ------------------
   65|       |
   66|     43|   const size_t bits = max.bits();
   67|       |
   68|     52|   for(;;) {
   69|     52|      BigInt r;
   70|     52|      r.randomize(rng, bits, false);
   71|     52|      if(r >= min && r < max) {
  ------------------
  |  Branch (71:10): [True: 52, False: 0]
  |  Branch (71:22): [True: 43, False: 9]
  ------------------
   72|     43|         return r;
   73|     43|      }
   74|     52|   }
   75|     43|}

_ZN5Botan6BigIntC2Em:
   18|    282|BigInt::BigInt(uint64_t n) {
   19|    282|   if constexpr(sizeof(word) == 8) {
   20|    282|      m_data.set_word_at(0, static_cast<word>(n));
   21|       |   } else {
   22|       |      m_data.set_word_at(1, static_cast<word>(n >> 32));
   23|       |      m_data.set_word_at(0, static_cast<word>(n));
   24|       |   }
   25|    282|}
_ZN5Botan6BigInt8from_u64Em:
   28|    281|BigInt BigInt::from_u64(uint64_t n) {
   29|    281|   return BigInt(n);
   30|    281|}
_ZN5Botan6BigInt9from_wordEm:
   33|  17.3k|BigInt BigInt::from_word(word n) {
   34|  17.3k|   BigInt bn;
   35|  17.3k|   bn.set_word_at(0, n);
   36|  17.3k|   return bn;
   37|  17.3k|}
_ZN5Botan6BigInt8from_s32Ei:
   40|    281|BigInt BigInt::from_s32(int32_t n) {
   41|    281|   if(n >= 0) {
  ------------------
  |  Branch (41:7): [True: 0, False: 281]
  ------------------
   42|      0|      return BigInt::from_u64(static_cast<uint64_t>(n));
   43|    281|   } else {
   44|    281|      return -BigInt::from_u64(static_cast<uint64_t>(-static_cast<int64_t>(n)));
   45|    281|   }
   46|    281|}
_ZN5Botan6BigInt13with_capacityEm:
   49|  2.10k|BigInt BigInt::with_capacity(size_t size) {
   50|  2.10k|   BigInt bn;
   51|  2.10k|   bn.grow_to(size);
   52|  2.10k|   return bn;
   53|  2.10k|}
_ZN5Botan6BigInt10from_bytesENSt3__14spanIKhLm18446744073709551615EEE:
   81|    813|BigInt BigInt::from_bytes(std::span<const uint8_t> input) {
   82|    813|   BigInt r;
   83|    813|   r.assign_from_bytes(input);
   84|    813|   return r;
   85|    813|}
_ZN5Botan6BigIntC2ERNS_21RandomNumberGeneratorEmb:
  112|      1|BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit) {
  113|      1|   randomize(rng, bits, set_high_bit);
  114|      1|}
_ZNK5Botan6BigInt8cmp_wordEm:
  120|  59.6k|int32_t BigInt::cmp_word(word other) const {
  121|  59.6k|   if(signum() < 0) {
  ------------------
  |  Branch (121:7): [True: 283, False: 59.3k]
  ------------------
  122|    283|      return -1;  // other is positive ...
  123|    283|   }
  124|       |
  125|  59.3k|   const size_t sw = this->sig_words();
  126|  59.3k|   if(sw > 1) {
  ------------------
  |  Branch (126:7): [True: 19.0k, False: 40.3k]
  ------------------
  127|  19.0k|      return 1;  // must be larger since other is just one word ...
  128|  19.0k|   }
  129|       |
  130|  40.3k|   return bigint_cmp(this->_data(), sw, &other, 1);
  131|  59.3k|}
_ZNK5Botan6BigInt3cmpERKS0_b:
  136|  1.87k|int32_t BigInt::cmp(const BigInt& other, bool check_signs) const {
  137|  1.87k|   if(check_signs) {
  ------------------
  |  Branch (137:7): [True: 1.87k, False: 0]
  ------------------
  138|  1.87k|      if(other.signum() >= 0 && this->signum() < 0) {
  ------------------
  |  Branch (138:10): [True: 1.87k, False: 0]
  |  Branch (138:33): [True: 0, False: 1.87k]
  ------------------
  139|      0|         return -1;
  140|      0|      }
  141|       |
  142|  1.87k|      if(other.signum() < 0 && this->signum() >= 0) {
  ------------------
  |  Branch (142:10): [True: 0, False: 1.87k]
  |  Branch (142:32): [True: 0, False: 0]
  ------------------
  143|      0|         return 1;
  144|      0|      }
  145|       |
  146|  1.87k|      if(other.signum() < 0 && this->signum() < 0) {
  ------------------
  |  Branch (146:10): [True: 0, False: 1.87k]
  |  Branch (146:32): [True: 0, False: 0]
  ------------------
  147|      0|         return (-bigint_cmp(this->_data(), this->size(), other._data(), other.size()));
  148|      0|      }
  149|  1.87k|   }
  150|       |
  151|  1.87k|   return bigint_cmp(this->_data(), this->size(), other._data(), other.size());
  152|  1.87k|}
_ZNK5Botan6BigInt8is_equalERKS0_:
  154|    530|bool BigInt::is_equal(const BigInt& other) const {
  155|    530|   if(this->sign() != other.sign()) {
  ------------------
  |  Branch (155:7): [True: 0, False: 530]
  ------------------
  156|      0|      return false;
  157|      0|   }
  158|       |
  159|    530|   return bigint_ct_is_eq(this->_data(), this->size(), other._data(), other.size()).as_bool();
  160|    530|}
_ZNK5Botan6BigInt12is_less_thanERKS0_:
  162|  27.3k|bool BigInt::is_less_than(const BigInt& other) const {
  163|  27.3k|   if(this->signum() < 0 && other.signum() >= 0) {
  ------------------
  |  Branch (163:7): [True: 0, False: 27.3k]
  |  Branch (163:29): [True: 0, False: 0]
  ------------------
  164|      0|      return true;
  165|      0|   }
  166|       |
  167|  27.3k|   if(this->signum() >= 0 && other.signum() < 0) {
  ------------------
  |  Branch (167:7): [True: 27.3k, False: 0]
  |  Branch (167:30): [True: 0, False: 27.3k]
  ------------------
  168|      0|      return false;
  169|      0|   }
  170|       |
  171|  27.3k|   if(other.signum() < 0 && this->signum() < 0) {
  ------------------
  |  Branch (171:7): [True: 0, False: 27.3k]
  |  Branch (171:29): [True: 0, False: 0]
  ------------------
  172|      0|      return bigint_ct_is_lt(other._data(), other.size(), this->_data(), this->size()).as_bool();
  173|      0|   }
  174|       |
  175|  27.3k|   return bigint_ct_is_lt(this->_data(), this->size(), other._data(), other.size()).as_bool();
  176|  27.3k|}
_ZN5Botan6BigInt4Data11set_to_zeroEv:
  189|    866|void BigInt::Data::set_to_zero() {
  190|    866|   m_reg.resize(m_reg.capacity());
  191|    866|   clear_mem(m_reg.data(), m_reg.size());
  192|    866|   m_sig_words = 0;
  193|    866|}
_ZNK5Botan6BigInt4Data14calc_sig_wordsEv:
  213|  59.5k|size_t BigInt::Data::calc_sig_words() const {
  214|  59.5k|   const size_t sz = m_reg.size();
  215|  59.5k|   size_t sig = sz;
  216|       |
  217|  59.5k|   word sub = 1;
  218|       |
  219|   512k|   for(size_t i = 0; i != sz; ++i) {
  ------------------
  |  Branch (219:22): [True: 453k, False: 59.5k]
  ------------------
  220|   453k|      const word w = m_reg[sz - i - 1];
  221|   453k|      sub &= ct_is_zero(w);
  222|   453k|      sig -= sub;
  223|   453k|   }
  224|       |
  225|       |   /*
  226|       |   * This depends on the data so is poisoned, but unpoison it here as
  227|       |   * later conditionals are made on the size.
  228|       |   */
  229|  59.5k|   CT::unpoison(sig);
  230|       |
  231|  59.5k|   return sig;
  232|  59.5k|}
_ZNK5Botan6BigInt13get_substringEmm:
  237|  66.0k|uint32_t BigInt::get_substring(size_t offset, size_t length) const {
  238|  66.0k|   if(length == 0 || length > 32) {
  ------------------
  |  Branch (238:7): [True: 0, False: 66.0k]
  |  Branch (238:22): [True: 0, False: 66.0k]
  ------------------
  239|      0|      throw Invalid_Argument("BigInt::get_substring invalid substring length");
  240|      0|   }
  241|       |
  242|  66.0k|   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
  243|       |
  244|  66.0k|   const size_t word_offset = offset / WordInfo<word>::bits;
  245|  66.0k|   const size_t wshift = (offset % WordInfo<word>::bits);
  246|       |
  247|       |   /*
  248|       |   * The substring is contained within one or at most two words. The
  249|       |   * offset and length are not secret, so we can perform conditional
  250|       |   * operations on those values.
  251|       |   */
  252|  66.0k|   const word w0 = word_at(word_offset);
  253|       |
  254|  66.0k|   if(wshift == 0 || (offset + length) / WordInfo<word>::bits == word_offset) {
  ------------------
  |  Branch (254:7): [True: 4.95k, False: 61.0k]
  |  Branch (254:22): [True: 57.9k, False: 3.11k]
  ------------------
  255|  62.9k|      return static_cast<uint32_t>(w0 >> wshift) & mask;
  256|  62.9k|   } else {
  257|  3.11k|      const word w1 = word_at(word_offset + 1);
  258|  3.11k|      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (WordInfo<word>::bits - wshift))) & mask;
  259|  3.11k|   }
  260|  66.0k|}
_ZNK5Botan6BigInt13top_bits_freeEv:
  296|  2.42k|size_t BigInt::top_bits_free() const {
  297|  2.42k|   const size_t words = sig_words();
  298|       |
  299|  2.42k|   const word top_word = word_at(words - 1);
  300|  2.42k|   const size_t bits_used = high_bit(CT::value_barrier(top_word));
  301|  2.42k|   CT::unpoison(bits_used);
  302|  2.42k|   return WordInfo<word>::bits - bits_used;
  303|  2.42k|}
_ZNK5Botan6BigInt4bitsEv:
  305|  2.42k|size_t BigInt::bits() const {
  306|  2.42k|   const size_t words = sig_words();
  307|       |
  308|  2.42k|   if(words == 0) {
  ------------------
  |  Branch (308:7): [True: 1, False: 2.42k]
  ------------------
  309|      1|      return 0;
  310|      1|   }
  311|       |
  312|  2.42k|   const size_t full_words = (words - 1) * WordInfo<word>::bits;
  313|  2.42k|   const size_t top_bits = WordInfo<word>::bits - top_bits_free();
  314|       |
  315|  2.42k|   return full_words + top_bits;
  316|  2.42k|}
_ZNK5Botan6BigIntngEv:
  321|    281|BigInt BigInt::operator-() const {
  322|    281|   BigInt x = (*this);
  323|    281|   x.flip_sign();
  324|    281|   return x;
  325|    281|}
_ZNK5Botan6BigInt3absEv:
  384|      4|BigInt BigInt::abs() const {
  385|      4|   BigInt x = (*this);
  386|      4|   x.set_sign(Positive);
  387|      4|   return x;
  388|      4|}
_ZN5Botan6BigInt17assign_from_bytesENSt3__14spanIKhLm18446744073709551615EEE:
  423|    866|void BigInt::assign_from_bytes(std::span<const uint8_t> bytes) {
  424|    866|   clear();
  425|       |
  426|    866|   const size_t length = bytes.size();
  427|    866|   const size_t full_words = length / sizeof(word);
  428|    866|   const size_t extra_bytes = length % sizeof(word);
  429|       |
  430|    866|   const size_t total_words = full_words + (extra_bytes > 0 ? 1 : 0);
  ------------------
  |  Branch (430:45): [True: 591, False: 275]
  ------------------
  431|       |
  432|    866|   secure_vector<word> reg(8 * ceil_division<size_t>(total_words, 8));
  433|       |
  434|  1.70k|   for(size_t i = 0; i != full_words; ++i) {
  ------------------
  |  Branch (434:22): [True: 843, False: 866]
  ------------------
  435|    843|      reg[i] = load_be<word>(bytes.last<sizeof(word)>());
  436|    843|      bytes = bytes.first(bytes.size() - sizeof(word));
  437|    843|   }
  438|       |
  439|    866|   if(!bytes.empty()) {
  ------------------
  |  Branch (439:7): [True: 591, False: 275]
  ------------------
  440|    591|      BOTAN_ASSERT_NOMSG(extra_bytes == bytes.size());
  ------------------
  |  |   84|    591|   do {                                                                     \
  |  |   85|    591|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    591|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 591]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    591|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 591]
  |  |  ------------------
  ------------------
  441|    591|      std::array<uint8_t, sizeof(word)> last_partial_word = {0};
  442|    591|      copy_mem(std::span{last_partial_word}.last(extra_bytes), bytes);
  443|    591|      reg[full_words] = load_be<word>(last_partial_word);
  444|    591|   }
  445|       |
  446|    866|   m_data.swap(reg);
  447|    866|}
_ZN5Botan6BigInt14cond_flip_signEb:
  521|  5.09k|void BigInt::cond_flip_sign(bool predicate) {
  522|       |   // This code is assuming Negative == 0, Positive == 1
  523|       |
  524|  5.09k|   const auto mask = CT::Mask<uint8_t>::expand_bool(predicate);
  525|       |
  526|  5.09k|   const uint8_t current_sign = static_cast<uint8_t>(sign());
  527|       |
  528|  5.09k|   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
  529|       |
  530|  5.09k|   set_sign(static_cast<Sign>(new_sign));
  531|  5.09k|}
_ZNK5Botan6BigInt20_const_time_unpoisonEv:
  559|  93.0k|void BigInt::_const_time_unpoison() const {
  560|  93.0k|   CT::unpoison(m_data.const_data(), m_data.size());
  561|  93.0k|}

_ZN5Botan9ct_divideERKNS_6BigIntES2_RS0_S3_:
  180|  5.09k|void ct_divide(const BigInt& x, const BigInt& y, BigInt& q_out, BigInt& r_out) {
  181|  5.09k|   if(y.is_zero()) {
  ------------------
  |  Branch (181:7): [True: 0, False: 5.09k]
  ------------------
  182|      0|      throw Invalid_Argument("ct_divide: cannot divide by zero");
  183|      0|   }
  184|       |
  185|  5.09k|   BigInt q;
  186|  5.09k|   BigInt r;
  187|  5.09k|   ct_divide_impl(q, r, x, y);
  188|       |
  189|  5.09k|   sign_fixup(x, y, q, r);
  190|  5.09k|   r_out = std::move(r);
  191|  5.09k|   q_out = std::move(q);
  192|  5.09k|}
_ZN5Botan15ct_divide_pow2kEmRKNS_6BigIntE:
  194|    545|BigInt ct_divide_pow2k(size_t k, const BigInt& y) {
  195|    545|   BOTAN_ARG_CHECK(y.signum() != 0, "Cannot divide by zero");
  ------------------
  |  |   35|    545|   do {                                                          \
  |  |   36|    545|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    545|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 545]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    545|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 545]
  |  |  ------------------
  ------------------
  196|    545|   BOTAN_ARG_CHECK(y.signum() >= 0, "Negative divisor not supported");
  ------------------
  |  |   35|    545|   do {                                                          \
  |  |   36|    545|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    545|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 545]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    545|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 545]
  |  |  ------------------
  ------------------
  197|    545|   BOTAN_ARG_CHECK(k > 1, "Invalid k");
  ------------------
  |  |   35|    545|   do {                                                          \
  |  |   36|    545|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    545|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 545]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    545|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 545]
  |  |  ------------------
  ------------------
  198|       |
  199|    545|   BigInt q;
  200|    545|   BigInt r;
  201|    545|   ct_divide_impl(q, r, BigInt::power_of_2(k), y);
  202|    545|   return q;
  203|    545|}
divide.cpp:_ZN5Botan12_GLOBAL__N_114ct_divide_implERNS_6BigIntES2_RKS1_S4_:
   66|  5.63k|void ct_divide_impl(BigInt& q_out, BigInt& r_out, const BigInt& x, const BigInt& y) {
   67|  5.63k|   constexpr size_t WB = WordInfo<word>::bits;
   68|       |
   69|  5.63k|   const size_t x_words = x.sig_words();
   70|  5.63k|   const size_t y_words = y.sig_words();
   71|  5.63k|   BOTAN_ASSERT_NOMSG(y_words > 0);
  ------------------
  |  |   84|  5.63k|   do {                                                                     \
  |  |   85|  5.63k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  5.63k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 5.63k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  5.63k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 5.63k]
  |  |  ------------------
  ------------------
   72|       |
   73|  5.63k|   if(x_words < y_words) {
  ------------------
  |  Branch (73:7): [True: 2, False: 5.63k]
  ------------------
   74|       |      // Here |x| < |y| so q = 0 and r = |x|
   75|      2|      r_out = x.abs();
   76|      2|      q_out = BigInt::zero();
   77|      2|      return;
   78|      2|   }
   79|       |
   80|  5.63k|   const size_t r_words = x_words + 1;
   81|  5.63k|   const size_t q_words = x_words - y_words + 1;
   82|       |
   83|       |   // The number of leading zero bits of y, in [0,WB)
   84|  5.63k|   const word s = static_cast<word>(WB) - static_cast<word>(high_bit(CT::value_barrier(y._data()[y_words - 1])));
   85|  5.63k|   const auto s_mask = CT::Mask<word>::expand(s);
   86|  5.63k|   const word s_comp = s_mask.if_set_return(static_cast<word>(WB) - s);
   87|       |
   88|  5.63k|   secure_vector<word> yn(y_words);
   89|  5.63k|   secure_vector<word> rw(r_words);
   90|  5.63k|   secure_vector<word> qw(q_words);
   91|       |
   92|       |   // Normalize: yn = |y| << s (which sets the top bit of yn) and rw = |x| << s;
   93|       |   // shifting y stays within y_words words, shifting x adds at most one word
   94|  5.63k|   word carry = 0;
   95|  19.4k|   for(size_t i = 0; i != y_words; ++i) {
  ------------------
  |  Branch (95:22): [True: 13.7k, False: 5.63k]
  ------------------
   96|  13.7k|      const word w = y._data()[i];
   97|  13.7k|      yn[i] = (w << s) | carry;
   98|  13.7k|      carry = s_mask.if_set_return(w >> s_comp);
   99|  13.7k|   }
  100|       |
  101|  5.63k|   carry = 0;
  102|  22.7k|   for(size_t i = 0; i != x_words; ++i) {
  ------------------
  |  Branch (102:22): [True: 17.1k, False: 5.63k]
  ------------------
  103|  17.1k|      const word w = x._data()[i];
  104|  17.1k|      rw[i] = (w << s) | carry;
  105|  17.1k|      carry = s_mask.if_set_return(w >> s_comp);
  106|  17.1k|   }
  107|  5.63k|   rw[x_words] = carry;
  108|       |
  109|  5.63k|   const auto div_by_yn = divide_precomp<word>::setup(CT::value_barrier(yn[y_words - 1]));
  110|       |
  111|  5.63k|   if(y_words == 1) {
  ------------------
  |  Branch (111:7): [True: 0, False: 5.63k]
  ------------------
  112|       |      /*
  113|       |      * 2/1 word-serial division. The initial remainder is the shift-out
  114|       |      * carry, which is less than 2^s and so less than the divisor.
  115|       |      */
  116|      0|      word r = rw[x_words];
  117|      0|      for(size_t i = x_words; i > 0; --i) {
  ------------------
  |  Branch (117:31): [True: 0, False: 0]
  ------------------
  118|      0|         const auto [qi, ri] = div_by_yn.divmod_2to1_ct(r, rw[i - 1]);
  119|      0|         qw[i - 1] = qi;
  120|      0|         r = ri;
  121|      0|      }
  122|       |
  123|      0|      rw[0] = r >> s;
  124|  5.63k|   } else {
  125|  5.63k|      const word yn1 = yn[y_words - 1];
  126|  5.63k|      const word yn2 = yn[y_words - 2];
  127|       |
  128|  14.6k|      for(size_t i = q_words; i > 0; --i) {
  ------------------
  |  Branch (128:31): [True: 9.02k, False: 5.63k]
  ------------------
  129|  9.02k|         const size_t j = i - 1;  // current window is rw[j ... j + y_words]
  130|       |
  131|  9.02k|         const word u2 = rw[j + y_words];
  132|  9.02k|         const word u1 = rw[j + y_words - 1];
  133|  9.02k|         const word u0 = rw[j + y_words - 2];
  134|       |
  135|       |         /*
  136|       |         * Estimate the quotient digit from the top two words of the window.
  137|       |         * The window invariant gives u2 <= yn1; if u2 == yn1 the 2/1
  138|       |         * division precondition does not hold, and instead the digit
  139|       |         * estimate is the maximum word value.
  140|       |         */
  141|  9.02k|         const auto top_eq = CT::Mask<word>::is_equal(u2, yn1);
  142|  9.02k|         const word q_est = div_by_yn.divmod_2to1_ct(u2, u1).first;
  143|  9.02k|         word qhat = top_eq.select(WordInfo<word>::max, q_est);
  144|       |
  145|       |         // Per HAC 14.23, this correction is required at most twice
  146|  9.02k|         qhat -= division_check_ct(qhat, yn1, yn2, u2, u1, u0).if_set_return(1);
  147|  9.02k|         qhat -= division_check_ct(qhat, yn1, yn2, u2, u1, u0).if_set_return(1);
  148|       |
  149|       |         // Subtract qhat * yn from the window
  150|  9.02k|         const word bw = bigint_submul(&rw[j], yn.data(), y_words, qhat);
  151|  9.02k|         word borrow = 0;
  152|  9.02k|         rw[j + y_words] = word_sub(u2, bw, &borrow);
  153|       |
  154|       |         // If the digit was still one too large, the subtraction
  155|       |         // underflowed; add back and decrement the digit
  156|  9.02k|         const word cb = bigint_cnd_add(borrow, &rw[j], yn.data(), y_words);
  157|  9.02k|         rw[j + y_words] += cb;
  158|  9.02k|         qhat -= borrow;
  159|       |
  160|  9.02k|         qw[j] = qhat;
  161|  9.02k|      }
  162|       |
  163|       |      // The remainder is in rw[0:y_words], still shifted left by s, and
  164|       |      // rw[y_words] is zero
  165|  19.4k|      for(size_t i = 0; i != y_words; ++i) {
  ------------------
  |  Branch (165:25): [True: 13.7k, False: 5.63k]
  ------------------
  166|  13.7k|         rw[i] = (rw[i] >> s) | s_mask.if_set_return(CT::value_barrier(rw[i + 1]) << s_comp);
  167|  13.7k|      }
  168|  5.63k|   }
  169|       |
  170|  5.63k|   BigInt q = BigInt::_from_words(qw);
  171|  5.63k|   rw.resize(y_words);
  172|  5.63k|   BigInt r = BigInt::_from_words(rw);
  173|       |
  174|  5.63k|   r_out = std::move(r);
  175|  5.63k|   q_out = std::move(q);
  176|  5.63k|}
divide.cpp:_ZN5Botan12_GLOBAL__N_117division_check_ctEmmmmmm:
   39|  18.0k|inline CT::Mask<word> division_check_ct(word q, word y2, word y1, word x3, word x2, word x1) {
   40|  18.0k|   word y3 = 0;
   41|  18.0k|   y1 = word_madd2(q, y1, &y3);
   42|  18.0k|   y2 = word_madd2(q, y2, &y3);
   43|       |
   44|  18.0k|   const auto gt3 = CT::Mask<word>::is_gt(y3, x3);
   45|  18.0k|   const auto eq3 = CT::Mask<word>::is_equal(y3, x3);
   46|  18.0k|   const auto gt2 = CT::Mask<word>::is_gt(y2, x2);
   47|  18.0k|   const auto eq2 = CT::Mask<word>::is_equal(y2, x2);
   48|  18.0k|   const auto gt1 = CT::Mask<word>::is_gt(y1, x1);
   49|       |
   50|  18.0k|   return gt3 | (eq3 & (gt2 | (eq2 & gt1)));
   51|  18.0k|}
divide.cpp:_ZN5Botan12_GLOBAL__N_110sign_fixupERKNS_6BigIntES3_RS1_S4_:
   22|  5.09k|void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r) {
   23|  5.09k|   q.cond_flip_sign(x.sign() != y.sign());
   24|       |
   25|  5.09k|   if(x.signum() < 0 && r.signum() != 0) {
  ------------------
  |  Branch (25:7): [True: 2, False: 5.09k]
  |  Branch (25:25): [True: 2, False: 0]
  ------------------
   26|      2|      if(y.signum() > 0) {
  ------------------
  |  Branch (26:10): [True: 2, False: 0]
  ------------------
   27|      2|         q -= 1;
   28|      2|      } else {
   29|      0|         q += 1;
   30|      0|      }
   31|      2|      r = y.abs() - r;
   32|      2|   }
   33|  5.09k|}

_ZN5Botan17bigint_comba_sqr4EPmPKm:
   22|   274k|void bigint_comba_sqr4(word z[8], const word x[4]) {
   23|   274k|#if defined(BOTAN_HAS_MP_MULX)
   24|   274k|   if(CPUID::has(CPUID::Feature::BMI, CPUID::Feature::ADX)) {
  ------------------
  |  Branch (24:7): [True: 274k, False: 0]
  ------------------
   25|   274k|      return bigint_mulx_sqr4(z, x);
   26|   274k|   }
   27|      0|#endif
   28|       |
   29|      0|   word3<word> accum;
   30|       |
   31|      0|   accum.mul(x[0], x[0]);
   32|      0|   z[0] = accum.extract();
   33|      0|   accum.mul_x2(x[0], x[1]);
   34|      0|   z[1] = accum.extract();
   35|      0|   accum.mul_x2(x[0], x[2]);
   36|      0|   accum.mul(x[1], x[1]);
   37|      0|   z[2] = accum.extract();
   38|      0|   accum.mul_x2(x[0], x[3]);
   39|      0|   accum.mul_x2(x[1], x[2]);
   40|      0|   z[3] = accum.extract();
   41|      0|   accum.mul_x2(x[1], x[3]);
   42|      0|   accum.mul(x[2], x[2]);
   43|      0|   z[4] = accum.extract();
   44|      0|   accum.mul_x2(x[2], x[3]);
   45|      0|   z[5] = accum.extract();
   46|      0|   accum.mul(x[3], x[3]);
   47|      0|   z[6] = accum.extract();
   48|      0|   z[7] = accum.extract();
   49|      0|}
_ZN5Botan17bigint_comba_mul4EPmPKmS2_:
   54|  78.5k|void bigint_comba_mul4(word z[8], const word x[4], const word y[4]) {
   55|  78.5k|#if defined(BOTAN_HAS_MP_MULX)
   56|  78.5k|   if(CPUID::has(CPUID::Feature::BMI, CPUID::Feature::ADX)) {
  ------------------
  |  Branch (56:7): [True: 78.5k, False: 0]
  ------------------
   57|  78.5k|      return bigint_mulx_mul4(z, x, y);
   58|  78.5k|   }
   59|      0|#endif
   60|       |
   61|      0|   word3<word> accum;
   62|       |
   63|      0|   accum.mul(x[0], y[0]);
   64|      0|   z[0] = accum.extract();
   65|      0|   accum.mul(x[0], y[1]);
   66|      0|   accum.mul(x[1], y[0]);
   67|      0|   z[1] = accum.extract();
   68|      0|   accum.mul(x[0], y[2]);
   69|      0|   accum.mul(x[1], y[1]);
   70|      0|   accum.mul(x[2], y[0]);
   71|      0|   z[2] = accum.extract();
   72|      0|   accum.mul(x[0], y[3]);
   73|      0|   accum.mul(x[1], y[2]);
   74|      0|   accum.mul(x[2], y[1]);
   75|      0|   accum.mul(x[3], y[0]);
   76|      0|   z[3] = accum.extract();
   77|      0|   accum.mul(x[1], y[3]);
   78|      0|   accum.mul(x[2], y[2]);
   79|      0|   accum.mul(x[3], y[1]);
   80|      0|   z[4] = accum.extract();
   81|      0|   accum.mul(x[2], y[3]);
   82|      0|   accum.mul(x[3], y[2]);
   83|      0|   z[5] = accum.extract();
   84|      0|   accum.mul(x[3], y[3]);
   85|      0|   z[6] = accum.extract();
   86|      0|   z[7] = accum.extract();
   87|      0|}
_ZN5Botan17bigint_comba_mul6EPmPKmS2_:
  139|  16.7k|void bigint_comba_mul6(word z[12], const word x[6], const word y[6]) {
  140|  16.7k|#if defined(BOTAN_HAS_MP_MULX)
  141|  16.7k|   if(CPUID::has(CPUID::Feature::BMI, CPUID::Feature::ADX)) {
  ------------------
  |  Branch (141:7): [True: 16.7k, False: 0]
  ------------------
  142|  16.7k|      return bigint_mulx_mul6(z, x, y);
  143|  16.7k|   }
  144|      0|#endif
  145|       |
  146|      0|   word3<word> accum;
  147|       |
  148|      0|   accum.mul(x[0], y[0]);
  149|      0|   z[0] = accum.extract();
  150|      0|   accum.mul(x[0], y[1]);
  151|      0|   accum.mul(x[1], y[0]);
  152|      0|   z[1] = accum.extract();
  153|      0|   accum.mul(x[0], y[2]);
  154|      0|   accum.mul(x[1], y[1]);
  155|      0|   accum.mul(x[2], y[0]);
  156|      0|   z[2] = accum.extract();
  157|      0|   accum.mul(x[0], y[3]);
  158|      0|   accum.mul(x[1], y[2]);
  159|      0|   accum.mul(x[2], y[1]);
  160|      0|   accum.mul(x[3], y[0]);
  161|      0|   z[3] = accum.extract();
  162|      0|   accum.mul(x[0], y[4]);
  163|      0|   accum.mul(x[1], y[3]);
  164|      0|   accum.mul(x[2], y[2]);
  165|      0|   accum.mul(x[3], y[1]);
  166|      0|   accum.mul(x[4], y[0]);
  167|      0|   z[4] = accum.extract();
  168|      0|   accum.mul(x[0], y[5]);
  169|      0|   accum.mul(x[1], y[4]);
  170|      0|   accum.mul(x[2], y[3]);
  171|      0|   accum.mul(x[3], y[2]);
  172|      0|   accum.mul(x[4], y[1]);
  173|      0|   accum.mul(x[5], y[0]);
  174|      0|   z[5] = accum.extract();
  175|      0|   accum.mul(x[1], y[5]);
  176|      0|   accum.mul(x[2], y[4]);
  177|      0|   accum.mul(x[3], y[3]);
  178|      0|   accum.mul(x[4], y[2]);
  179|      0|   accum.mul(x[5], y[1]);
  180|      0|   z[6] = accum.extract();
  181|      0|   accum.mul(x[2], y[5]);
  182|      0|   accum.mul(x[3], y[4]);
  183|      0|   accum.mul(x[4], y[3]);
  184|      0|   accum.mul(x[5], y[2]);
  185|      0|   z[7] = accum.extract();
  186|      0|   accum.mul(x[3], y[5]);
  187|      0|   accum.mul(x[4], y[4]);
  188|      0|   accum.mul(x[5], y[3]);
  189|      0|   z[8] = accum.extract();
  190|      0|   accum.mul(x[4], y[5]);
  191|      0|   accum.mul(x[5], y[4]);
  192|      0|   z[9] = accum.extract();
  193|      0|   accum.mul(x[5], y[5]);
  194|      0|   z[10] = accum.extract();
  195|      0|   z[11] = accum.extract();
  196|      0|}

_ZN5Botan10bigint_mulEPmmPKmmmS2_mmS0_m:
  292|  95.2k|                size_t ws_size) {
  293|  95.2k|   zeroize_buffer(z, z_size);
  294|       |
  295|  95.2k|   if(x_sw == 1) {
  ------------------
  |  Branch (295:7): [True: 0, False: 95.2k]
  ------------------
  296|      0|      bigint_linmul3(z, y, y_sw, x[0]);
  297|  95.2k|   } else if(y_sw == 1) {
  ------------------
  |  Branch (297:14): [True: 0, False: 95.2k]
  ------------------
  298|      0|      bigint_linmul3(z, x, x_sw, y[0]);
  299|  95.2k|   } else if(sized_for_comba_mul<4>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (299:14): [True: 78.5k, False: 16.7k]
  ------------------
  300|  78.5k|      bigint_comba_mul4(z, x, y);
  301|  78.5k|   } else if(sized_for_comba_mul<6>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (301:14): [True: 16.7k, False: 0]
  ------------------
  302|  16.7k|      bigint_comba_mul6(z, x, y);
  303|  16.7k|   } else if(sized_for_comba_mul<8>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (303:14): [True: 0, False: 0]
  ------------------
  304|      0|      bigint_comba_mul8(z, x, y);
  305|      0|   } else if(sized_for_comba_mul<9>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (305:14): [True: 0, False: 0]
  ------------------
  306|      0|      bigint_comba_mul9(z, x, y);
  307|      0|   } else if(sized_for_comba_mul<16>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (307:14): [True: 0, False: 0]
  ------------------
  308|      0|      bigint_comba_mul16(z, x, y);
  309|      0|   } else if(sized_for_comba_mul<24>(x_sw, x_size, y_sw, y_size, z_size)) {
  ------------------
  |  Branch (309:14): [True: 0, False: 0]
  ------------------
  310|      0|      bigint_comba_mul24(z, x, y);
  311|      0|   } else if(x_sw < KARATSUBA_MULTIPLY_THRESHOLD || y_sw < KARATSUBA_MULTIPLY_THRESHOLD || workspace == nullptr) {
  ------------------
  |  Branch (311:14): [True: 0, False: 0]
  |  Branch (311:53): [True: 0, False: 0]
  |  Branch (311:92): [True: 0, False: 0]
  ------------------
  312|      0|      basecase_mul(z, z_size, x, x_sw, y, y_sw);
  313|      0|   } else {
  314|      0|      const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);
  315|       |
  316|      0|      if(N > 0 && z_size >= 2 * N && ws_size >= 2 * N) {
  ------------------
  |  Branch (316:10): [True: 0, False: 0]
  |  Branch (316:19): [True: 0, False: 0]
  |  Branch (316:38): [True: 0, False: 0]
  ------------------
  317|      0|         karatsuba_mul(z, x, y, N, workspace);
  318|      0|      } else {
  319|      0|         basecase_mul(z, z_size, x, x_sw, y, y_sw);
  320|      0|      }
  321|      0|   }
  322|  95.2k|}
_ZN5Botan10bigint_sqrEPmmPKmmmS0_m:
  327|   274k|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) {
  328|   274k|   zeroize_buffer(z, z_size);
  329|       |
  330|   274k|   BOTAN_ASSERT(z_size / 2 >= x_sw, "Output size is sufficient");
  ------------------
  |  |   71|   274k|   do {                                                                                 \
  |  |   72|   274k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|   274k|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 274k]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|   274k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 274k]
  |  |  ------------------
  ------------------
  331|       |
  332|   274k|   if(x_sw == 1) {
  ------------------
  |  Branch (332:7): [True: 0, False: 274k]
  ------------------
  333|      0|      bigint_linmul3(z, x, x_sw, x[0]);
  334|   274k|   } else if(sized_for_comba_sqr<4>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (334:14): [True: 274k, False: 0]
  ------------------
  335|   274k|      bigint_comba_sqr4(z, x);
  336|   274k|   } else if(sized_for_comba_sqr<6>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (336:14): [True: 0, False: 0]
  ------------------
  337|      0|      bigint_comba_sqr6(z, x);
  338|      0|   } else if(sized_for_comba_sqr<8>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (338:14): [True: 0, False: 0]
  ------------------
  339|      0|      bigint_comba_sqr8(z, x);
  340|      0|   } else if(sized_for_comba_sqr<9>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (340:14): [True: 0, False: 0]
  ------------------
  341|      0|      bigint_comba_sqr9(z, x);
  342|      0|   } else if(sized_for_comba_sqr<16>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (342:14): [True: 0, False: 0]
  ------------------
  343|      0|      bigint_comba_sqr16(z, x);
  344|      0|   } else if(sized_for_comba_sqr<24>(x_sw, x_size, z_size)) {
  ------------------
  |  Branch (344:14): [True: 0, False: 0]
  ------------------
  345|      0|      bigint_comba_sqr24(z, x);
  346|      0|   } else if(x_size < KARATSUBA_SQUARE_THRESHOLD || workspace == nullptr) {
  ------------------
  |  Branch (346:14): [True: 0, False: 0]
  |  Branch (346:53): [True: 0, False: 0]
  ------------------
  347|      0|      basecase_sqr(z, z_size, x, x_sw);
  348|      0|   } else {
  349|      0|      const size_t N = karatsuba_size(z_size, x_size, x_sw);
  350|       |
  351|      0|      if(N > 0 && z_size >= 2 * N && ws_size >= 2 * N) {
  ------------------
  |  Branch (351:10): [True: 0, False: 0]
  |  Branch (351:19): [True: 0, False: 0]
  |  Branch (351:38): [True: 0, False: 0]
  ------------------
  352|      0|         karatsuba_sqr(z, x, N, workspace);
  353|      0|      } else {
  354|      0|         basecase_sqr(z, z_size, x, x_sw);
  355|      0|      }
  356|      0|   }
  357|   274k|}
mp_karat.cpp:_ZN5Botan12_GLOBAL__N_119sized_for_comba_mulILm4EEEbmmmmm:
  272|  95.2k|inline bool sized_for_comba_mul(size_t x_sw, size_t x_size, size_t y_sw, size_t y_size, size_t z_size) {
  273|  95.2k|   return (x_sw <= SZ && x_size >= SZ && y_sw <= SZ && y_size >= SZ && z_size >= 2 * SZ);
  ------------------
  |  Branch (273:12): [True: 78.5k, False: 16.7k]
  |  Branch (273:26): [True: 78.5k, False: 0]
  |  Branch (273:42): [True: 78.5k, False: 0]
  |  Branch (273:56): [True: 78.5k, False: 0]
  |  Branch (273:72): [True: 78.5k, False: 0]
  ------------------
  274|  95.2k|}
mp_karat.cpp:_ZN5Botan12_GLOBAL__N_119sized_for_comba_mulILm6EEEbmmmmm:
  272|  16.7k|inline bool sized_for_comba_mul(size_t x_sw, size_t x_size, size_t y_sw, size_t y_size, size_t z_size) {
  273|  16.7k|   return (x_sw <= SZ && x_size >= SZ && y_sw <= SZ && y_size >= SZ && z_size >= 2 * SZ);
  ------------------
  |  Branch (273:12): [True: 16.7k, False: 0]
  |  Branch (273:26): [True: 16.7k, False: 0]
  |  Branch (273:42): [True: 16.7k, False: 0]
  |  Branch (273:56): [True: 16.7k, False: 0]
  |  Branch (273:72): [True: 16.7k, False: 0]
  ------------------
  274|  16.7k|}
mp_karat.cpp:_ZN5Botan12_GLOBAL__N_119sized_for_comba_sqrILm4EEEbmmm:
  277|   274k|inline bool sized_for_comba_sqr(size_t x_sw, size_t x_size, size_t z_size) {
  278|   274k|   return (x_sw <= SZ && x_size >= SZ && z_size >= 2 * SZ);
  ------------------
  |  Branch (278:12): [True: 274k, False: 0]
  |  Branch (278:26): [True: 274k, False: 0]
  |  Branch (278:42): [True: 274k, False: 0]
  ------------------
  279|   274k|}

_ZN5Botan16bigint_monty_mulEPmPKmS2_S2_mmS0_m:
  144|  75.3k|   word z[], const word x[], const word y[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size) {
  145|  75.3k|   BOTAN_ARG_CHECK(ws_size >= 4 * p_size && p_size > 0, "Invalid workspace for Montgomery multiplication");
  ------------------
  |  |   35|  75.3k|   do {                                                          \
  |  |   36|  75.3k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|   150k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 75.3k, False: 0]
  |  |  |  Branch (37:12): [True: 75.3k, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  75.3k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 75.3k]
  |  |  ------------------
  ------------------
  146|       |
  147|  75.3k|#if defined(BOTAN_HAS_MP_MULX)
  148|  75.3k|   if(use_mulx_monty(p_size)) {
  ------------------
  |  Branch (148:7): [True: 0, False: 75.3k]
  ------------------
  149|      0|      return bigint_mulx_monty_mul(z, x, y, p, p_size, p_dash, ws);
  150|      0|   }
  151|  75.3k|#endif
  152|       |
  153|  75.3k|   word* prod = ws;
  154|  75.3k|   word* mul_ws = ws + 2 * p_size;
  155|  75.3k|   bigint_mul(prod, 2 * p_size, x, p_size, p_size, y, p_size, p_size, mul_ws, 2 * p_size);
  156|  75.3k|   bigint_monty_redc(z, prod, p, p_size, p_dash, mul_ws, 2 * p_size);
  157|  75.3k|}
_ZN5Botan16bigint_monty_sqrEPmPKmS2_mmS0_m:
  159|   270k|void bigint_monty_sqr(word z[], const word x[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size) {
  160|   270k|   BOTAN_ARG_CHECK(ws_size >= 4 * p_size && p_size > 0, "Invalid workspace for Montgomery squaring");
  ------------------
  |  |   35|   270k|   do {                                                          \
  |  |   36|   270k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|   540k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 270k, False: 0]
  |  |  |  Branch (37:12): [True: 270k, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|   270k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 270k]
  |  |  ------------------
  ------------------
  161|       |
  162|   270k|   word* prod = ws;
  163|       |
  164|   270k|#if defined(BOTAN_HAS_MP_MULX)
  165|   270k|   if(use_mulx_monty(p_size)) {
  ------------------
  |  Branch (165:7): [True: 0, False: 270k]
  ------------------
  166|      0|      return bigint_mulx_monty_sqr(z, x, p, p_size, p_dash, ws);
  167|      0|   }
  168|   270k|#endif
  169|       |
  170|   270k|   word* mul_ws = ws + 2 * p_size;
  171|   270k|   bigint_sqr(prod, 2 * p_size, x, p_size, p_size, mul_ws, 2 * p_size);
  172|   270k|   bigint_monty_redc(z, prod, p, p_size, p_dash, mul_ws, 2 * p_size);
  173|   270k|}

_ZN5Botan19bigint_monty_redc_4EPmPKmS2_mS0_:
   12|   347k|void bigint_monty_redc_4(word r[4], const word z[8], const word p[4], word p_dash, word ws[4]) {
   13|   347k|   word3<word> accum;
   14|   347k|   accum.add(z[0]);
   15|   347k|   ws[0] = accum.monty_step(p[0], p_dash);
   16|   347k|   accum.mul(ws[0], p[1]);
   17|   347k|   accum.add(z[1]);
   18|   347k|   ws[1] = accum.monty_step(p[0], p_dash);
   19|   347k|   accum.mul(ws[0], p[2]);
   20|   347k|   accum.mul(ws[1], p[1]);
   21|   347k|   accum.add(z[2]);
   22|   347k|   ws[2] = accum.monty_step(p[0], p_dash);
   23|   347k|   accum.mul(ws[0], p[3]);
   24|   347k|   accum.mul(ws[1], p[2]);
   25|   347k|   accum.mul(ws[2], p[1]);
   26|   347k|   accum.add(z[3]);
   27|   347k|   ws[3] = accum.monty_step(p[0], p_dash);
   28|   347k|   accum.mul(ws[1], p[3]);
   29|   347k|   accum.mul(ws[2], p[2]);
   30|   347k|   accum.mul(ws[3], p[1]);
   31|   347k|   accum.add(z[4]);
   32|   347k|   ws[0] = accum.extract();
   33|   347k|   accum.mul(ws[2], p[3]);
   34|   347k|   accum.mul(ws[3], p[2]);
   35|   347k|   accum.add(z[5]);
   36|   347k|   ws[1] = accum.extract();
   37|   347k|   accum.mul(ws[3], p[3]);
   38|   347k|   accum.add(z[6]);
   39|   347k|   ws[2] = accum.extract();
   40|   347k|   accum.add(z[7]);
   41|   347k|   ws[3] = accum.extract();
   42|   347k|   const word w1 = accum.extract();
   43|   347k|   bigint_monty_maybe_sub<4>(r, w1, ws, p);
   44|   347k|}

_ZN5Botan16bigint_mulx_sqr4EPmPKm:
   27|   274k|void bigint_mulx_sqr4(word z[8], const word x[4]) {
   28|       |   // clang-format off
   29|   274k|   asm(
   30|   274k|      "xorl %%r9d, %%r9d\n\t"
   31|   274k|      "xorl %%r10d, %%r10d\n\t"
   32|   274k|      "xorl %%r8d, %%r8d\n\t"
   33|       |
   34|   274k|      "movq 0(%[x]), %%rdx\n\t"  // x[0] * x[1..3]
   35|   274k|      "xorl %%eax, %%eax\n\t"
   36|   274k|      "mulx 8(%[x]), %%rax, %%rcx\n\t"
   37|   274k|      "adcx %%rax, %%r9\n\t"
   38|   274k|      "movq %%r9, 8(%[z])\n\t"
   39|   274k|      "mulx 16(%[x]), %%rax, %%r9\n\t"
   40|   274k|      "adox %%rcx, %%rax\n\t"
   41|   274k|      "adcx %%rax, %%r10\n\t"
   42|   274k|      "mulx 24(%[x]), %%rax, %%rcx\n\t"
   43|   274k|      "adox %%r9, %%rax\n\t"
   44|   274k|      "adcx %%rax, %%r8\n\t"
   45|   274k|      "movl $0, %%eax\n\t"
   46|   274k|      "adox %%rax, %%rcx\n\t"
   47|   274k|      "adcx %%rax, %%rcx\n\t"
   48|   274k|      "movq %%rcx, %%r9\n\t"
   49|   274k|      "movq %%r10, 16(%[z])\n\t"
   50|       |
   51|   274k|      "movq 8(%[x]), %%rdx\n\t"  // x[1] * x[2..3]
   52|   274k|      "xorl %%eax, %%eax\n\t"
   53|   274k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
   54|   274k|      "adcx %%rax, %%r8\n\t"
   55|   274k|      "movq %%r8, 24(%[z])\n\t"
   56|   274k|      "mulx 24(%[x]), %%rax, %%r10\n\t"
   57|   274k|      "adox %%rcx, %%rax\n\t"
   58|   274k|      "adcx %%rax, %%r9\n\t"
   59|   274k|      "movl $0, %%eax\n\t"
   60|   274k|      "adox %%rax, %%r10\n\t"
   61|   274k|      "adcx %%rax, %%r10\n\t"
   62|   274k|      "movq %%r9, 32(%[z])\n\t"
   63|       |
   64|   274k|      "movq 16(%[x]), %%rdx\n\t"  // x[2] * x[3..3]
   65|   274k|      "xorl %%eax, %%eax\n\t"
   66|   274k|      "mulx 24(%[x]), %%rax, %%rcx\n\t"
   67|   274k|      "adcx %%rax, %%r10\n\t"
   68|   274k|      "movq %%r10, 40(%[z])\n\t"
   69|   274k|      "movl $0, %%eax\n\t"
   70|   274k|      "adox %%rax, %%rcx\n\t"
   71|   274k|      "adcx %%rax, %%rcx\n\t"
   72|   274k|      "movq %%rcx, %%r8\n\t"
   73|   274k|      "movq %%r8, 48(%[z])\n\t"
   74|       |
   75|   274k|      "movq $0, 56(%[z])\n\t"
   76|   274k|      "xorl %%eax, %%eax\n\t"  // double the cross products and add the squares
   77|   274k|      "movq 0(%[x]), %%rdx\n\t"
   78|   274k|      "mulx %%rdx, %%rax, %%rcx\n\t"
   79|   274k|      "movq %%rax, 0(%[z])\n\t"
   80|   274k|      "movq 8(%[z]), %%r8\n\t"
   81|   274k|      "adcx %%r8, %%r8\n\t"
   82|   274k|      "adox %%rcx, %%r8\n\t"
   83|   274k|      "movq %%r8, 8(%[z])\n\t"
   84|   274k|      "movq 8(%[x]), %%rdx\n\t"
   85|   274k|      "mulx %%rdx, %%rax, %%rcx\n\t"
   86|   274k|      "movq 16(%[z]), %%r8\n\t"
   87|   274k|      "adcx %%r8, %%r8\n\t"
   88|   274k|      "adox %%rax, %%r8\n\t"
   89|   274k|      "movq %%r8, 16(%[z])\n\t"
   90|   274k|      "movq 24(%[z]), %%r8\n\t"
   91|   274k|      "adcx %%r8, %%r8\n\t"
   92|   274k|      "adox %%rcx, %%r8\n\t"
   93|   274k|      "movq %%r8, 24(%[z])\n\t"
   94|   274k|      "movq 16(%[x]), %%rdx\n\t"
   95|   274k|      "mulx %%rdx, %%rax, %%rcx\n\t"
   96|   274k|      "movq 32(%[z]), %%r8\n\t"
   97|   274k|      "adcx %%r8, %%r8\n\t"
   98|   274k|      "adox %%rax, %%r8\n\t"
   99|   274k|      "movq %%r8, 32(%[z])\n\t"
  100|   274k|      "movq 40(%[z]), %%r8\n\t"
  101|   274k|      "adcx %%r8, %%r8\n\t"
  102|   274k|      "adox %%rcx, %%r8\n\t"
  103|   274k|      "movq %%r8, 40(%[z])\n\t"
  104|   274k|      "movq 24(%[x]), %%rdx\n\t"
  105|   274k|      "mulx %%rdx, %%rax, %%rcx\n\t"
  106|   274k|      "movq 48(%[z]), %%r8\n\t"
  107|   274k|      "adcx %%r8, %%r8\n\t"
  108|   274k|      "adox %%rax, %%r8\n\t"
  109|   274k|      "movq %%r8, 48(%[z])\n\t"
  110|   274k|      "movq 56(%[z]), %%r8\n\t"
  111|   274k|      "adcx %%r8, %%r8\n\t"
  112|   274k|      "adox %%rcx, %%r8\n\t"
  113|   274k|      "movq %%r8, 56(%[z])\n\t"
  114|   274k|      :
  115|   274k|      : [z] "r"(z), [x] "r"(x)
  116|   274k|      : "rax", "rcx", "rdx", "r8", "r9", "r10", "cc", "memory");
  117|       |   // clang-format on
  118|   274k|}
_ZN5Botan16bigint_mulx_mul4EPmPKmS2_:
  120|  78.5k|void bigint_mulx_mul4(word z[8], const word x[4], const word y[4]) {
  121|       |   // clang-format off
  122|  78.5k|   asm(
  123|  78.5k|      "xorl %%r8d, %%r8d\n\t"
  124|  78.5k|      "xorl %%r9d, %%r9d\n\t"
  125|  78.5k|      "xorl %%r10d, %%r10d\n\t"
  126|  78.5k|      "xorl %%r11d, %%r11d\n\t"
  127|       |
  128|  78.5k|      "movq 0(%[y]), %%rdx\n\t"  // row 0: x * y[0]
  129|  78.5k|      "xorl %%eax, %%eax\n\t"
  130|  78.5k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  131|  78.5k|      "adcx %%rax, %%r8\n\t"
  132|  78.5k|      "movq %%r8, 0(%[z])\n\t"
  133|  78.5k|      "mulx 8(%[x]), %%rax, %%r8\n\t"
  134|  78.5k|      "adox %%rcx, %%rax\n\t"
  135|  78.5k|      "adcx %%rax, %%r9\n\t"
  136|  78.5k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  137|  78.5k|      "adox %%r8, %%rax\n\t"
  138|  78.5k|      "adcx %%rax, %%r10\n\t"
  139|  78.5k|      "mulx 24(%[x]), %%rax, %%r8\n\t"
  140|  78.5k|      "adox %%rcx, %%rax\n\t"
  141|  78.5k|      "adcx %%rax, %%r11\n\t"
  142|  78.5k|      "movl $0, %%eax\n\t"
  143|  78.5k|      "adox %%rax, %%r8\n\t"
  144|  78.5k|      "adcx %%rax, %%r8\n\t"
  145|       |
  146|  78.5k|      "movq 8(%[y]), %%rdx\n\t"  // row 1: x * y[1]
  147|  78.5k|      "xorl %%eax, %%eax\n\t"
  148|  78.5k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  149|  78.5k|      "adcx %%rax, %%r9\n\t"
  150|  78.5k|      "movq %%r9, 8(%[z])\n\t"
  151|  78.5k|      "mulx 8(%[x]), %%rax, %%r9\n\t"
  152|  78.5k|      "adox %%rcx, %%rax\n\t"
  153|  78.5k|      "adcx %%rax, %%r10\n\t"
  154|  78.5k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  155|  78.5k|      "adox %%r9, %%rax\n\t"
  156|  78.5k|      "adcx %%rax, %%r11\n\t"
  157|  78.5k|      "mulx 24(%[x]), %%rax, %%r9\n\t"
  158|  78.5k|      "adox %%rcx, %%rax\n\t"
  159|  78.5k|      "adcx %%rax, %%r8\n\t"
  160|  78.5k|      "movl $0, %%eax\n\t"
  161|  78.5k|      "adox %%rax, %%r9\n\t"
  162|  78.5k|      "adcx %%rax, %%r9\n\t"
  163|       |
  164|  78.5k|      "movq 16(%[y]), %%rdx\n\t"  // row 2: x * y[2]
  165|  78.5k|      "xorl %%eax, %%eax\n\t"
  166|  78.5k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  167|  78.5k|      "adcx %%rax, %%r10\n\t"
  168|  78.5k|      "movq %%r10, 16(%[z])\n\t"
  169|  78.5k|      "mulx 8(%[x]), %%rax, %%r10\n\t"
  170|  78.5k|      "adox %%rcx, %%rax\n\t"
  171|  78.5k|      "adcx %%rax, %%r11\n\t"
  172|  78.5k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  173|  78.5k|      "adox %%r10, %%rax\n\t"
  174|  78.5k|      "adcx %%rax, %%r8\n\t"
  175|  78.5k|      "mulx 24(%[x]), %%rax, %%r10\n\t"
  176|  78.5k|      "adox %%rcx, %%rax\n\t"
  177|  78.5k|      "adcx %%rax, %%r9\n\t"
  178|  78.5k|      "movl $0, %%eax\n\t"
  179|  78.5k|      "adox %%rax, %%r10\n\t"
  180|  78.5k|      "adcx %%rax, %%r10\n\t"
  181|       |
  182|  78.5k|      "movq 24(%[y]), %%rdx\n\t"  // row 3: x * y[3]
  183|  78.5k|      "xorl %%eax, %%eax\n\t"
  184|  78.5k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  185|  78.5k|      "adcx %%rax, %%r11\n\t"
  186|  78.5k|      "movq %%r11, 24(%[z])\n\t"
  187|  78.5k|      "mulx 8(%[x]), %%rax, %%r11\n\t"
  188|  78.5k|      "adox %%rcx, %%rax\n\t"
  189|  78.5k|      "adcx %%rax, %%r8\n\t"
  190|  78.5k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  191|  78.5k|      "adox %%r11, %%rax\n\t"
  192|  78.5k|      "adcx %%rax, %%r9\n\t"
  193|  78.5k|      "mulx 24(%[x]), %%rax, %%r11\n\t"
  194|  78.5k|      "adox %%rcx, %%rax\n\t"
  195|  78.5k|      "adcx %%rax, %%r10\n\t"
  196|  78.5k|      "movl $0, %%eax\n\t"
  197|  78.5k|      "adox %%rax, %%r11\n\t"
  198|  78.5k|      "adcx %%rax, %%r11\n\t"
  199|       |
  200|  78.5k|      "movq %%r8, 32(%[z])\n\t"
  201|  78.5k|      "movq %%r9, 40(%[z])\n\t"
  202|  78.5k|      "movq %%r10, 48(%[z])\n\t"
  203|  78.5k|      "movq %%r11, 56(%[z])\n\t"
  204|  78.5k|      :
  205|  78.5k|      : [z] "r"(z), [x] "r"(x), [y] "r"(y)
  206|  78.5k|      : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "cc", "memory");
  207|       |   // clang-format on
  208|  78.5k|}
_ZN5Botan16bigint_mulx_mul6EPmPKmS2_:
  367|  16.7k|void bigint_mulx_mul6(word z[12], const word x[6], const word y[6]) {
  368|       |   // clang-format off
  369|  16.7k|   asm(
  370|  16.7k|      "xorl %%r8d, %%r8d\n\t"
  371|  16.7k|      "xorl %%r9d, %%r9d\n\t"
  372|  16.7k|      "xorl %%r10d, %%r10d\n\t"
  373|  16.7k|      "xorl %%r11d, %%r11d\n\t"
  374|  16.7k|      "xorl %%r12d, %%r12d\n\t"
  375|  16.7k|      "xorl %%r13d, %%r13d\n\t"
  376|       |
  377|  16.7k|      "movq 0(%[y]), %%rdx\n\t"  // row 0: x * y[0]
  378|  16.7k|      "xorl %%eax, %%eax\n\t"
  379|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  380|  16.7k|      "adcx %%rax, %%r8\n\t"
  381|  16.7k|      "movq %%r8, 0(%[z])\n\t"
  382|  16.7k|      "mulx 8(%[x]), %%rax, %%r8\n\t"
  383|  16.7k|      "adox %%rcx, %%rax\n\t"
  384|  16.7k|      "adcx %%rax, %%r9\n\t"
  385|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  386|  16.7k|      "adox %%r8, %%rax\n\t"
  387|  16.7k|      "adcx %%rax, %%r10\n\t"
  388|  16.7k|      "mulx 24(%[x]), %%rax, %%r8\n\t"
  389|  16.7k|      "adox %%rcx, %%rax\n\t"
  390|  16.7k|      "adcx %%rax, %%r11\n\t"
  391|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  392|  16.7k|      "adox %%r8, %%rax\n\t"
  393|  16.7k|      "adcx %%rax, %%r12\n\t"
  394|  16.7k|      "mulx 40(%[x]), %%rax, %%r8\n\t"
  395|  16.7k|      "adox %%rcx, %%rax\n\t"
  396|  16.7k|      "adcx %%rax, %%r13\n\t"
  397|  16.7k|      "movl $0, %%eax\n\t"
  398|  16.7k|      "adox %%rax, %%r8\n\t"
  399|  16.7k|      "adcx %%rax, %%r8\n\t"
  400|       |
  401|  16.7k|      "movq 8(%[y]), %%rdx\n\t"  // row 1: x * y[1]
  402|  16.7k|      "xorl %%eax, %%eax\n\t"
  403|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  404|  16.7k|      "adcx %%rax, %%r9\n\t"
  405|  16.7k|      "movq %%r9, 8(%[z])\n\t"
  406|  16.7k|      "mulx 8(%[x]), %%rax, %%r9\n\t"
  407|  16.7k|      "adox %%rcx, %%rax\n\t"
  408|  16.7k|      "adcx %%rax, %%r10\n\t"
  409|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  410|  16.7k|      "adox %%r9, %%rax\n\t"
  411|  16.7k|      "adcx %%rax, %%r11\n\t"
  412|  16.7k|      "mulx 24(%[x]), %%rax, %%r9\n\t"
  413|  16.7k|      "adox %%rcx, %%rax\n\t"
  414|  16.7k|      "adcx %%rax, %%r12\n\t"
  415|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  416|  16.7k|      "adox %%r9, %%rax\n\t"
  417|  16.7k|      "adcx %%rax, %%r13\n\t"
  418|  16.7k|      "mulx 40(%[x]), %%rax, %%r9\n\t"
  419|  16.7k|      "adox %%rcx, %%rax\n\t"
  420|  16.7k|      "adcx %%rax, %%r8\n\t"
  421|  16.7k|      "movl $0, %%eax\n\t"
  422|  16.7k|      "adox %%rax, %%r9\n\t"
  423|  16.7k|      "adcx %%rax, %%r9\n\t"
  424|       |
  425|  16.7k|      "movq 16(%[y]), %%rdx\n\t"  // row 2: x * y[2]
  426|  16.7k|      "xorl %%eax, %%eax\n\t"
  427|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  428|  16.7k|      "adcx %%rax, %%r10\n\t"
  429|  16.7k|      "movq %%r10, 16(%[z])\n\t"
  430|  16.7k|      "mulx 8(%[x]), %%rax, %%r10\n\t"
  431|  16.7k|      "adox %%rcx, %%rax\n\t"
  432|  16.7k|      "adcx %%rax, %%r11\n\t"
  433|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  434|  16.7k|      "adox %%r10, %%rax\n\t"
  435|  16.7k|      "adcx %%rax, %%r12\n\t"
  436|  16.7k|      "mulx 24(%[x]), %%rax, %%r10\n\t"
  437|  16.7k|      "adox %%rcx, %%rax\n\t"
  438|  16.7k|      "adcx %%rax, %%r13\n\t"
  439|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  440|  16.7k|      "adox %%r10, %%rax\n\t"
  441|  16.7k|      "adcx %%rax, %%r8\n\t"
  442|  16.7k|      "mulx 40(%[x]), %%rax, %%r10\n\t"
  443|  16.7k|      "adox %%rcx, %%rax\n\t"
  444|  16.7k|      "adcx %%rax, %%r9\n\t"
  445|  16.7k|      "movl $0, %%eax\n\t"
  446|  16.7k|      "adox %%rax, %%r10\n\t"
  447|  16.7k|      "adcx %%rax, %%r10\n\t"
  448|       |
  449|  16.7k|      "movq 24(%[y]), %%rdx\n\t"  // row 3: x * y[3]
  450|  16.7k|      "xorl %%eax, %%eax\n\t"
  451|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  452|  16.7k|      "adcx %%rax, %%r11\n\t"
  453|  16.7k|      "movq %%r11, 24(%[z])\n\t"
  454|  16.7k|      "mulx 8(%[x]), %%rax, %%r11\n\t"
  455|  16.7k|      "adox %%rcx, %%rax\n\t"
  456|  16.7k|      "adcx %%rax, %%r12\n\t"
  457|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  458|  16.7k|      "adox %%r11, %%rax\n\t"
  459|  16.7k|      "adcx %%rax, %%r13\n\t"
  460|  16.7k|      "mulx 24(%[x]), %%rax, %%r11\n\t"
  461|  16.7k|      "adox %%rcx, %%rax\n\t"
  462|  16.7k|      "adcx %%rax, %%r8\n\t"
  463|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  464|  16.7k|      "adox %%r11, %%rax\n\t"
  465|  16.7k|      "adcx %%rax, %%r9\n\t"
  466|  16.7k|      "mulx 40(%[x]), %%rax, %%r11\n\t"
  467|  16.7k|      "adox %%rcx, %%rax\n\t"
  468|  16.7k|      "adcx %%rax, %%r10\n\t"
  469|  16.7k|      "movl $0, %%eax\n\t"
  470|  16.7k|      "adox %%rax, %%r11\n\t"
  471|  16.7k|      "adcx %%rax, %%r11\n\t"
  472|       |
  473|  16.7k|      "movq 32(%[y]), %%rdx\n\t"  // row 4: x * y[4]
  474|  16.7k|      "xorl %%eax, %%eax\n\t"
  475|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  476|  16.7k|      "adcx %%rax, %%r12\n\t"
  477|  16.7k|      "movq %%r12, 32(%[z])\n\t"
  478|  16.7k|      "mulx 8(%[x]), %%rax, %%r12\n\t"
  479|  16.7k|      "adox %%rcx, %%rax\n\t"
  480|  16.7k|      "adcx %%rax, %%r13\n\t"
  481|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  482|  16.7k|      "adox %%r12, %%rax\n\t"
  483|  16.7k|      "adcx %%rax, %%r8\n\t"
  484|  16.7k|      "mulx 24(%[x]), %%rax, %%r12\n\t"
  485|  16.7k|      "adox %%rcx, %%rax\n\t"
  486|  16.7k|      "adcx %%rax, %%r9\n\t"
  487|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  488|  16.7k|      "adox %%r12, %%rax\n\t"
  489|  16.7k|      "adcx %%rax, %%r10\n\t"
  490|  16.7k|      "mulx 40(%[x]), %%rax, %%r12\n\t"
  491|  16.7k|      "adox %%rcx, %%rax\n\t"
  492|  16.7k|      "adcx %%rax, %%r11\n\t"
  493|  16.7k|      "movl $0, %%eax\n\t"
  494|  16.7k|      "adox %%rax, %%r12\n\t"
  495|  16.7k|      "adcx %%rax, %%r12\n\t"
  496|       |
  497|  16.7k|      "movq 40(%[y]), %%rdx\n\t"  // row 5: x * y[5]
  498|  16.7k|      "xorl %%eax, %%eax\n\t"
  499|  16.7k|      "mulx 0(%[x]), %%rax, %%rcx\n\t"
  500|  16.7k|      "adcx %%rax, %%r13\n\t"
  501|  16.7k|      "movq %%r13, 40(%[z])\n\t"
  502|  16.7k|      "mulx 8(%[x]), %%rax, %%r13\n\t"
  503|  16.7k|      "adox %%rcx, %%rax\n\t"
  504|  16.7k|      "adcx %%rax, %%r8\n\t"
  505|  16.7k|      "mulx 16(%[x]), %%rax, %%rcx\n\t"
  506|  16.7k|      "adox %%r13, %%rax\n\t"
  507|  16.7k|      "adcx %%rax, %%r9\n\t"
  508|  16.7k|      "mulx 24(%[x]), %%rax, %%r13\n\t"
  509|  16.7k|      "adox %%rcx, %%rax\n\t"
  510|  16.7k|      "adcx %%rax, %%r10\n\t"
  511|  16.7k|      "mulx 32(%[x]), %%rax, %%rcx\n\t"
  512|  16.7k|      "adox %%r13, %%rax\n\t"
  513|  16.7k|      "adcx %%rax, %%r11\n\t"
  514|  16.7k|      "mulx 40(%[x]), %%rax, %%r13\n\t"
  515|  16.7k|      "adox %%rcx, %%rax\n\t"
  516|  16.7k|      "adcx %%rax, %%r12\n\t"
  517|  16.7k|      "movl $0, %%eax\n\t"
  518|  16.7k|      "adox %%rax, %%r13\n\t"
  519|  16.7k|      "adcx %%rax, %%r13\n\t"
  520|       |
  521|  16.7k|      "movq %%r8, 48(%[z])\n\t"
  522|  16.7k|      "movq %%r9, 56(%[z])\n\t"
  523|  16.7k|      "movq %%r10, 64(%[z])\n\t"
  524|  16.7k|      "movq %%r11, 72(%[z])\n\t"
  525|  16.7k|      "movq %%r12, 80(%[z])\n\t"
  526|  16.7k|      "movq %%r13, 88(%[z])\n\t"
  527|  16.7k|      :
  528|  16.7k|      : [z] "r"(z), [x] "r"(x), [y] "r"(y)
  529|  16.7k|      : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc", "memory");
  530|       |   // clang-format on
  531|  16.7k|}

_ZN5Botan17Barrett_ReductionC2ERKNS_6BigIntES1_m:
   17|    545|      m_modulus(m), m_mu(std::move(mu)), m_mod_words(mw), m_modulus_bits(m.bits()) {
   18|       |   // Give some extra space for Karatsuba
   19|    545|   m_modulus.grow_to(m_mod_words + 8);
   20|    545|   m_mu.grow_to(m_mod_words + 8);
   21|    545|}
_ZN5Botan17Barrett_Reduction18for_secret_modulusERKNS_6BigIntE:
   23|    545|Barrett_Reduction Barrett_Reduction::for_secret_modulus(const BigInt& mod) {
   24|    545|   BOTAN_ARG_CHECK(mod.signum() > 0, "Modulus must be positive");
  ------------------
  |  |   35|    545|   do {                                                          \
  |  |   36|    545|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    545|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 545]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    545|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 545]
  |  |  ------------------
  ------------------
   25|       |
   26|    545|   const size_t mod_words = mod.sig_words();
   27|       |
   28|       |   // Compute mu = floor(2^{2k} / m)
   29|    545|   const size_t mu_bits = 2 * WordInfo<word>::bits * mod_words;
   30|    545|   return Barrett_Reduction(mod, ct_divide_pow2k(mu_bits, mod), mod_words);
   31|    545|}
_ZN5Botan17Barrett_Reduction18for_public_modulusERKNS_6BigIntE:
   33|    530|Barrett_Reduction Barrett_Reduction::for_public_modulus(const BigInt& mod) {
   34|    530|   return Barrett_Reduction::for_secret_modulus(mod);
   35|    530|}
_ZNK5Botan17Barrett_Reduction8multiplyERKNS_6BigIntES3_:
  153|  3.22k|BigInt Barrett_Reduction::multiply(const BigInt& x, const BigInt& y) const {
  154|  3.22k|   BOTAN_ARG_CHECK(acceptable_barrett_input(x, m_modulus).as_bool(), "Invalid x param for Barrett multiply");
  ------------------
  |  |   35|  3.22k|   do {                                                          \
  |  |   36|  3.22k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  3.22k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 3.22k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  3.22k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 3.22k]
  |  |  ------------------
  ------------------
  155|  3.22k|   BOTAN_ARG_CHECK(acceptable_barrett_input(y, m_modulus).as_bool(), "Invalid y param for Barrett multiply");
  ------------------
  |  |   35|  3.22k|   do {                                                          \
  |  |   36|  3.22k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  3.22k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 3.22k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  3.22k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 3.22k]
  |  |  ------------------
  ------------------
  156|       |
  157|  3.22k|   secure_vector<word> ws(2 * (m_mod_words + 2));
  158|  3.22k|   secure_vector<word> xy(2 * m_mod_words);
  159|       |
  160|  3.22k|   bigint_mul(xy.data(),
  161|  3.22k|              xy.size(),
  162|  3.22k|              x._data(),
  163|  3.22k|              x.size(),
  164|  3.22k|              std::min(x.size(), m_mod_words),
  165|  3.22k|              y._data(),
  166|  3.22k|              y.size(),
  167|  3.22k|              std::min(y.size(), m_mod_words),
  168|  3.22k|              ws.data(),
  169|  3.22k|              ws.size());
  170|       |
  171|  3.22k|   return barrett_reduce(m_mod_words, m_modulus, m_mu, xy, ws);
  172|  3.22k|}
_ZNK5Botan17Barrett_Reduction6squareERKNS_6BigIntE:
  174|  4.05k|BigInt Barrett_Reduction::square(const BigInt& x) const {
  175|  4.05k|   BOTAN_ARG_CHECK(acceptable_barrett_input(x, m_modulus).as_bool(), "Invalid x param for Barrett square");
  ------------------
  |  |   35|  4.05k|   do {                                                          \
  |  |   36|  4.05k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  4.05k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 4.05k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  4.05k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 4.05k]
  |  |  ------------------
  ------------------
  176|       |
  177|  4.05k|   secure_vector<word> ws(2 * (m_mod_words + 2));
  178|  4.05k|   secure_vector<word> x2(2 * m_mod_words);
  179|       |
  180|  4.05k|   bigint_sqr(x2.data(), x2.size(), x._data(), x.size(), std::min(x.size(), m_mod_words), ws.data(), ws.size());
  181|       |
  182|  4.05k|   return barrett_reduce(m_mod_words, m_modulus, m_mu, x2, ws);
  183|  4.05k|}
_ZNK5Botan17Barrett_Reduction6reduceERKNS_6BigIntE:
  185|  1.07k|BigInt Barrett_Reduction::reduce(const BigInt& x) const {
  186|  1.07k|   BOTAN_ARG_CHECK(x.signum() >= 0, "Argument must be non-negative");
  ------------------
  |  |   35|  1.07k|   do {                                                          \
  |  |   36|  1.07k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  1.07k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1.07k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  1.07k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1.07k]
  |  |  ------------------
  ------------------
  187|       |
  188|  1.07k|   const size_t x_sw = x.sig_words();
  189|  1.07k|   BOTAN_ARG_CHECK(x_sw <= 2 * m_mod_words, "Argument is too large for Barrett reduction");
  ------------------
  |  |   35|  1.07k|   do {                                                          \
  |  |   36|  1.07k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  1.07k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1.07k]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  1.07k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1.07k]
  |  |  ------------------
  ------------------
  190|       |
  191|  1.07k|   x.grow_to(2 * m_mod_words);
  192|       |
  193|  1.07k|   secure_vector<word> ws;
  194|  1.07k|   return barrett_reduce(m_mod_words, m_modulus, m_mu, x._as_span(), ws);
  195|  1.07k|}
barrett.cpp:_ZN5Botan12_GLOBAL__N_124acceptable_barrett_inputERKNS_6BigIntES3_:
  145|  10.5k|CT::Choice acceptable_barrett_input(const BigInt& x, const BigInt& modulus) {
  146|  10.5k|   const auto x_is_positive = CT::Choice::from_int(static_cast<uint32_t>(x.signum() >= 0));
  147|  10.5k|   const auto x_lt_mod = bigint_ct_is_lt(x._data(), x.size(), modulus._data(), modulus.sig_words()).as_choice();
  148|  10.5k|   return x_is_positive && x_lt_mod;
  149|  10.5k|}
barrett.cpp:_ZN5Botan12_GLOBAL__N_114barrett_reduceEmRKNS_6BigIntES3_NSt3__14spanIKmLm18446744073709551615EEERNS4_6vectorImNS_16secure_allocatorImEEEE:
   48|  8.35k|   size_t mod_words, const BigInt& modulus, const BigInt& mu, std::span<const word> x_words, secure_vector<word>& ws) {
   49|  8.35k|   BOTAN_ASSERT_NOMSG(modulus.sig_words() == mod_words);
  ------------------
  |  |   84|  8.35k|   do {                                                                     \
  |  |   85|  8.35k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  8.35k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 8.35k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  8.35k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 8.35k]
  |  |  ------------------
  ------------------
   50|       |
   51|       |   // Caller must expand input to be at least this size
   52|  8.35k|   BOTAN_ASSERT_NOMSG(x_words.size() >= 2 * mod_words);
  ------------------
  |  |   84|  8.35k|   do {                                                                     \
  |  |   85|  8.35k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  8.35k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 8.35k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  8.35k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 8.35k]
  |  |  ------------------
  ------------------
   53|       |
   54|       |   // Normally mod_words + 1 but can be + 2 if the modulus is a power of 2
   55|  8.35k|   const size_t mu_words = mu.sig_words();
   56|  8.35k|   BOTAN_ASSERT_NOMSG(mu_words <= mod_words + 2);
  ------------------
  |  |   84|  8.35k|   do {                                                                     \
  |  |   85|  8.35k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  8.35k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 8.35k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  8.35k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 8.35k]
  |  |  ------------------
  ------------------
   57|       |
   58|  8.35k|   if(ws.size() < 2 * (mod_words + 2)) {
  ------------------
  |  Branch (58:7): [True: 1.07k, False: 7.28k]
  ------------------
   59|  1.07k|      ws.resize(2 * (mod_words + 2));
   60|  1.07k|   }
   61|       |
   62|  8.35k|   CT::poison(x_words);
   63|       |
   64|       |   /*
   65|       |   * Following the notation of Handbook of Applied Cryptography
   66|       |   * Algorithm 14.42 "Barrett modular reduction", page 604
   67|       |   * <https://cacr.uwaterloo.ca/hac/about/chap14.pdf>
   68|       |   *
   69|       |   * Using `mu` for µ in the code
   70|       |   */
   71|       |
   72|       |   // Compute q1 = floor(x / 2^(k - 1)) which is equivalent to ignoring the low (k-1) words
   73|       |
   74|       |   // 2 * mod_words + 1 is sufficient, extra is to enable Karatsuba
   75|  8.35k|   secure_vector<word> r(2 * mu_words + 2);
   76|       |
   77|  8.35k|   copy_mem(r.data(), x_words.data() + (mod_words - 1), mod_words + 1);
   78|       |
   79|       |   // Now compute q2 = q1 * µ
   80|       |
   81|       |   // We allocate more size than required since this allows Karatsuba more often;
   82|       |   // just `mu_words + (mod_words + 1)` is sufficient
   83|  8.35k|   const size_t q2_size = 2 * mu_words + 2;
   84|       |
   85|  8.35k|   secure_vector<word> q2(q2_size);
   86|       |
   87|  8.35k|   bigint_mul(
   88|  8.35k|      q2.data(), q2.size(), r.data(), r.size(), mod_words + 1, mu._data(), mu.size(), mu_words, ws.data(), ws.size());
   89|       |
   90|       |   // Compute r2 = (floor(q2 / b^(k+1)) * m) mod 2^(k+1)
   91|       |   // The division/floor is again effected by just ignoring the low k + 1 words
   92|  8.35k|   bigint_mul(r.data(),
   93|  8.35k|              r.size(),
   94|  8.35k|              &q2[mod_words + 1],  // ignoring the low mod_words + 1 words of the first product
   95|  8.35k|              q2.size() - (mod_words + 1),
   96|  8.35k|              mod_words + 1,
   97|  8.35k|              modulus._data(),
   98|  8.35k|              modulus.size(),
   99|  8.35k|              mod_words,
  100|  8.35k|              ws.data(),
  101|  8.35k|              ws.size());
  102|       |
  103|       |   // Clear the high words of the product, equivalent to computing mod 2^(k+1)
  104|       |   // TODO add masked mul to avoid computing high bits at all
  105|  8.35k|   clear_mem(std::span{r}.subspan(mod_words + 1));
  106|       |
  107|       |   // Compute r = r1 - r2
  108|       |
  109|       |   // The return value of bigint_sub_abs isn't quite right for what we need here so first compare
  110|  8.35k|   const int32_t relative_size = bigint_cmp(r.data(), mod_words + 1, x_words.data(), mod_words + 1);
  111|       |
  112|  8.35k|   bigint_sub_abs(r.data(), r.data(), x_words.data(), mod_words + 1, ws.data());
  113|       |
  114|       |   /*
  115|       |   If r is negative then we have to set r to r + 2^(k+1)
  116|       |
  117|       |   However for r negative computing this sum is equivalent to computing 2^(k+1) - abs(r)
  118|       |   */
  119|  8.35k|   clear_mem(ws.data(), mod_words + 2);
  120|  8.35k|   ws[mod_words + 1] = 1;
  121|  8.35k|   bigint_sub2(ws.data(), mod_words + 2, r.data(), mod_words + 2);
  122|       |
  123|       |   // If relative_size > 0 then assign r to 2^(k+1) - r
  124|  8.35k|   CT::Mask<word>::is_equal(static_cast<word>(relative_size), 1).select_n(r.data(), ws.data(), r.data(), mod_words + 2);
  125|       |
  126|       |   /*
  127|       |   * Per HAC Note 14.44 (ii) "step 4 is repeated at most twice since 0 <= r < 3m"
  128|       |   */
  129|  8.35k|   const size_t bound = 2;
  130|       |
  131|  8.35k|   BOTAN_ASSERT_NOMSG(r.size() >= mod_words + 1);
  ------------------
  |  |   84|  8.35k|   do {                                                                     \
  |  |   85|  8.35k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  8.35k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 8.35k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  8.35k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 8.35k]
  |  |  ------------------
  ------------------
  132|  25.0k|   for(size_t i = 0; i != bound; ++i) {
  ------------------
  |  Branch (132:22): [True: 16.7k, False: 8.35k]
  ------------------
  133|  16.7k|      const word borrow = bigint_sub3(ws.data(), r.data(), mod_words + 1, modulus._data(), mod_words);
  134|  16.7k|      CT::Mask<word>::is_zero(borrow).select_n(r.data(), ws.data(), r.data(), mod_words + 1);
  135|  16.7k|   }
  136|       |
  137|  8.35k|   CT::unpoison(q2);
  138|  8.35k|   CT::unpoison(r);
  139|  8.35k|   CT::unpoison(ws);
  140|  8.35k|   CT::unpoison(x_words);
  141|       |
  142|  8.35k|   return BigInt::_from_words(r);
  143|  8.35k|}

_ZN5Botan12random_primeERNS_21RandomNumberGeneratorEmRKNS_6BigIntEmmm:
  190|      1|   RandomNumberGenerator& rng, size_t bits, const BigInt& coprime, size_t equiv, size_t modulo, size_t prob) {
  191|      1|   if(bits <= 1) {
  ------------------
  |  Branch (191:7): [True: 0, False: 1]
  ------------------
  192|      0|      throw Invalid_Argument("random_prime: Can't make a prime of " + std::to_string(bits) + " bits");
  193|      0|   }
  194|      1|   if(coprime.signum() < 0 || (coprime.signum() != 0 && coprime.is_even()) || coprime.bits() >= bits) {
  ------------------
  |  Branch (194:7): [True: 0, False: 1]
  |  Branch (194:32): [True: 0, False: 1]
  |  Branch (194:57): [True: 0, False: 0]
  |  Branch (194:79): [True: 0, False: 1]
  ------------------
  195|      0|      throw Invalid_Argument("random_prime: invalid coprime");
  196|      0|   }
  197|       |   // TODO(Botan4) reduce this to ~1000
  198|      1|   if(modulo == 0 || modulo >= 100000) {
  ------------------
  |  Branch (198:7): [True: 0, False: 1]
  |  Branch (198:22): [True: 0, False: 1]
  ------------------
  199|      0|      throw Invalid_Argument("random_prime: Invalid modulo value");
  200|      0|   }
  201|       |
  202|       |   // TODO(Botan4) reject equiv > modulo instead of reducing here
  203|      1|   equiv %= modulo;
  204|       |
  205|      1|   if(equiv == 0) {
  ------------------
  |  Branch (205:7): [True: 0, False: 1]
  ------------------
  206|      0|      throw Invalid_Argument("random_prime Invalid value for equiv/modulo");
  207|      0|   }
  208|       |
  209|       |   // Handle small values:
  210|       |
  211|      1|   if(bits <= 16) {
  ------------------
  |  Branch (211:7): [True: 0, False: 1]
  ------------------
  212|      0|      if(equiv != 1 || modulo != 2 || coprime != 0) {
  ------------------
  |  Branch (212:10): [True: 0, False: 0]
  |  Branch (212:24): [True: 0, False: 0]
  |  Branch (212:39): [True: 0, False: 0]
  ------------------
  213|      0|         throw Not_Implemented("random_prime equiv/modulo/coprime options not usable for small primes");
  214|      0|      }
  215|       |
  216|      0|      if(bits == 2) {
  ------------------
  |  Branch (216:10): [True: 0, False: 0]
  ------------------
  217|      0|         return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 2 : 3));
  ------------------
  |  Branch (217:36): [True: 0, False: 0]
  ------------------
  218|      0|      } else if(bits == 3) {
  ------------------
  |  Branch (218:17): [True: 0, False: 0]
  ------------------
  219|      0|         return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 5 : 7));
  ------------------
  |  Branch (219:36): [True: 0, False: 0]
  ------------------
  220|      0|      } else if(bits == 4) {
  ------------------
  |  Branch (220:17): [True: 0, False: 0]
  ------------------
  221|      0|         return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 11 : 13));
  ------------------
  |  Branch (221:36): [True: 0, False: 0]
  ------------------
  222|      0|      } else {
  223|      0|         for(;;) {
  224|       |            // This is slightly biased, but for small primes it does not seem to matter
  225|      0|            uint8_t b[4] = {0};
  226|      0|            rng.randomize(b, 4);
  227|      0|            const size_t idx = load_le<uint32_t>(b, 0) % PRIME_TABLE_SIZE;
  228|      0|            const uint16_t small_prime = PRIMES[idx];
  229|       |
  230|      0|            if(high_bit(small_prime) == bits) {
  ------------------
  |  Branch (230:16): [True: 0, False: 0]
  ------------------
  231|      0|               return BigInt::from_word(small_prime);
  232|      0|            }
  233|      0|         }
  234|      0|      }
  235|      0|   }
  236|       |
  237|       |   // The check_2p1 sieve filter is only appropriate when generating q for a
  238|       |   // safe prime; for arbitrary equiv/modulo it can pre-reject every candidate
  239|       |   // (eg equiv=1, modulo=3 makes the residue mod 3 always equal (3-1)/2).
  240|      1|   return random_prime_with_sieve(rng, bits, coprime, equiv, modulo, prob, false);
  241|      1|}
make_prm.cpp:_ZN5Botan12_GLOBAL__N_123random_prime_with_sieveERNS_21RandomNumberGeneratorEmRKNS_6BigIntEmmmb:
  110|      1|                               bool sieve_check_2p1) {
  111|      1|   const size_t MAX_ATTEMPTS = 32 * 1024;
  112|       |
  113|      1|   const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
  114|       |
  115|       |   // Variable time gcd here is fine since these are generation parameters, not secrets
  116|      1|   if(std::gcd(equiv, modulo) != 1) {
  ------------------
  |  Branch (116:7): [True: 0, False: 1]
  ------------------
  117|      0|      throw Invalid_Argument("random_prime equiv and modulo must be relatively prime");
  118|      0|   }
  119|       |
  120|      1|   while(true) {
  ------------------
  |  Branch (120:10): [True: 1, Folded]
  ------------------
  121|      1|      BigInt p(rng, bits);
  122|       |
  123|       |      // Force lowest and two top bits on
  124|      1|      p.set_bit(bits - 1);
  125|      1|      p.set_bit(bits - 2);
  126|      1|      p.set_bit(0);
  127|       |
  128|       |      // Force p to be equal to equiv mod modulo
  129|      1|      p += (modulo - (p % modulo)) + equiv;
  130|       |
  131|      1|      Prime_Sieve sieve(p, bits, modulo, sieve_check_2p1);
  132|       |
  133|     96|      for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
  ------------------
  |  Branch (133:31): [True: 96, False: 0]
  ------------------
  134|     96|         p += modulo;
  135|       |
  136|     96|         if(!sieve.next()) {
  ------------------
  |  Branch (136:13): [True: 81, False: 15]
  ------------------
  137|     81|            continue;
  138|     81|         }
  139|       |
  140|       |         // here p can be even if modulo is odd, continue on in that case
  141|     15|         if(p.is_even()) {
  ------------------
  |  Branch (141:13): [True: 0, False: 15]
  ------------------
  142|      0|            continue;
  143|      0|         }
  144|       |
  145|     15|         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
  ------------------
  |  |  137|     15|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|     15|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 15]
  |  |  ------------------
  ------------------
  146|       |
  147|     15|         const Montgomery_Params monty_p(p);
  148|       |
  149|     15|         if(coprime > 1) {
  ------------------
  |  Branch (149:13): [True: 0, False: 15]
  ------------------
  150|       |            /*
  151|       |            First do a single M-R iteration to quickly eliminate most non-primes,
  152|       |            before doing the coprimality check which is expensive
  153|       |            */
  154|      0|            if(!is_miller_rabin_probable_prime(p, monty_p, rng, 1)) {
  ------------------
  |  Branch (154:16): [True: 0, False: 0]
  ------------------
  155|      0|               continue;
  156|      0|            }
  157|       |
  158|       |            /*
  159|       |            * Check if p - 1 and coprime are relatively prime, using gcd.
  160|       |            * The gcd computation is const-time
  161|       |            */
  162|      0|            if(gcd(p - 1, coprime) > 1) {
  ------------------
  |  Branch (162:16): [True: 0, False: 0]
  ------------------
  163|      0|               continue;
  164|      0|            }
  165|      0|         }
  166|       |
  167|     15|         if(p.bits() > bits) {
  ------------------
  |  Branch (167:13): [True: 0, False: 15]
  ------------------
  168|      0|            break;
  169|      0|         }
  170|       |
  171|     15|         if(!is_miller_rabin_probable_prime(p, monty_p, rng, mr_trials)) {
  ------------------
  |  Branch (171:13): [True: 14, False: 1]
  ------------------
  172|     14|            continue;
  173|     14|         }
  174|       |
  175|      1|         if(prob > 32 && !is_lucas_probable_prime(p, monty_p)) {
  ------------------
  |  Branch (175:13): [True: 1, False: 0]
  |  Branch (175:26): [True: 0, False: 1]
  ------------------
  176|      0|            continue;
  177|      0|         }
  178|       |
  179|      1|         return p;
  180|      1|      }
  181|      1|   }
  182|      1|}
make_prm.cpp:_ZN5Botan12_GLOBAL__N_111Prime_SieveC2ERKNS_6BigIntEmmb:
   26|      1|            m_sieve(mod_small_primes(init_value, std::min(sieve_size, PRIME_TABLE_SIZE))),
   27|      1|            m_step(step),
   28|      1|            m_check_2p1(check_2p1) {}
make_prm.cpp:_ZN5Botan12_GLOBAL__N_111Prime_Sieve4nextEv:
   34|     96|      bool next() {
   35|     96|         auto passes = CT::Mask<word>::set();
   36|  24.6k|         for(size_t i = 0; i != m_sieve.size(); ++i) {
  ------------------
  |  Branch (36:28): [True: 24.5k, False: 96]
  ------------------
   37|  24.5k|            m_sieve[i] = sieve_step_incr(m_sieve[i], m_step, PRIMES[i]);
   38|       |
   39|       |            // If m_sieve[i] == 0 then val % p == 0 -> not prime
   40|  24.5k|            passes &= CT::Mask<word>::expand(m_sieve[i]);
   41|       |
   42|  24.5k|            if(this->check_2p1()) {
  ------------------
  |  Branch (42:16): [True: 0, False: 24.5k]
  ------------------
   43|       |               /*
   44|       |               If v % p == (p-1)/2 then 2*v+1 == 0 (mod p)
   45|       |
   46|       |               So if potentially generating a safe prime, we want to
   47|       |               avoid this value because 2*v+1 will certainly not be prime.
   48|       |
   49|       |               See "Safe Prime Generation with a Combined Sieve" M. Wiener
   50|       |               https://eprint.iacr.org/2003/186.pdf
   51|       |               */
   52|      0|               passes &= ~CT::Mask<word>::is_equal(m_sieve[i], (PRIMES[i] - 1) / 2);
   53|      0|            }
   54|  24.5k|         }
   55|       |
   56|     96|         return passes.as_bool();
   57|     96|      }
make_prm.cpp:_ZN5Botan12_GLOBAL__N_111Prime_Sieve15sieve_step_incrEmmm:
   63|  24.5k|      static constexpr word sieve_step_incr(word v, word step, word mod) {
   64|  24.5k|         BOTAN_DEBUG_ASSERT(v < mod);
  ------------------
  |  |  137|  24.5k|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|  24.5k|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 24.5k]
  |  |  ------------------
  ------------------
   65|       |         // The sieve step and primes are public so this modulo is ok
   66|  24.5k|         const word stepmod = (step >= mod) ? (step % mod) : step;
  ------------------
  |  Branch (66:31): [True: 96, False: 24.4k]
  ------------------
   67|       |
   68|       |         // This sum is at most 2*(mod-1)
   69|  24.5k|         const word next = (v + stepmod);
   70|  24.5k|         return next - CT::Mask<word>::is_gte(next, mod).if_set_return(mod);
   71|  24.5k|      }
make_prm.cpp:_ZNK5Botan12_GLOBAL__N_111Prime_Sieve9check_2p1Ev:
   32|  24.5k|      bool check_2p1() const { return m_check_2p1; }

_ZN5Botan17Montgomery_Params4DataC2ERKNS_6BigIntERKNS_17Barrett_ReductionE:
   40|    544|Montgomery_Params::Data::Data(const BigInt& p, const Barrett_Reduction& mod_p) {
   41|    544|   if(p.is_even() || p < 3) {
  ------------------
  |  Branch (41:7): [True: 0, False: 544]
  |  Branch (41:22): [True: 0, False: 544]
  ------------------
   42|      0|      throw Invalid_Argument("Montgomery_Params invalid modulus");
   43|      0|   }
   44|       |
   45|    544|   m_p = p;
   46|    544|   m_p_words = m_p.sig_words();
   47|    544|   m_p_dash = monty_inverse(m_p.word_at(0));
   48|       |
   49|    544|   const BigInt r = BigInt::power_of_2(m_p_words * WordInfo<word>::bits);
   50|       |
   51|    544|   m_r1 = mod_p.reduce(r);
   52|    544|   m_r2 = mod_p.square(m_r1);
   53|    544|   m_r3 = mod_p.multiply(m_r1, m_r2);
   54|       |
   55|       |   // Barrett should be at least zero prefixing up to modulus size
   56|    544|   BOTAN_ASSERT_NOMSG(m_r1.size() >= m_p_words);
  ------------------
  |  |   84|    544|   do {                                                                     \
  |  |   85|    544|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    544|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 544]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    544|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 544]
  |  |  ------------------
  ------------------
   57|    544|   BOTAN_ASSERT_NOMSG(m_r2.size() >= m_p_words);
  ------------------
  |  |   84|    544|   do {                                                                     \
  |  |   85|    544|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    544|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 544]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    544|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 544]
  |  |  ------------------
  ------------------
   58|    544|   BOTAN_ASSERT_NOMSG(m_r3.size() >= m_p_words);
  ------------------
  |  |   84|    544|   do {                                                                     \
  |  |   85|    544|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    544|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 544]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    544|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 544]
  |  |  ------------------
  ------------------
   59|    544|}
_ZN5Botan17Montgomery_ParamsC2ERKNS_6BigIntERKNS_17Barrett_ReductionE:
   62|    544|      m_data(std::make_shared<Data>(p, mod_p)) {}
_ZN5Botan17Montgomery_ParamsC2ERKNS_6BigIntE:
   65|     15|      Montgomery_Params(p, Barrett_Reduction::for_secret_modulus(p)) {}
_ZNK5Botan17Montgomery_ParamseqERKS0_:
   67|  72.0k|bool Montgomery_Params::operator==(const Montgomery_Params& other) const {
   68|  72.0k|   if(this->m_data == other.m_data) {
  ------------------
  |  Branch (68:7): [True: 72.0k, False: 0]
  ------------------
   69|  72.0k|      return true;
   70|  72.0k|   }
   71|       |
   72|      0|   return (this->m_data->p() == other.m_data->p());
   73|  72.0k|}
_ZN5Botan14Montgomery_IntC2ERKNS_17Montgomery_ParamsENSt3__16vectorImNS_16secure_allocatorImEEEE:
  227|  12.9k|      m_params(params), m_v(std::move(words)) {
  228|  12.9k|   BOTAN_ASSERT_NOMSG(m_v.size() == m_params.p_words());
  ------------------
  |  |   84|  12.9k|   do {                                                                     \
  |  |   85|  12.9k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  12.9k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 12.9k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  12.9k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 12.9k]
  |  |  ------------------
  ------------------
  229|  12.9k|}
_ZN5Botan14Montgomery_Int3oneERKNS_17Montgomery_ParamsE:
  231|  1.84k|Montgomery_Int Montgomery_Int::one(const Montgomery_Params& params) {
  232|  1.84k|   return Montgomery_Int(params, params.R1(), false);
  233|  1.84k|}
_ZN5Botan14Montgomery_IntC2ERKNS_17Montgomery_ParamsERKNS_6BigIntEb:
  242|  3.69k|      m_params(params), m_v(m_params.p_words()) {
  243|  3.69k|   BOTAN_ARG_CHECK(v.signum() >= 0 && v < m_params.p(), "Input out of range");
  ------------------
  |  |   35|  3.69k|   do {                                                          \
  |  |   36|  3.69k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  7.39k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 3.69k, False: 0]
  |  |  |  Branch (37:12): [True: 3.69k, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  3.69k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 3.69k]
  |  |  ------------------
  ------------------
  244|       |
  245|  3.69k|   const size_t p_size = m_params.p_words();
  246|       |
  247|  3.69k|   auto v_span = v._as_span();
  248|       |
  249|  3.69k|   if(v_span.size() > p_size) {
  ------------------
  |  Branch (249:7): [True: 3.69k, False: 0]
  ------------------
  250|       |      // Safe to truncate the span since we already checked v < p
  251|  3.69k|      v_span = v_span.first(p_size);
  252|  3.69k|   }
  253|       |
  254|  3.69k|   BOTAN_ASSERT_NOMSG(m_v.size() >= v_span.size());
  ------------------
  |  |   84|  3.69k|   do {                                                                     \
  |  |   85|  3.69k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  3.69k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 3.69k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  3.69k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 3.69k]
  |  |  ------------------
  ------------------
  255|       |
  256|  3.69k|   copy_mem(std::span{m_v}.first(v_span.size()), v_span);
  257|       |
  258|  3.69k|   if(redc_needed) {
  ------------------
  |  Branch (258:7): [True: 1.84k, False: 1.84k]
  ------------------
  259|  1.84k|      secure_vector<word> ws;
  260|  1.84k|      this->mul_by(m_params.R2()._as_span().first(p_size), ws);
  261|  1.84k|   }
  262|  3.69k|}
_ZN5Botan14Montgomery_IntC2ERKNS_17Montgomery_ParamsENSt3__14spanIKmLm18446744073709551615EEE:
  265|     43|      m_params(params), m_v(words.begin(), words.end()) {
  266|     43|   BOTAN_ARG_CHECK(m_v.size() == m_params.p_words(), "Invalid input span");
  ------------------
  |  |   35|     43|   do {                                                          \
  |  |   36|     43|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|     43|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 43]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|     43|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 43]
  |  |  ------------------
  ------------------
  267|     43|}
_ZNK5Botan14Montgomery_Int5valueEv:
  273|  1.80k|BigInt Montgomery_Int::value() const {
  274|  1.80k|   secure_vector<word> ws(m_params.p_words());
  275|       |
  276|  1.80k|   secure_vector<word> z = m_v;
  277|  1.80k|   z.resize(2 * m_params.p_words());  // zero extend
  278|       |
  279|  1.80k|   bigint_monty_redc_inplace(
  280|  1.80k|      z.data(), m_params.p()._data(), m_params.p_words(), m_params.p_dash(), ws.data(), ws.size());
  281|       |
  282|  1.80k|   return BigInt::_from_words(z);
  283|  1.80k|}
_ZNK5Botan14Montgomery_Int3mulERKS0_RNSt3__16vectorImNS_16secure_allocatorImEEEE:
  320|  12.9k|Montgomery_Int Montgomery_Int::mul(const Montgomery_Int& other, secure_vector<word>& ws) const {
  321|  12.9k|   BOTAN_STATE_CHECK(other.m_params == m_params);
  ------------------
  |  |   51|  12.9k|   do {                                                         \
  |  |   52|  12.9k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */             \
  |  |   53|  12.9k|      if(!(expr)) {                                             \
  |  |  ------------------
  |  |  |  Branch (53:10): [True: 0, False: 12.9k]
  |  |  ------------------
  |  |   54|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */    \
  |  |   55|      0|         Botan::throw_invalid_state(#expr, __func__, __FILE__); \
  |  |   56|      0|      }                                                         \
  |  |   57|  12.9k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (57:12): [Folded, False: 12.9k]
  |  |  ------------------
  ------------------
  322|       |
  323|  12.9k|   const size_t p_size = m_params.p_words();
  324|  12.9k|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size && other.m_v.size() == p_size);
  ------------------
  |  |   84|  12.9k|   do {                                                                     \
  |  |   85|  12.9k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  25.8k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:12): [True: 12.9k, False: 0]
  |  |  |  Branch (86:12): [True: 12.9k, False: 0]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  12.9k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 12.9k]
  |  |  ------------------
  ------------------
  325|       |
  326|  12.9k|   if(ws.size() < 4 * p_size) {
  ------------------
  |  Branch (326:7): [True: 0, False: 12.9k]
  ------------------
  327|      0|      ws.resize(4 * p_size);
  328|      0|   }
  329|       |
  330|  12.9k|   secure_vector<word> z(p_size);
  331|       |
  332|  12.9k|   bigint_monty_mul(
  333|  12.9k|      z.data(), m_v.data(), other.m_v.data(), m_params.p()._data(), p_size, m_params.p_dash(), ws.data(), ws.size());
  334|       |
  335|  12.9k|   return Montgomery_Int(m_params, std::move(z));
  336|  12.9k|}
_ZN5Botan14Montgomery_Int6mul_byERKS0_RNSt3__16vectorImNS_16secure_allocatorImEEEE:
  338|  57.8k|Montgomery_Int& Montgomery_Int::mul_by(const Montgomery_Int& other, secure_vector<word>& ws) {
  339|  57.8k|   BOTAN_STATE_CHECK(other.m_params == m_params);
  ------------------
  |  |   51|  57.8k|   do {                                                         \
  |  |   52|  57.8k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */             \
  |  |   53|  57.8k|      if(!(expr)) {                                             \
  |  |  ------------------
  |  |  |  Branch (53:10): [True: 0, False: 57.8k]
  |  |  ------------------
  |  |   54|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */    \
  |  |   55|      0|         Botan::throw_invalid_state(#expr, __func__, __FILE__); \
  |  |   56|      0|      }                                                         \
  |  |   57|  57.8k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (57:12): [Folded, False: 57.8k]
  |  |  ------------------
  ------------------
  340|  57.8k|   return this->mul_by(std::span{other.m_v}, ws);
  341|  57.8k|}
_ZN5Botan14Montgomery_Int6mul_byENSt3__14spanIKmLm18446744073709551615EEERNS1_6vectorImNS_16secure_allocatorImEEEE:
  343|  62.3k|Montgomery_Int& Montgomery_Int::mul_by(std::span<const word> other, secure_vector<word>& ws) {
  344|  62.3k|   const size_t p_size = m_params.p_words();
  345|  62.3k|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size && other.size() == p_size);
  ------------------
  |  |   84|  62.3k|   do {                                                                     \
  |  |   85|  62.3k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|   124k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:12): [True: 62.3k, False: 0]
  |  |  |  Branch (86:12): [True: 62.3k, False: 0]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  62.3k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 62.3k]
  |  |  ------------------
  ------------------
  346|       |
  347|  62.3k|   if(ws.size() < 4 * p_size) {
  ------------------
  |  Branch (347:7): [True: 1.84k, False: 60.5k]
  ------------------
  348|  1.84k|      ws.resize(4 * p_size);
  349|  1.84k|   }
  350|       |
  351|  62.3k|   bigint_monty_mul(
  352|  62.3k|      m_v.data(), m_v.data(), other.data(), m_params.p()._data(), p_size, m_params.p_dash(), ws.data(), ws.size());
  353|       |
  354|  62.3k|   return (*this);
  355|  62.3k|}
_ZN5Botan14Montgomery_Int19square_this_n_timesERNSt3__16vectorImNS_16secure_allocatorImEEEEm:
  357|  77.7k|Montgomery_Int& Montgomery_Int::square_this_n_times(secure_vector<word>& ws, size_t n) {
  358|  77.7k|   const size_t p_size = m_params.p_words();
  359|  77.7k|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size);
  ------------------
  |  |   84|  77.7k|   do {                                                                     \
  |  |   85|  77.7k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  77.7k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 77.7k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  77.7k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 77.7k]
  |  |  ------------------
  ------------------
  360|       |
  361|  77.7k|   if(ws.size() < 4 * p_size) {
  ------------------
  |  Branch (361:7): [True: 2.92k, False: 74.7k]
  ------------------
  362|  2.92k|      ws.resize(4 * p_size);
  363|  2.92k|   }
  364|       |
  365|   347k|   for(size_t i = 0; i != n; ++i) {
  ------------------
  |  Branch (365:22): [True: 270k, False: 77.7k]
  ------------------
  366|   270k|      bigint_monty_sqr(m_v.data(), m_v.data(), m_params.p()._data(), p_size, m_params.p_dash(), ws.data(), ws.size());
  367|   270k|   }
  368|       |
  369|  77.7k|   return (*this);
  370|  77.7k|}
_ZN5Botan14Montgomery_Int9add_mod_pENSt3__14spanIKmLm18446744073709551615EEE:
  372|  3.31k|void Montgomery_Int::add_mod_p(std::span<const word> other) {
  373|  3.31k|   const size_t p_size = m_params.p_words();
  374|  3.31k|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size && other.size() == p_size);
  ------------------
  |  |   84|  3.31k|   do {                                                                     \
  |  |   85|  3.31k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  6.63k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:12): [True: 3.31k, False: 0]
  |  |  |  Branch (86:12): [True: 3.31k, False: 0]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  3.31k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 3.31k]
  |  |  ------------------
  ------------------
  375|       |
  376|  3.31k|   const auto do_add = [&](std::span<word> t) {
  377|  3.31k|      const word carry = bigint_add3(t.data(), m_v.data(), p_size, other.data(), p_size);
  378|  3.31k|      bigint_monty_maybe_sub(p_size, m_v.data(), carry, t.data(), m_params.p()._data());
  379|  3.31k|   };
  380|       |
  381|  3.31k|   if(p_size <= MontgomeryUseStackLimit) {
  ------------------
  |  Branch (381:7): [True: 3.31k, False: 0]
  ------------------
  382|  3.31k|      std::array<word, MontgomeryUseStackLimit> t{};
  383|  3.31k|      do_add(std::span{t}.first(p_size));
  384|  3.31k|   } else {
  385|      0|      secure_vector<word> t(p_size);
  386|      0|      do_add(t);
  387|      0|   }
  388|  3.31k|}
_ZN5Botan14Montgomery_IntpLERKS0_:
  390|    765|Montgomery_Int& Montgomery_Int::operator+=(const Montgomery_Int& other) {
  391|    765|   BOTAN_STATE_CHECK(other.m_params == m_params);
  ------------------
  |  |   51|    765|   do {                                                         \
  |  |   52|    765|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */             \
  |  |   53|    765|      if(!(expr)) {                                             \
  |  |  ------------------
  |  |  |  Branch (53:10): [True: 0, False: 765]
  |  |  ------------------
  |  |   54|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */    \
  |  |   55|      0|         Botan::throw_invalid_state(#expr, __func__, __FILE__); \
  |  |   56|      0|      }                                                         \
  |  |   57|    765|   } while(0)
  |  |  ------------------
  |  |  |  Branch (57:12): [Folded, False: 765]
  |  |  ------------------
  ------------------
  392|    765|   this->add_mod_p(other.m_v);
  393|    765|   return (*this);
  394|    765|}
_ZN5Botan14Montgomery_Int11mul_by_wordEm:
  408|    510|Montgomery_Int& Montgomery_Int::mul_by_word(word d) {
  409|    510|   BOTAN_ARG_CHECK(d > 0, "Multiplier must be positive");
  ------------------
  |  |   35|    510|   do {                                                          \
  |  |   36|    510|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    510|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 510]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    510|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 510]
  |  |  ------------------
  ------------------
  410|       |
  411|    510|   const size_t p_size = m_params.p_words();
  412|    510|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size);
  ------------------
  |  |   84|    510|   do {                                                                     \
  |  |   85|    510|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    510|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 510]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    510|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 510]
  |  |  ------------------
  ------------------
  413|       |
  414|       |   // Double and add, from the second highest bit of d downwards
  415|    510|   const auto do_mul = [&](std::span<word> x) {
  416|    510|      copy_mem(x.data(), m_v.data(), p_size);
  417|       |
  418|    510|      for(size_t i = high_bit(d) - 1; i > 0; --i) {
  419|    510|         this->add_mod_p(m_v);
  420|    510|         if(((d >> (i - 1)) & 1) == 1) {
  421|    510|            this->add_mod_p(x);
  422|    510|         }
  423|    510|      }
  424|    510|   };
  425|       |
  426|    510|   if(p_size <= MontgomeryUseStackLimit) {
  ------------------
  |  Branch (426:7): [True: 510, False: 0]
  ------------------
  427|    510|      std::array<word, MontgomeryUseStackLimit> x{};
  428|    510|      do_mul(std::span{x}.first(p_size));
  429|    510|   } else {
  430|      0|      secure_vector<word> x(p_size);
  431|      0|      do_mul(x);
  432|      0|   }
  433|       |
  434|    510|   return (*this);
  435|    510|}
_ZN5Botan14Montgomery_Int4div2Ev:
  437|    765|Montgomery_Int& Montgomery_Int::div2() {
  438|    765|   const size_t p_size = m_params.p_words();
  439|    765|   BOTAN_ASSERT_NOMSG(m_v.size() == p_size);
  ------------------
  |  |   84|    765|   do {                                                                     \
  |  |   85|    765|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    765|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 765]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    765|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 765]
  |  |  ------------------
  ------------------
  440|    765|   constexpr size_t WB = WordInfo<word>::bits;
  441|       |
  442|       |   // If odd, add p (also odd) to make the value even; the sum is below 2p
  443|    765|   const word carry = bigint_cnd_add(m_v[0] & 1, m_v.data(), m_params.p()._data(), p_size);
  444|       |
  445|  3.06k|   for(size_t i = 0; i != p_size - 1; ++i) {
  ------------------
  |  Branch (445:22): [True: 2.29k, False: 765]
  ------------------
  446|  2.29k|      m_v[i] = (m_v[i] >> 1) | (m_v[i + 1] << (WB - 1));
  447|  2.29k|   }
  448|    765|   m_v[p_size - 1] = (m_v[p_size - 1] >> 1) | (carry << (WB - 1));
  449|       |
  450|    765|   return (*this);
  451|    765|}
_ZN5Botan14Montgomery_Int14ct_cond_assignEbRKS0_:
  453|    510|void Montgomery_Int::ct_cond_assign(bool predicate, const Montgomery_Int& other) {
  454|    510|   BOTAN_STATE_CHECK(other.m_params == m_params);
  ------------------
  |  |   51|    510|   do {                                                         \
  |  |   52|    510|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */             \
  |  |   53|    510|      if(!(expr)) {                                             \
  |  |  ------------------
  |  |  |  Branch (53:10): [True: 0, False: 510]
  |  |  ------------------
  |  |   54|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */    \
  |  |   55|      0|         Botan::throw_invalid_state(#expr, __func__, __FILE__); \
  |  |   56|      0|      }                                                         \
  |  |   57|    510|   } while(0)
  |  |  ------------------
  |  |  |  Branch (57:12): [Folded, False: 510]
  |  |  ------------------
  ------------------
  455|    510|   BOTAN_ASSERT_NOMSG(m_v.size() == other.m_v.size());
  ------------------
  |  |   84|    510|   do {                                                                     \
  |  |   85|    510|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    510|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 510]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    510|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 510]
  |  |  ------------------
  ------------------
  456|    510|   CT::conditional_assign_mem(static_cast<word>(predicate), m_v.data(), other.m_v.data(), m_v.size());
  457|    510|}
_ZNK5Botan14Montgomery_Int7is_zeroEv:
  459|      1|bool Montgomery_Int::is_zero() const {
  460|      1|   return CT::all_zeros(m_v.data(), m_v.size()).as_bool();
  461|      1|}
_ZNK5Botan14Montgomery_Int6squareERNSt3__16vectorImNS_16secure_allocatorImEEEE:
  463|  12.9k|Montgomery_Int Montgomery_Int::square(secure_vector<word>& ws) const {
  464|  12.9k|   auto z = (*this);
  465|  12.9k|   z.square_this_n_times(ws, 1);
  466|  12.9k|   return z;
  467|  12.9k|}
monty.cpp:_ZZN5Botan14Montgomery_Int9add_mod_pENSt3__14spanIKmLm18446744073709551615EEEENK3$_0clENS2_ImLm18446744073709551615EEE:
  376|  3.31k|   const auto do_add = [&](std::span<word> t) {
  377|  3.31k|      const word carry = bigint_add3(t.data(), m_v.data(), p_size, other.data(), p_size);
  378|  3.31k|      bigint_monty_maybe_sub(p_size, m_v.data(), carry, t.data(), m_params.p()._data());
  379|  3.31k|   };
monty.cpp:_ZZN5Botan14Montgomery_Int11mul_by_wordEmENK3$_0clENSt3__14spanImLm18446744073709551615EEE:
  415|    510|   const auto do_mul = [&](std::span<word> x) {
  416|    510|      copy_mem(x.data(), m_v.data(), p_size);
  417|       |
  418|  2.04k|      for(size_t i = high_bit(d) - 1; i > 0; --i) {
  ------------------
  |  Branch (418:39): [True: 1.53k, False: 510]
  ------------------
  419|  1.53k|         this->add_mod_p(m_v);
  420|  1.53k|         if(((d >> (i - 1)) & 1) == 1) {
  ------------------
  |  Branch (420:13): [True: 1.02k, False: 510]
  ------------------
  421|  1.02k|            this->add_mod_p(x);
  422|  1.02k|         }
  423|  1.53k|      }
  424|    510|   };

_ZN5Botan16monty_precomputeERKNS_14Montgomery_IntEmb:
  145|  1.84k|                                                                        bool const_time) {
  146|  1.84k|   if(window_bits == 0) {
  ------------------
  |  Branch (146:7): [True: 0, False: 1.84k]
  ------------------
  147|      0|      window_bits = 4;
  148|      0|   }
  149|       |
  150|  1.84k|   if(window_bits < 1 || window_bits > 12) {  // really even 8 is too large ...
  ------------------
  |  Branch (150:7): [True: 0, False: 1.84k]
  |  Branch (150:26): [True: 0, False: 1.84k]
  ------------------
  151|      0|      throw Invalid_Argument("Invalid window bits for Montgomery exponentiation");
  152|      0|   }
  153|       |
  154|  1.84k|#if defined(BOTAN_HAS_MONTY_EXP_AVX512)
  155|  1.84k|   if(CPUID::has(CPUID::Feature::AVX512)) {
  ------------------
  |  Branch (155:7): [True: 0, False: 1.84k]
  ------------------
  156|      0|      if(auto state = make_monty_exp_avx512(g, window_bits, const_time)) {
  ------------------
  |  Branch (156:15): [True: 0, False: 0]
  ------------------
  157|      0|         return state;
  158|      0|      }
  159|      0|   }
  160|  1.84k|#endif
  161|       |
  162|  1.84k|   return std::make_shared<const Montgomery_Exponentiation_Generic>(g, window_bits, const_time);
  163|  1.84k|}
_ZN5Botan16monty_precomputeERKNS_17Montgomery_ParamsERKNS_6BigIntEmb:
  168|  1.84k|                                                                        bool const_time) {
  169|  1.84k|   BOTAN_ARG_CHECK(g.signum() >= 0 && g < params.p(), "Montgomery exponentiation base integer out of range");
  ------------------
  |  |   35|  1.84k|   do {                                                          \
  |  |   36|  1.84k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  3.69k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 1.84k, False: 0]
  |  |  |  Branch (37:12): [True: 1.84k, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  1.84k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1.84k]
  |  |  ------------------
  ------------------
  170|  1.84k|   const Montgomery_Int monty_g(params, g);
  171|  1.84k|   return monty_precompute(monty_g, window_bits, const_time);
  172|  1.84k|}
_ZN5Botan13monty_executeERKNS_31Montgomery_Exponentiation_StateERKNS_6BigIntEm:
  176|     43|                             size_t max_k_bits) {
  177|     43|   return precomputed_state.exponentiation(k, max_k_bits);
  178|     43|}
_ZN5Botan21monty_execute_vartimeERKNS_31Montgomery_Exponentiation_StateERKNS_6BigIntE:
  180|  1.80k|Montgomery_Int monty_execute_vartime(const Montgomery_Exponentiation_State& precomputed_state, const BigInt& k) {
  181|  1.80k|   return precomputed_state.exponentiation_vartime(k);
  182|  1.80k|}
monty_exp.cpp:_ZN5Botan12_GLOBAL__N_133Montgomery_Exponentiation_GenericC2ERKNS_14Montgomery_IntEmb:
   43|  1.84k|      m_params(g._params()), m_window_bits(window_bits) {
   44|  1.84k|   const size_t window_size = (static_cast<size_t>(1) << m_window_bits);
   45|       |
   46|  1.84k|   m_g.reserve(window_size);
   47|       |
   48|  1.84k|   m_g.push_back(Montgomery_Int::one(m_params));
   49|       |
   50|  1.84k|   m_g.push_back(g);
   51|       |
   52|  1.84k|   secure_vector<word> ws(2 * m_params.p_words());
   53|       |
   54|  27.7k|   for(size_t i = 2; i != window_size; ++i) {
  ------------------
  |  Branch (54:22): [True: 25.8k, False: 1.84k]
  ------------------
   55|  25.8k|      if(i % 2 == 0) {
  ------------------
  |  Branch (55:10): [True: 12.9k, False: 12.9k]
  ------------------
   56|  12.9k|         m_g.push_back(m_g[i / 2].square(ws));
   57|  12.9k|      } else {
   58|  12.9k|         m_g.push_back(m_g[1].mul(m_g[i - 1], ws));
   59|  12.9k|      }
   60|  25.8k|   }
   61|       |
   62|  1.84k|   if(const_time) {
  ------------------
  |  Branch (62:7): [True: 43, False: 1.80k]
  ------------------
   63|     43|      CT::poison_range(m_g);
   64|     43|   }
   65|  1.84k|}
monty_exp.cpp:_ZNK5Botan12_GLOBAL__N_133Montgomery_Exponentiation_Generic14exponentiationERKNS_6BigIntEm:
   90|     43|Montgomery_Int Montgomery_Exponentiation_Generic::exponentiation(const BigInt& scalar, size_t max_k_bits) const {
   91|     43|   BOTAN_ARG_CHECK(scalar.signum() >= 0, "Invalid scalar for Montgomery exponentiation");
  ------------------
  |  |   35|     43|   do {                                                          \
  |  |   36|     43|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|     43|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 43]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|     43|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 43]
  |  |  ------------------
  ------------------
   92|     43|   BOTAN_DEBUG_ASSERT(scalar.bits() <= max_k_bits);
  ------------------
  |  |  137|     43|      do { /* NOLINT(*-avoid-do-while) */ \
  |  |  138|     43|      } while(0)
  |  |  ------------------
  |  |  |  Branch (138:15): [Folded, False: 43]
  |  |  ------------------
  ------------------
   93|       |   // TODO add a const-time implementation of above assert and use it in release builds
   94|       |
   95|     43|   const size_t exp_nibbles = (max_k_bits + m_window_bits - 1) / m_window_bits;
   96|       |
   97|     43|   if(exp_nibbles == 0) {
  ------------------
  |  Branch (97:7): [True: 0, False: 43]
  ------------------
   98|      0|      return Montgomery_Int::one(m_params);
   99|      0|   }
  100|       |
  101|     43|   secure_vector<word> e_bits(m_params.p_words());
  102|     43|   secure_vector<word> ws(2 * m_params.p_words());
  103|       |
  104|     43|   const_time_lookup(e_bits, m_g, scalar.get_substring(m_window_bits * (exp_nibbles - 1), m_window_bits));
  105|     43|   Montgomery_Int x(m_params, std::span{e_bits});
  106|       |
  107|  2.72k|   for(size_t i = exp_nibbles - 1; i > 0; --i) {
  ------------------
  |  Branch (107:36): [True: 2.67k, False: 43]
  ------------------
  108|  2.67k|      x.square_this_n_times(ws, m_window_bits);
  109|  2.67k|      const_time_lookup(e_bits, m_g, scalar.get_substring(m_window_bits * (i - 1), m_window_bits));
  110|  2.67k|      x.mul_by(e_bits, ws);
  111|  2.67k|   }
  112|       |
  113|     43|   CT::unpoison(x);
  114|     43|   return x;
  115|     43|}
monty_exp.cpp:_ZN5Botan12_GLOBAL__N_117const_time_lookupERNSt3__16vectorImNS_16secure_allocatorImEEEERKNS2_INS_14Montgomery_IntENS1_9allocatorIS7_EEEEm:
   67|  2.72k|void const_time_lookup(secure_vector<word>& output, const std::vector<Montgomery_Int>& g, size_t nibble) {
   68|  2.72k|   BOTAN_ASSERT_NOMSG(g.size() % 2 == 0);  // actually a power of 2
  ------------------
  |  |   84|  2.72k|   do {                                                                     \
  |  |   85|  2.72k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  2.72k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 2.72k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  2.72k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 2.72k]
  |  |  ------------------
  ------------------
   69|       |
   70|  2.72k|   const size_t words = output.size();
   71|       |
   72|  2.72k|   clear_mem(output.data(), output.size());
   73|       |
   74|  24.4k|   for(size_t i = 0; i != g.size(); i += 2) {
  ------------------
  |  Branch (74:22): [True: 21.7k, False: 2.72k]
  ------------------
   75|  21.7k|      const secure_vector<word>& vec_0 = g[i].repr();
   76|  21.7k|      const secure_vector<word>& vec_1 = g[i + 1].repr();
   77|       |
   78|  21.7k|      BOTAN_ASSERT_NOMSG(vec_0.size() >= words && vec_1.size() >= words);
  ------------------
  |  |   84|  21.7k|   do {                                                                     \
  |  |   85|  21.7k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  43.5k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:12): [True: 21.7k, False: 0]
  |  |  |  Branch (86:12): [True: 21.7k, False: 0]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  21.7k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 21.7k]
  |  |  ------------------
  ------------------
   79|       |
   80|  21.7k|      const auto mask_0 = CT::Mask<word>::is_equal(nibble, i);
   81|  21.7k|      const auto mask_1 = CT::Mask<word>::is_equal(nibble, i + 1);
   82|       |
   83|   108k|      for(size_t w = 0; w != words; ++w) {
  ------------------
  |  Branch (83:25): [True: 87.0k, False: 21.7k]
  ------------------
   84|  87.0k|         output[w] |= mask_0.if_set_return(vec_0[w]);
   85|  87.0k|         output[w] |= mask_1.if_set_return(vec_1[w]);
   86|  87.0k|      }
   87|  21.7k|   }
   88|  2.72k|}
monty_exp.cpp:_ZNK5Botan12_GLOBAL__N_133Montgomery_Exponentiation_Generic22exponentiation_vartimeERKNS_6BigIntE:
  117|  1.80k|Montgomery_Int Montgomery_Exponentiation_Generic::exponentiation_vartime(const BigInt& scalar) const {
  118|  1.80k|   const size_t exp_nibbles = (scalar.bits() + m_window_bits - 1) / m_window_bits;
  119|       |
  120|  1.80k|   secure_vector<word> ws(2 * m_params.p_words());
  121|       |
  122|  1.80k|   if(exp_nibbles == 0) {
  ------------------
  |  Branch (122:7): [True: 0, False: 1.80k]
  ------------------
  123|      0|      return Montgomery_Int::one(m_params);
  124|      0|   }
  125|       |
  126|  1.80k|   Montgomery_Int x = m_g[scalar.get_substring(m_window_bits * (exp_nibbles - 1), m_window_bits)];
  127|       |
  128|  63.3k|   for(size_t i = exp_nibbles - 1; i > 0; --i) {
  ------------------
  |  Branch (128:36): [True: 61.5k, False: 1.80k]
  ------------------
  129|  61.5k|      x.square_this_n_times(ws, m_window_bits);
  130|       |
  131|  61.5k|      const uint32_t nibble = scalar.get_substring(m_window_bits * (i - 1), m_window_bits);
  132|  61.5k|      if(nibble > 0) {
  ------------------
  |  Branch (132:10): [True: 57.6k, False: 3.90k]
  ------------------
  133|  57.6k|         x.mul_by(m_g[nibble], ws);
  134|  57.6k|      }
  135|  61.5k|   }
  136|       |
  137|  1.80k|   CT::unpoison(x);
  138|  1.80k|   return x;
  139|  1.80k|}

_ZN5Botan17sqrt_modulo_primeERKNS_6BigIntES2_:
   27|    813|BigInt sqrt_modulo_prime(const BigInt& a, const BigInt& p) {
   28|    813|   BOTAN_ARG_CHECK(p > 1, "invalid prime");
  ------------------
  |  |   35|    813|   do {                                                          \
  |  |   36|    813|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    813|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 813]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    813|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 813]
  |  |  ------------------
  ------------------
   29|    813|   BOTAN_ARG_CHECK(a < p, "value to solve for must be less than p");
  ------------------
  |  |   35|    813|   do {                                                          \
  |  |   36|    813|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    813|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 1, False: 812]
  |  |  ------------------
  |  |   38|      1|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      1|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      1|      }                                                          \
  |  |   41|    813|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 813]
  |  |  ------------------
  ------------------
   30|    813|   BOTAN_ARG_CHECK(a >= 0, "value to solve for must not be negative");
  ------------------
  |  |   35|    813|   do {                                                          \
  |  |   36|    813|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    813|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 813]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    813|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 813]
  |  |  ------------------
  ------------------
   31|       |
   32|       |   // some very easy cases
   33|    813|   if(p == 2 || a <= 1) {
  ------------------
  |  Branch (33:7): [True: 1, False: 812]
  |  Branch (33:17): [True: 2, False: 810]
  ------------------
   34|      2|      return a;
   35|      2|   }
   36|       |
   37|    811|   BOTAN_ARG_CHECK(p.is_odd(), "invalid prime");
  ------------------
  |  |   35|    811|   do {                                                          \
  |  |   36|    811|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    811|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 811]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    811|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 811]
  |  |  ------------------
  ------------------
   38|       |
   39|    811|   if(jacobi(a, p) != 1) {  // not a quadratic residue
  ------------------
  |  Branch (39:7): [True: 281, False: 530]
  ------------------
   40|    281|      return BigInt::from_s32(-1);
   41|    281|   }
   42|       |
   43|    530|   const auto mod_p = Barrett_Reduction::for_public_modulus(p);
   44|    530|   const Montgomery_Params monty_p(p, mod_p);
   45|       |
   46|       |   // If p == 3 (mod 4) there is a simple solution
   47|    530|   if(p % 4 == 3) {
  ------------------
  |  Branch (47:7): [True: 0, False: 530]
  ------------------
   48|      0|      return monty_exp_vartime(monty_p, a, ((p + 1) >> 2)).value();
   49|      0|   }
   50|       |
   51|       |   // Otherwise we have to use Shanks-Tonelli
   52|    530|   size_t s = low_zero_bits(p - 1);
   53|    530|   BigInt q = p >> s;
   54|       |
   55|    530|   q -= 1;
   56|    530|   q >>= 1;
   57|       |
   58|    530|   BigInt r = monty_exp_vartime(monty_p, a, q).value();
   59|    530|   BigInt n = mod_p.multiply(a, mod_p.square(r));
   60|    530|   r = mod_p.multiply(r, a);
   61|       |
   62|    530|   if(n == 1) {
  ------------------
  |  Branch (62:7): [True: 66, False: 464]
  ------------------
   63|     66|      return r;
   64|     66|   }
   65|       |
   66|       |   // find random quadratic nonresidue z
   67|    464|   word z = 2;
   68|    926|   for(;;) {
   69|    926|      if(jacobi(BigInt::from_word(z), p) == -1) {  // found one
  ------------------
  |  Branch (69:10): [True: 463, False: 463]
  ------------------
   70|    463|         break;
   71|    463|      }
   72|       |
   73|    463|      z += 1;  // try next z
   74|       |
   75|       |      /*
   76|       |      * The expected number of tests to find a non-residue modulo a
   77|       |      * prime is 2. If we have not found one after 256 then almost
   78|       |      * certainly we have been given a non-prime p.
   79|       |      */
   80|    463|      if(z >= 256) {
  ------------------
  |  Branch (80:10): [True: 0, False: 463]
  ------------------
   81|      0|         return BigInt::from_s32(-1);
   82|      0|      }
   83|    463|   }
   84|       |
   85|    464|   BigInt c = monty_exp_vartime(monty_p, BigInt::from_word(z), (q << 1) + 1).value();
   86|       |
   87|  1.27k|   while(n > 1) {
  ------------------
  |  Branch (87:10): [True: 812, False: 464]
  ------------------
   88|    812|      q = n;
   89|       |
   90|    812|      size_t i = 0;
   91|  2.45k|      while(q != 1) {
  ------------------
  |  Branch (91:13): [True: 1.64k, False: 812]
  ------------------
   92|  1.64k|         q = mod_p.square(q);
   93|  1.64k|         ++i;
   94|       |
   95|  1.64k|         if(i >= s) {
  ------------------
  |  Branch (95:13): [True: 0, False: 1.64k]
  ------------------
   96|      0|            return BigInt::from_s32(-1);
   97|      0|         }
   98|  1.64k|      }
   99|       |
  100|    812|      BOTAN_ASSERT_NOMSG(s >= (i + 1));  // No underflow!
  ------------------
  |  |   84|    812|   do {                                                                     \
  |  |   85|    812|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    812|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 812]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    812|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 812]
  |  |  ------------------
  ------------------
  101|    812|      c = monty_exp_vartime(monty_p, c, BigInt::power_of_2(s - i - 1)).value();
  102|    812|      r = mod_p.multiply(r, c);
  103|    812|      c = mod_p.square(c);
  104|    812|      n = mod_p.multiply(n, c);
  105|       |
  106|       |      // s decreases as the algorithm proceeds
  107|    812|      BOTAN_ASSERT_NOMSG(s >= i);
  ------------------
  |  |   84|    812|   do {                                                                     \
  |  |   85|    812|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|    812|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 812]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|    812|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 812]
  |  |  ------------------
  ------------------
  108|    812|      s = i;
  109|    812|   }
  110|       |
  111|    464|   return r;
  112|    464|}
_ZN5Botan6jacobiENS_6BigIntES0_:
  119|  1.74k|int32_t jacobi(BigInt a, BigInt n) {
  120|  1.74k|   BOTAN_ARG_CHECK(n.is_odd() && n >= 3, "Argument n must be an odd integer >= 3");
  ------------------
  |  |   35|  1.74k|   do {                                                          \
  |  |   36|  1.74k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|  3.48k|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 1.74k, False: 0]
  |  |  |  Branch (37:12): [True: 1.74k, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|  1.74k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1.74k]
  |  |  ------------------
  ------------------
  121|       |
  122|  1.74k|   if(a < 0 || a >= n) {
  ------------------
  |  Branch (122:7): [True: 2, False: 1.73k]
  |  Branch (122:16): [True: 0, False: 1.73k]
  ------------------
  123|      2|      a %= n;
  124|      2|   }
  125|       |
  126|  1.74k|   if(a == 0) {
  ------------------
  |  Branch (126:7): [True: 0, False: 1.74k]
  ------------------
  127|      0|      return 0;
  128|      0|   }
  129|  1.74k|   if(a == 1) {
  ------------------
  |  Branch (129:7): [True: 0, False: 1.74k]
  ------------------
  130|      0|      return 1;
  131|      0|   }
  132|       |
  133|  1.74k|   int32_t s = 1;
  134|       |
  135|  22.7k|   for(;;) {
  136|  22.7k|      const size_t e = low_zero_bits(a);
  137|  22.7k|      a >>= e;
  138|  22.7k|      const word n_mod_8 = n.word_at(0) % 8;
  139|  22.7k|      const word n_mod_4 = n_mod_8 % 4;
  140|       |
  141|  22.7k|      if(e % 2 == 1 && (n_mod_8 == 3 || n_mod_8 == 5)) {
  ------------------
  |  Branch (141:10): [True: 8.51k, False: 14.2k]
  |  Branch (141:25): [True: 2.37k, False: 6.13k]
  |  Branch (141:41): [True: 1.84k, False: 4.29k]
  ------------------
  142|  4.21k|         s = -s;
  143|  4.21k|      }
  144|       |
  145|  22.7k|      if(n_mod_4 == 3 && a % 4 == 3) {
  ------------------
  |  Branch (145:10): [True: 10.8k, False: 11.8k]
  |  Branch (145:26): [True: 5.01k, False: 5.84k]
  ------------------
  146|  5.01k|         s = -s;
  147|  5.01k|      }
  148|       |
  149|       |      /*
  150|       |      * The HAC presentation of the algorithm uses recursion, which is not
  151|       |      * desirable or necessary.
  152|       |      *
  153|       |      * Instead we loop accumulating the product of the various jacobi()
  154|       |      * subcomputations into s, until we reach algorithm termination, which
  155|       |      * occurs in one of two ways.
  156|       |      *
  157|       |      * If a == 1 then the recursion has completed; we can return the value of s.
  158|       |      *
  159|       |      * Otherwise, after swapping and reducing, check for a == 0 [this value is
  160|       |      * called `n1` in HAC's presentation]. This would imply that jacobi(n1,a1)
  161|       |      * would have the value 0, due to Line 1 in HAC 2.149, in which case the
  162|       |      * entire product is zero, and we can immediately return that result.
  163|       |      */
  164|       |
  165|  22.7k|      if(a == 1) {
  ------------------
  |  Branch (165:10): [True: 1.74k, False: 20.9k]
  ------------------
  166|  1.74k|         return s;
  167|  1.74k|      }
  168|       |
  169|  20.9k|      std::swap(a, n);
  170|       |
  171|  20.9k|      BOTAN_ASSERT_NOMSG(n.is_odd());
  ------------------
  |  |   84|  20.9k|   do {                                                                     \
  |  |   85|  20.9k|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|  20.9k|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 20.9k]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|  20.9k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 20.9k]
  |  |  ------------------
  ------------------
  172|       |
  173|  20.9k|      a %= n;
  174|       |
  175|  20.9k|      if(a == 0) {
  ------------------
  |  Branch (175:10): [True: 0, False: 20.9k]
  ------------------
  176|      0|         return 0;
  177|      0|      }
  178|  20.9k|   }
  179|  1.74k|}
_ZN5Botan13low_zero_bitsERKNS_6BigIntE:
  194|  23.2k|size_t low_zero_bits(const BigInt& n) {
  195|  23.2k|   size_t low_zero = 0;
  196|       |
  197|  23.2k|   auto seen_nonempty_word = CT::Mask<word>::cleared();
  198|       |
  199|   180k|   for(size_t i = 0; i != n.size(); ++i) {
  ------------------
  |  Branch (199:22): [True: 156k, False: 23.2k]
  ------------------
  200|   156k|      const word x = n.word_at(i);
  201|       |
  202|       |      // ctz(0) will return sizeof(word)
  203|   156k|      const size_t tz_x = ctz(x);
  204|       |
  205|       |      // if x > 0 we want to count tz_x in total but not any
  206|       |      // further words, so set the mask after the addition
  207|   156k|      low_zero += seen_nonempty_word.if_not_set_return(tz_x);
  208|       |
  209|   156k|      seen_nonempty_word |= CT::Mask<word>::expand(x);
  210|   156k|   }
  211|       |
  212|       |   // if we saw no words with x > 0 then n == 0 and the value we have
  213|       |   // computed is meaningless. Instead return BigInt::zero() in that case.
  214|  23.2k|   return static_cast<size_t>(seen_nonempty_word.if_set_return(low_zero));
  215|  23.2k|}

_ZN5Botan23is_lucas_probable_primeERKNS_6BigIntERKNS_17Montgomery_ParamsE:
  370|      1|bool is_lucas_probable_prime(const BigInt& n, const Montgomery_Params& monty_n) {
  371|      1|   return lucas_test(n, monty_n, false);
  372|      1|}
_ZN5Botan30is_miller_rabin_probable_primeERKNS_6BigIntERKNS_17Montgomery_ParamsERNS_21RandomNumberGeneratorEm:
  409|     15|                                    size_t test_iterations) {
  410|     15|   return miller_rabin_test(n, monty_n, rng, test_iterations, false);
  411|     15|}
_ZN5Botan28miller_rabin_test_iterationsEmmb:
  434|      1|size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random) {
  435|       |   // Cap prob at 512 bits as _way_ more than enough; a random fault causing
  436|       |   // false accept is much more likely to occur than an actual 2^-512 event is.
  437|       |
  438|      1|   prob = std::min<size_t>(512, prob);
  439|       |
  440|      1|   const size_t base = (prob + 2) / 2;  // worst case 4^-t error rate
  441|       |
  442|       |   /*
  443|       |   * If the candidate prime was maliciously constructed, we can't rely
  444|       |   * on arguments based on p being random.
  445|       |   */
  446|      1|   if(!random) {
  ------------------
  |  Branch (446:7): [True: 0, False: 1]
  ------------------
  447|      0|      return base;
  448|      0|   }
  449|       |
  450|       |   /*
  451|       |   * For randomly chosen numbers we can use the estimates from
  452|       |   * http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
  453|       |   *
  454|       |   * These values are derived from the inequality for p(k,t) given on
  455|       |   * the second page.
  456|       |   */
  457|      1|   if(prob <= 128) {
  ------------------
  |  Branch (457:7): [True: 1, False: 0]
  ------------------
  458|      1|      if(n_bits >= 1536) {
  ------------------
  |  Branch (458:10): [True: 0, False: 1]
  ------------------
  459|      0|         return 4;  // < 2^-133
  460|      0|      }
  461|      1|      if(n_bits >= 1024) {
  ------------------
  |  Branch (461:10): [True: 0, False: 1]
  ------------------
  462|      0|         return 6;  // < 2^-133
  463|      0|      }
  464|      1|      if(n_bits >= 512) {
  ------------------
  |  Branch (464:10): [True: 0, False: 1]
  ------------------
  465|      0|         return 12;  // < 2^-129
  466|      0|      }
  467|      1|      if(n_bits >= 256) {
  ------------------
  |  Branch (467:10): [True: 1, False: 0]
  ------------------
  468|      1|         return 29;  // < 2^-128
  469|      1|      }
  470|      1|   }
  471|       |
  472|       |   /*
  473|       |   If the user desires a smaller error probability than we have
  474|       |   precomputed error estimates for, just fall back to using the worst
  475|       |   case error rate.
  476|       |   */
  477|      0|   return base;
  478|      1|}
primality.cpp:_ZN5Botan12_GLOBAL__N_110lucas_testERKNS_6BigIntERKNS_17Montgomery_ParamsEb:
   31|      1|bool lucas_test(const BigInt& C, const Montgomery_Params& monty_C, bool vartime) {
   32|      1|   BOTAN_ARG_CHECK(C.signum() >= 0, "Argument must be non-negative");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      1|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
   33|       |
   34|      1|   if(C == 2 || C == 3 || C == 5 || C == 7 || C == 11 || C == 13) {
  ------------------
  |  Branch (34:7): [True: 0, False: 1]
  |  Branch (34:17): [True: 0, False: 1]
  |  Branch (34:27): [True: 0, False: 1]
  |  Branch (34:37): [True: 0, False: 1]
  |  Branch (34:47): [True: 0, False: 1]
  |  Branch (34:58): [True: 0, False: 1]
  ------------------
   35|      0|      return true;
   36|      0|   }
   37|       |
   38|      1|   if(C <= 1 || C.is_even()) {
  ------------------
  |  Branch (38:7): [True: 0, False: 1]
  |  Branch (38:17): [True: 0, False: 1]
  ------------------
   39|      0|      return false;
   40|      0|   }
   41|       |
   42|       |   // Check 5, -7, 9, -11, 13, -15, 17, ...
   43|      1|   word D = 5;
   44|      1|   bool D_negative = false;
   45|       |
   46|      5|   for(;;) {
   47|      5|      auto D_bn = BigInt::from_word(D);
   48|      5|      D_bn.cond_flip_sign(D_negative);
   49|       |
   50|      5|      const int32_t j = jacobi(D_bn, C);
   51|      5|      if(j == 0) {
  ------------------
  |  Branch (51:10): [True: 0, False: 5]
  ------------------
   52|      0|         return false;
   53|      0|      }
   54|       |
   55|      5|      if(j == -1) {
  ------------------
  |  Branch (55:10): [True: 1, False: 4]
  ------------------
   56|      1|         break;
   57|      1|      }
   58|       |
   59|      4|      D += 2;
   60|      4|      D_negative = !D_negative;
   61|       |
   62|      4|      if(D == 17 && is_perfect_square(C).signum() != 0) {
  ------------------
  |  Branch (62:10): [True: 0, False: 4]
  |  Branch (62:10): [True: 0, False: 4]
  |  Branch (62:21): [True: 0, False: 0]
  ------------------
   63|      0|         return false;
   64|      0|      }
   65|      4|   }
   66|       |
   67|      1|   const BigInt K = C + 1;
   68|      1|   const size_t K_bits = K.bits() - 1;
   69|       |
   70|      1|   secure_vector<word> ws;
   71|       |
   72|      1|   Montgomery_Int U = Montgomery_Int::one(monty_C);
   73|      1|   Montgomery_Int V = U;
   74|      1|   Montgomery_Int Ut = U;
   75|      1|   Montgomery_Int Vt = U;
   76|      1|   Montgomery_Int U2 = U;
   77|      1|   Montgomery_Int V2 = U;
   78|      1|   Montgomery_Int T = U;
   79|       |
   80|    256|   for(size_t i = 0; i != K_bits; ++i) {
  ------------------
  |  Branch (80:22): [True: 255, False: 1]
  ------------------
   81|    255|      const bool k_bit = K.get_bit(K_bits - 1 - i);
   82|       |
   83|       |      // U_temp = U V
   84|    255|      Ut = U;
   85|    255|      Ut.mul_by(V, ws);
   86|       |
   87|       |      // V_temp = (V^2 + D U^2) / 2
   88|    255|      T = U;
   89|    255|      T.square_this_n_times(ws, 1);
   90|    255|      T.mul_by_word(D);
   91|    255|      Vt = V;
   92|    255|      Vt.square_this_n_times(ws, 1);
   93|    255|      if(D_negative) {
  ------------------
  |  Branch (93:10): [True: 0, False: 255]
  ------------------
   94|      0|         Vt -= T;
   95|    255|      } else {
   96|    255|         Vt += T;
   97|    255|      }
   98|    255|      Vt.div2();
   99|       |
  100|    255|      if(!vartime || k_bit) {
  ------------------
  |  Branch (100:10): [True: 255, False: 0]
  |  Branch (100:22): [True: 0, False: 0]
  ------------------
  101|       |         // U_i = (U_temp + V_temp) / 2
  102|    255|         U2 = Ut;
  103|    255|         U2 += Vt;
  104|    255|         U2.div2();
  105|       |
  106|       |         // V_i = (V_temp + D U_temp) / 2
  107|    255|         T = Ut;
  108|    255|         T.mul_by_word(D);
  109|    255|         V2 = Vt;
  110|    255|         if(D_negative) {
  ------------------
  |  Branch (110:13): [True: 0, False: 255]
  ------------------
  111|      0|            V2 -= T;
  112|    255|         } else {
  113|    255|            V2 += T;
  114|    255|         }
  115|    255|         V2.div2();
  116|    255|      }
  117|       |
  118|    255|      if(vartime) {
  ------------------
  |  Branch (118:10): [True: 0, False: 255]
  ------------------
  119|      0|         if(k_bit) {
  ------------------
  |  Branch (119:13): [True: 0, False: 0]
  ------------------
  120|      0|            U = U2;
  121|      0|            V = V2;
  122|      0|         } else {
  123|      0|            U = Ut;
  124|      0|            V = Vt;
  125|      0|         }
  126|    255|      } else {
  127|    255|         U = Ut;
  128|    255|         V = Vt;
  129|    255|         U.ct_cond_assign(k_bit, U2);
  130|    255|         V.ct_cond_assign(k_bit, V2);
  131|    255|      }
  132|    255|   }
  133|       |
  134|      1|   return U.is_zero();
  135|      1|}
primality.cpp:_ZN5Botan12_GLOBAL__N_117Miller_Rabin_TestC2ERKNS_6BigIntERKNS_17Montgomery_ParamsEb:
  158|     15|            m_monty_n(monty_n), m_vartime(vartime) {
  159|     15|         BOTAN_ARG_CHECK(n >= 3 && n.is_odd(), "Invalid integer for Miller-Rabin test");
  ------------------
  |  |   35|     15|   do {                                                          \
  |  |   36|     15|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|     30|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 15, False: 0]
  |  |  |  Branch (37:12): [True: 15, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|     15|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 15]
  |  |  ------------------
  ------------------
  160|       |
  161|     15|         const size_t N = m_monty_n.p_words();
  162|       |
  163|     15|         const BigInt n_minus_1 = n - 1;
  164|       |         /*
  165|       |         * This unpoison is not ideal but realistically there is no way to
  166|       |         * hide the number of loop iterations (below). The main user of
  167|       |         * secret primes is RSA and we always generate RSA primes such that
  168|       |         * p == 3 (mod 4), which means s is always 1.
  169|       |         */
  170|     15|         m_s = CT::driveby_unpoison(low_zero_bits(n_minus_1));
  171|     15|         m_d = n_minus_1 >> m_s;
  172|     15|         m_d_bits = m_d.bits();
  173|       |
  174|       |         // 1 and -1 in Montgomery form
  175|     15|         m_one.assign(m_monty_n.R1()._as_span().first(N).begin(), m_monty_n.R1()._as_span().first(N).end());
  176|     15|         m_minus_one.resize(N);
  177|     15|         bigint_sub3(m_minus_one.data(), n._data(), N, m_one.data(), N);
  178|     15|      }
primality.cpp:_ZNK5Botan12_GLOBAL__N_117Miller_Rabin_Test6passesERKNS_6BigIntE:
  183|     43|      bool passes(const BigInt& a) const {
  184|     43|         Montgomery_Int y = [&]() {
  185|     43|            if(m_vartime) {
  186|     43|               const auto powm_a = monty_precompute(m_monty_n, a, vartime_window_bits(m_d_bits), false);
  187|     43|               return monty_execute_vartime(*powm_a, m_d);
  188|     43|            } else {
  189|     43|               const auto powm_a = monty_precompute(m_monty_n, a, 4, true);
  190|     43|               return monty_execute(*powm_a, m_d, m_d_bits);
  191|     43|            }
  192|     43|         }();
  193|       |
  194|     43|         if(is_one(y) || is_minus_one(y)) {
  ------------------
  |  Branch (194:13): [True: 3, False: 40]
  |  Branch (194:26): [True: 0, False: 40]
  ------------------
  195|      3|            return true;
  196|      3|         }
  197|       |
  198|     40|         secure_vector<word> ws(2 * m_monty_n.p_words());
  199|       |
  200|    103|         for(size_t i = 1; i != m_s; ++i) {
  ------------------
  |  Branch (200:28): [True: 89, False: 14]
  ------------------
  201|     89|            y.square_this_n_times(ws, 1);
  202|       |
  203|     89|            if(is_one(y)) {  // found a non-trivial square root
  ------------------
  |  Branch (203:16): [True: 0, False: 89]
  ------------------
  204|      0|               return false;
  205|      0|            }
  206|       |
  207|       |            /*
  208|       |            -1 is the trivial square root of unity, so ``a`` is not a
  209|       |            witness for this number - give up
  210|       |            */
  211|     89|            if(is_minus_one(y)) {
  ------------------
  |  Branch (211:16): [True: 26, False: 63]
  ------------------
  212|     26|               return true;
  213|     26|            }
  214|     89|         }
  215|       |
  216|     14|         return false;
  217|     40|      }
primality.cpp:_ZZNK5Botan12_GLOBAL__N_117Miller_Rabin_Test6passesERKNS_6BigIntEENKUlvE_clEv:
  184|     43|         Montgomery_Int y = [&]() {
  185|     43|            if(m_vartime) {
  ------------------
  |  Branch (185:16): [True: 0, False: 43]
  ------------------
  186|      0|               const auto powm_a = monty_precompute(m_monty_n, a, vartime_window_bits(m_d_bits), false);
  187|      0|               return monty_execute_vartime(*powm_a, m_d);
  188|     43|            } else {
  189|     43|               const auto powm_a = monty_precompute(m_monty_n, a, 4, true);
  190|     43|               return monty_execute(*powm_a, m_d, m_d_bits);
  191|     43|            }
  192|     43|         }();
primality.cpp:_ZNK5Botan12_GLOBAL__N_117Miller_Rabin_Test6is_oneERKNS_14Montgomery_IntE:
  220|    132|      bool is_one(const Montgomery_Int& y) const {
  221|    132|         return CT::is_equal(y.repr().data(), m_one.data(), m_one.size()).as_bool();
  222|    132|      }
primality.cpp:_ZNK5Botan12_GLOBAL__N_117Miller_Rabin_Test12is_minus_oneERKNS_14Montgomery_IntE:
  224|    129|      bool is_minus_one(const Montgomery_Int& y) const {
  225|    129|         return CT::is_equal(y.repr().data(), m_minus_one.data(), m_minus_one.size()).as_bool();
  226|    129|      }
primality.cpp:_ZN5Botan12_GLOBAL__N_117miller_rabin_testERKNS_6BigIntERKNS_17Montgomery_ParamsERNS_21RandomNumberGeneratorEmb:
  241|     15|                       bool vartime) {
  242|     15|   if(n < 3 || n.is_even()) {
  ------------------
  |  Branch (242:7): [True: 0, False: 15]
  |  Branch (242:16): [True: 0, False: 15]
  ------------------
  243|      0|      return false;
  244|      0|   }
  245|       |
  246|     15|   const Miller_Rabin_Test mr(n, monty_n, vartime);
  247|       |
  248|     44|   for(size_t i = 0; i != test_iterations; ++i) {
  ------------------
  |  Branch (248:22): [True: 43, False: 1]
  ------------------
  249|     43|      const BigInt a = BigInt::random_integer(rng, BigInt::from_word(2), n);
  250|       |
  251|     43|      if(!mr.passes(a)) {
  ------------------
  |  Branch (251:10): [True: 14, False: 29]
  ------------------
  252|     14|         return false;
  253|     14|      }
  254|     43|   }
  255|       |
  256|       |   // Failed to find a counterexample
  257|      1|   return true;
  258|     15|}

_ZN5Botan16mod_small_primesERKNS_6BigIntEm:
  458|      1|std::vector<word> mod_small_primes(const BigInt& n, size_t num_primes) {
  459|      1|   BOTAN_ARG_CHECK(num_primes > 0 && num_primes <= PRIME_TABLE_SIZE, "Invalid num_primes");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      2|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 1, False: 0]
  |  |  |  Branch (37:12): [True: 1, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
  460|      1|   BOTAN_ARG_CHECK(n.signum() >= 0, "The argument n must be non-negative");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      1|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 1]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
  461|       |
  462|      1|   std::vector<word> residues(num_primes);
  463|       |
  464|      1|   const size_t n_words = n.sig_words();
  465|       |
  466|      1|   size_t i = 0;
  467|     40|   for(const auto& group : SMALL_PRIME_GROUPS) {
  ------------------
  |  Branch (467:26): [True: 40, False: 0]
  ------------------
  468|     40|      if(i >= num_primes) {
  ------------------
  |  Branch (468:10): [True: 1, False: 39]
  ------------------
  469|      1|         break;
  470|      1|      }
  471|       |
  472|     39|      const auto div_product = divide_precomp<word>::setup_vartime(group.first);
  473|     39|      const size_t group_end = std::min<size_t>(i + group.second, num_primes);
  474|       |
  475|       |      // First compute n modulo the group product
  476|     39|      word n_mod_product = 0;
  477|    195|      for(size_t w = n_words; w > 0; --w) {
  ------------------
  |  Branch (477:31): [True: 156, False: 39]
  ------------------
  478|    156|         n_mod_product = div_product.mod_2to1(n_mod_product, n._data()[w - 1]);
  479|    156|      }
  480|       |
  481|       |      // Then extract the individual remainders using word arithmetic
  482|    295|      while(i != group_end) {
  ------------------
  |  Branch (482:13): [True: 256, False: 39]
  ------------------
  483|    256|         const auto div_p = divide_precomp<word>::setup_vartime(PRIMES[i]);
  484|    256|         residues[i] = div_p.mod_2to1(0, n_mod_product);
  485|    256|         ++i;
  486|    256|      }
  487|     39|   }
  488|       |
  489|      1|   return residues;
  490|      1|}

_ZN5Botan10ChaCha_RNGC2ENSt3__14spanIKhLm18446744073709551615EEE:
   20|      1|ChaCha_RNG::ChaCha_RNG(std::span<const uint8_t> seed) {
   21|      1|   m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)");
   22|      1|   m_chacha = StreamCipher::create_or_throw("ChaCha(20)");
   23|      1|   clear();
   24|      1|   add_entropy(seed);
   25|      1|}
_ZN5Botan10ChaCha_RNG11clear_stateEv:
   50|      1|void ChaCha_RNG::clear_state() {
   51|      1|   m_hmac->set_key(std::vector<uint8_t>(m_hmac->output_length(), 0x00));
   52|      1|   m_chacha->set_key(m_hmac->final());
   53|      1|}
_ZN5Botan10ChaCha_RNG15generate_outputENSt3__14spanIhLm18446744073709551615EEENS2_IKhLm18446744073709551615EEE:
   55|     53|void ChaCha_RNG::generate_output(std::span<uint8_t> output, std::span<const uint8_t> input) {
   56|     53|   BOTAN_ASSERT_NOMSG(!output.empty());
  ------------------
  |  |   84|     53|   do {                                                                     \
  |  |   85|     53|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|     53|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 53]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|     53|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 53]
  |  |  ------------------
  ------------------
   57|       |
   58|     53|   if(!input.empty()) {
  ------------------
  |  Branch (58:7): [True: 0, False: 53]
  ------------------
   59|      0|      update(input);
   60|      0|   }
   61|       |
   62|     53|   m_chacha->write_keystream(output);
   63|     53|}
_ZN5Botan10ChaCha_RNG6updateENSt3__14spanIKhLm18446744073709551615EEE:
   65|      1|void ChaCha_RNG::update(std::span<const uint8_t> input) {
   66|      1|   m_hmac->update(input);
   67|      1|   m_chacha->set_key(m_hmac->final());
   68|      1|   const auto mac_key = m_chacha->keystream_bytes(m_hmac->output_length());
   69|      1|   m_hmac->set_key(mac_key);
   70|      1|}
_ZNK5Botan10ChaCha_RNG14security_levelEv:
   72|      1|size_t ChaCha_RNG::security_level() const {
   73|      1|   return 256;
   74|      1|}

_ZN5Botan12Stateful_RNGC2Ev:
   35|      1|Stateful_RNG::Stateful_RNG() : m_reseed_interval(0), m_fork_detector(std::make_unique<OS::Fork_Detector>()) {}
_ZN5Botan12Stateful_RNGD2Ev:
   37|      1|Stateful_RNG::~Stateful_RNG() = default;
_ZN5Botan12Stateful_RNG5clearEv:
   39|      1|void Stateful_RNG::clear() {
   40|      1|   const lock_guard_type<recursive_mutex_type> lock(m_mutex);
   41|      1|   m_reseed_counter = 0;
   42|       |   // The cleared state has nothing left to inherit from a parent process
   43|      1|   m_fork_detector->rebaseline();
   44|      1|   clear_state();
   45|      1|}
_ZNK5Botan12Stateful_RNG9is_seededEv:
   52|     53|bool Stateful_RNG::is_seeded() const {
   53|     53|   const lock_guard_type<recursive_mutex_type> lock(m_mutex);
   54|     53|   return m_reseed_counter > 0;
   55|     53|}
_ZN5Botan12Stateful_RNG23generate_batched_outputENSt3__14spanIhLm18446744073709551615EEENS2_IKhLm18446744073709551615EEE:
   64|     53|void Stateful_RNG::generate_batched_output(std::span<uint8_t> output, std::span<const uint8_t> input) {
   65|     53|   BOTAN_ASSERT_NOMSG(!output.empty());
  ------------------
  |  |   84|     53|   do {                                                                     \
  |  |   85|     53|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|     53|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 53]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|     53|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 53]
  |  |  ------------------
  ------------------
   66|       |
   67|     53|   const size_t max_per_request = max_number_of_bytes_per_request();
   68|       |
   69|     53|   if(max_per_request == 0) {
  ------------------
  |  Branch (69:7): [True: 53, False: 0]
  ------------------
   70|       |      // no limit
   71|     53|      reseed_check();
   72|     53|      this->generate_output(output, input);
   73|     53|   } else {
   74|      0|      while(!output.empty()) {
  ------------------
  |  Branch (74:13): [True: 0, False: 0]
  ------------------
   75|      0|         const size_t this_req = std::min(max_per_request, output.size());
   76|       |
   77|      0|         reseed_check();
   78|      0|         this->generate_output(output.subspan(0, this_req), input);
   79|       |
   80|       |         // only include the input for the first iteration
   81|      0|         input = {};
   82|       |
   83|      0|         output = output.subspan(this_req);
   84|      0|      }
   85|      0|   }
   86|     53|}
_ZN5Botan12Stateful_RNG20accept_seed_materialENSt3__14spanIKhLm18446744073709551615EEE:
   88|      1|void Stateful_RNG::accept_seed_material(std::span<const uint8_t> input) {
   89|      1|   const lock_guard_type<recursive_mutex_type> lock(m_mutex);
   90|       |
   91|      1|   this->update(input);
   92|       |
   93|       |   // The contract of add_entropy is that the caller asserts full entropy
   94|      1|   if(8 * input.size() >= security_level()) {
  ------------------
  |  Branch (94:7): [True: 1, False: 0]
  ------------------
   95|      1|      const bool can_reseed = (m_underlying_rng != nullptr || m_entropy_sources != nullptr);
  ------------------
  |  Branch (95:32): [True: 0, False: 1]
  |  Branch (95:63): [True: 0, False: 1]
  ------------------
   96|       |
   97|      1|      if(can_reseed && fork_detected()) {
  ------------------
  |  Branch (97:10): [True: 0, False: 1]
  |  Branch (97:24): [True: 0, False: 0]
  ------------------
   98|       |         // The input may be identical in parent and child, so leave the
   99|       |         // fork pending for reseed_check to handle
  100|      0|         m_reseed_counter = 1;
  101|      1|      } else {
  102|      1|         reset_reseed_counter();
  103|      1|      }
  104|      1|   }
  105|      1|}
_ZN5Botan12Stateful_RNG21fill_bytes_with_inputENSt3__14spanIhLm18446744073709551615EEENS2_IKhLm18446744073709551615EEE:
  107|     53|void Stateful_RNG::fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) {
  108|     53|   const lock_guard_type<recursive_mutex_type> lock(m_mutex);
  109|       |
  110|     53|   if(output.empty()) {
  ------------------
  |  Branch (110:7): [True: 0, False: 53]
  ------------------
  111|       |      // Additional input without output is mixed in but never credited
  112|      0|      this->update(input);
  113|     53|   } else {
  114|     53|      generate_batched_output(output, input);
  115|     53|   }
  116|     53|}
_ZN5Botan12Stateful_RNG20reset_reseed_counterEv:
  149|      1|void Stateful_RNG::reset_reseed_counter() {
  150|       |   // Lock is held whenever this function is called
  151|      1|   m_fork_detector->rebaseline();
  152|      1|   m_reseed_counter = 1;
  153|      1|}
_ZNK5Botan12Stateful_RNG13fork_detectedEv:
  155|     53|bool Stateful_RNG::fork_detected() const {
  156|       |   // Lock is held whenever this function is called
  157|     53|   return m_fork_detector->fork_detected();
  158|     53|}
_ZN5Botan12Stateful_RNG12reseed_checkEv:
  160|     53|void Stateful_RNG::reseed_check() {
  161|       |   // Lock is held whenever this function is called
  162|       |
  163|     53|   const bool fork_detected = this->fork_detected();
  164|       |
  165|     53|   if(is_seeded() == false || fork_detected || (m_reseed_interval > 0 && m_reseed_counter >= m_reseed_interval)) {
  ------------------
  |  Branch (165:7): [True: 0, False: 53]
  |  Branch (165:31): [True: 0, False: 53]
  |  Branch (165:49): [True: 0, False: 53]
  |  Branch (165:74): [True: 0, False: 0]
  ------------------
  166|       |      // The fork baselines are only updated by a successful reseed
  167|      0|      m_reseed_counter = 0;
  168|       |
  169|      0|      if(m_underlying_rng != nullptr) {
  ------------------
  |  Branch (169:10): [True: 0, False: 0]
  ------------------
  170|      0|         reseed_from_rng(*m_underlying_rng, security_level());
  171|      0|      }
  172|       |
  173|      0|      if(m_entropy_sources != nullptr) {
  ------------------
  |  Branch (173:10): [True: 0, False: 0]
  ------------------
  174|      0|         reseed_from_sources(*m_entropy_sources, security_level());
  175|      0|      }
  176|       |
  177|      0|      if(!is_seeded()) {
  ------------------
  |  Branch (177:10): [True: 0, False: 0]
  ------------------
  178|      0|         if(fork_detected) {
  ------------------
  |  Branch (178:13): [True: 0, False: 0]
  ------------------
  179|      0|            throw Invalid_State("Detected use of fork but cannot reseed DRBG");
  180|      0|         } else {
  181|      0|            throw PRNG_Unseeded(name());
  182|      0|         }
  183|      0|      }
  184|     53|   } else {
  185|     53|      BOTAN_ASSERT(m_reseed_counter != 0, "RNG is seeded");
  ------------------
  |  |   71|     53|   do {                                                                                 \
  |  |   72|     53|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|     53|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 53]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|     53|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 53]
  |  |  ------------------
  ------------------
  186|     53|      m_reseed_counter += 1;
  187|     53|   }
  188|     53|}

_ZN5Botan6ChaChaC2Em:
   92|      1|ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) {
   93|      1|   BOTAN_ARG_CHECK(m_rounds == 8 || m_rounds == 12 || m_rounds == 20, "ChaCha only supports 8, 12 or 20 rounds");
  ------------------
  |  |   35|      1|   do {                                                          \
  |  |   36|      1|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|      4|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:12): [True: 0, False: 1]
  |  |  |  Branch (37:12): [True: 0, False: 1]
  |  |  |  Branch (37:12): [True: 1, False: 0]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|      1|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 1]
  |  |  ------------------
  ------------------
   94|      1|}
_ZN5Botan6ChaCha11parallelismEv:
   96|      2|size_t ChaCha::parallelism() {
   97|      2|#if defined(BOTAN_HAS_CHACHA_AVX512)
   98|      2|   if(CPUID::has(CPUID::Feature::AVX512)) {
  ------------------
  |  Branch (98:7): [True: 0, False: 2]
  ------------------
   99|      0|      return 16;
  100|      0|   }
  101|      2|#endif
  102|       |
  103|      2|#if defined(BOTAN_HAS_CHACHA_SIMD8X32)
  104|      2|   if(CPUID::has(CPUID::Feature::SIMD_8X32)) {
  ------------------
  |  Branch (104:7): [True: 2, False: 0]
  ------------------
  105|      2|      return 8;
  106|      2|   }
  107|      0|#endif
  108|       |
  109|      0|   return 4;
  110|      2|}
_ZN5Botan6ChaCha6chachaEPhmPjm:
  134|      5|void ChaCha::chacha(uint8_t output[], size_t output_blocks, uint32_t state[16], size_t rounds) {
  135|      5|   BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds");
  ------------------
  |  |   71|      5|   do {                                                                                 \
  |  |   72|      5|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|      5|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 5]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|      5|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 5]
  |  |  ------------------
  ------------------
  136|       |
  137|      5|#if defined(BOTAN_HAS_CHACHA_AVX512)
  138|      5|   if(CPUID::has(CPUID::Feature::AVX512)) {
  ------------------
  |  Branch (138:7): [True: 0, False: 5]
  ------------------
  139|      0|      while(output_blocks >= 16) {
  ------------------
  |  Branch (139:13): [True: 0, False: 0]
  ------------------
  140|      0|         ChaCha::chacha_avx512_x16(output, state, rounds);
  141|      0|         output += 16 * 64;
  142|      0|         output_blocks -= 16;
  143|      0|      }
  144|      0|   }
  145|      5|#endif
  146|       |
  147|      5|#if defined(BOTAN_HAS_CHACHA_SIMD8X32)
  148|      5|   if(CPUID::has(CPUID::Feature::SIMD_8X32)) {
  ------------------
  |  Branch (148:7): [True: 5, False: 0]
  ------------------
  149|     10|      while(output_blocks >= 8) {
  ------------------
  |  Branch (149:13): [True: 5, False: 5]
  ------------------
  150|      5|         ChaCha::chacha_simd8x32_x8(output, state, rounds);
  151|      5|         output += 8 * 64;
  152|      5|         output_blocks -= 8;
  153|      5|      }
  154|      5|   }
  155|      5|#endif
  156|       |
  157|      5|#if defined(BOTAN_HAS_CHACHA_SIMD32)
  158|      5|   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
  ------------------
  |  Branch (158:7): [True: 5, False: 0]
  ------------------
  159|      5|      while(output_blocks >= 4) {
  ------------------
  |  Branch (159:13): [True: 0, False: 5]
  ------------------
  160|      0|         ChaCha::chacha_simd32_x4(output, state, rounds);
  161|      0|         output += 4 * 64;
  162|      0|         output_blocks -= 4;
  163|      0|      }
  164|      5|   }
  165|      5|#endif
  166|       |
  167|       |   // TODO interleave rounds
  168|      5|   for(size_t i = 0; i != output_blocks; ++i) {
  ------------------
  |  Branch (168:22): [True: 0, False: 5]
  ------------------
  169|      0|      uint32_t x00 = state[0];
  170|      0|      uint32_t x01 = state[1];
  171|      0|      uint32_t x02 = state[2];
  172|      0|      uint32_t x03 = state[3];
  173|      0|      uint32_t x04 = state[4];
  174|      0|      uint32_t x05 = state[5];
  175|      0|      uint32_t x06 = state[6];
  176|      0|      uint32_t x07 = state[7];
  177|      0|      uint32_t x08 = state[8];
  178|      0|      uint32_t x09 = state[9];
  179|      0|      uint32_t x10 = state[10];
  180|      0|      uint32_t x11 = state[11];
  181|      0|      uint32_t x12 = state[12];
  182|      0|      uint32_t x13 = state[13];
  183|      0|      uint32_t x14 = state[14];
  184|      0|      uint32_t x15 = state[15];
  185|       |
  186|      0|      for(size_t r = 0; r != rounds / 2; ++r) {
  ------------------
  |  Branch (186:25): [True: 0, False: 0]
  ------------------
  187|      0|         chacha_quarter_round(x00, x04, x08, x12);
  188|      0|         chacha_quarter_round(x01, x05, x09, x13);
  189|      0|         chacha_quarter_round(x02, x06, x10, x14);
  190|      0|         chacha_quarter_round(x03, x07, x11, x15);
  191|       |
  192|      0|         chacha_quarter_round(x00, x05, x10, x15);
  193|      0|         chacha_quarter_round(x01, x06, x11, x12);
  194|      0|         chacha_quarter_round(x02, x07, x08, x13);
  195|      0|         chacha_quarter_round(x03, x04, x09, x14);
  196|      0|      }
  197|       |
  198|      0|      x00 += state[0];
  199|      0|      x01 += state[1];
  200|      0|      x02 += state[2];
  201|      0|      x03 += state[3];
  202|      0|      x04 += state[4];
  203|      0|      x05 += state[5];
  204|      0|      x06 += state[6];
  205|      0|      x07 += state[7];
  206|      0|      x08 += state[8];
  207|      0|      x09 += state[9];
  208|      0|      x10 += state[10];
  209|      0|      x11 += state[11];
  210|      0|      x12 += state[12];
  211|      0|      x13 += state[13];
  212|      0|      x14 += state[14];
  213|      0|      x15 += state[15];
  214|       |
  215|      0|      store_le(x00, output + 64 * i + 4 * 0);
  216|      0|      store_le(x01, output + 64 * i + 4 * 1);
  217|      0|      store_le(x02, output + 64 * i + 4 * 2);
  218|      0|      store_le(x03, output + 64 * i + 4 * 3);
  219|      0|      store_le(x04, output + 64 * i + 4 * 4);
  220|      0|      store_le(x05, output + 64 * i + 4 * 5);
  221|      0|      store_le(x06, output + 64 * i + 4 * 6);
  222|      0|      store_le(x07, output + 64 * i + 4 * 7);
  223|      0|      store_le(x08, output + 64 * i + 4 * 8);
  224|      0|      store_le(x09, output + 64 * i + 4 * 9);
  225|      0|      store_le(x10, output + 64 * i + 4 * 10);
  226|      0|      store_le(x11, output + 64 * i + 4 * 11);
  227|      0|      store_le(x12, output + 64 * i + 4 * 12);
  228|      0|      store_le(x13, output + 64 * i + 4 * 13);
  229|      0|      store_le(x14, output + 64 * i + 4 * 14);
  230|      0|      store_le(x15, output + 64 * i + 4 * 15);
  231|       |
  232|      0|      state[12]++;
  233|      0|      if(state[12] == 0) {
  ------------------
  |  Branch (233:10): [True: 0, False: 0]
  ------------------
  234|      0|         state[13] += 1;
  235|      0|      }
  236|      0|   }
  237|      5|}
_ZN5Botan6ChaCha18generate_keystreamEPhm:
  269|     54|void ChaCha::generate_keystream(uint8_t out[], size_t length) {
  270|     54|   assert_key_material_set();
  271|       |
  272|     54|   if(m_iv_length == 12) {
  ------------------
  |  Branch (272:7): [True: 0, False: 54]
  ------------------
  273|      0|      if(length > m_bytes_remaining) {
  ------------------
  |  Branch (273:10): [True: 0, False: 0]
  ------------------
  274|      0|         throw Invalid_State("ChaCha 96-bit nonce keystream exhausted");
  275|      0|      }
  276|      0|      m_bytes_remaining -= length;
  277|      0|   }
  278|       |
  279|     57|   while(length >= m_buffer.size() - m_position) {
  ------------------
  |  Branch (279:10): [True: 3, False: 54]
  ------------------
  280|      3|      const size_t available = m_buffer.size() - m_position;
  281|       |
  282|       |      // TODO: this could write directly to the output buffer
  283|       |      // instead of bouncing it through m_buffer first
  284|      3|      copy_mem(out, &m_buffer[m_position], available);
  285|      3|      chacha(m_buffer.data(), m_buffer.size() / 64, m_state.data(), m_rounds);
  286|       |
  287|      3|      length -= available;
  288|      3|      out += available;
  289|      3|      m_position = 0;
  290|      3|   }
  291|       |
  292|     54|   copy_mem(out, &m_buffer[m_position], length);
  293|       |
  294|     54|   m_position += length;
  295|     54|}
_ZN5Botan6ChaCha16initialize_stateEv:
  297|      2|void ChaCha::initialize_state() {
  298|      2|   static const uint32_t TAU[] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574};
  299|       |
  300|      2|   static const uint32_t SIGMA[] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
  301|       |
  302|      2|   m_state[4] = m_key[0];
  303|      2|   m_state[5] = m_key[1];
  304|      2|   m_state[6] = m_key[2];
  305|      2|   m_state[7] = m_key[3];
  306|       |
  307|      2|   if(m_key.size() == 4) {
  ------------------
  |  Branch (307:7): [True: 0, False: 2]
  ------------------
  308|      0|      m_state[0] = TAU[0];
  309|      0|      m_state[1] = TAU[1];
  310|      0|      m_state[2] = TAU[2];
  311|      0|      m_state[3] = TAU[3];
  312|       |
  313|      0|      m_state[8] = m_key[0];
  314|      0|      m_state[9] = m_key[1];
  315|      0|      m_state[10] = m_key[2];
  316|      0|      m_state[11] = m_key[3];
  317|      2|   } else {
  318|      2|      m_state[0] = SIGMA[0];
  319|      2|      m_state[1] = SIGMA[1];
  320|      2|      m_state[2] = SIGMA[2];
  321|      2|      m_state[3] = SIGMA[3];
  322|       |
  323|      2|      m_state[8] = m_key[4];
  324|      2|      m_state[9] = m_key[5];
  325|      2|      m_state[10] = m_key[6];
  326|      2|      m_state[11] = m_key[7];
  327|      2|   }
  328|       |
  329|      2|   m_state[12] = 0;
  330|      2|   m_state[13] = 0;
  331|      2|   m_state[14] = 0;
  332|      2|   m_state[15] = 0;
  333|       |
  334|      2|   m_position = 0;
  335|      2|}
_ZNK5Botan6ChaCha19has_keying_materialEv:
  337|     56|bool ChaCha::has_keying_material() const {
  338|     56|   return !m_state.empty();
  339|     56|}
_ZN5Botan6ChaCha12key_scheduleENSt3__14spanIKhLm18446744073709551615EEE:
  348|      2|void ChaCha::key_schedule(std::span<const uint8_t> key) {
  349|      2|   m_key.resize(key.size() / 4);
  350|      2|   load_le<uint32_t>(m_key.data(), key.data(), m_key.size());
  351|       |
  352|      2|   m_state.resize(16);
  353|       |
  354|      2|   const size_t chacha_block = 64;
  355|      2|   m_buffer.resize(parallelism() * chacha_block);
  356|       |
  357|      2|   set_iv(nullptr, 0);
  358|      2|}
_ZNK5Botan6ChaCha8key_specEv:
  364|      2|Key_Length_Specification ChaCha::key_spec() const {
  365|      2|   return Key_Length_Specification(16, 32, 16);
  366|      2|}
_ZNK5Botan6ChaCha15valid_iv_lengthEm:
  372|      2|bool ChaCha::valid_iv_length(size_t iv_len) const {
  373|      2|   return (iv_len == 0 || iv_len == 8 || iv_len == 12 || iv_len == 24);
  ------------------
  |  Branch (373:12): [True: 2, False: 0]
  |  Branch (373:27): [True: 0, False: 0]
  |  Branch (373:42): [True: 0, False: 0]
  |  Branch (373:58): [True: 0, False: 0]
  ------------------
  374|      2|}
_ZN5Botan6ChaCha12set_iv_bytesEPKhm:
  376|      2|void ChaCha::set_iv_bytes(const uint8_t iv[], size_t length) {
  377|      2|   assert_key_material_set();
  378|       |
  379|      2|   if(!valid_iv_length(length)) {
  ------------------
  |  Branch (379:7): [True: 0, False: 2]
  ------------------
  380|      0|      throw Invalid_IV_Length(name(), length);
  381|      0|   }
  382|       |
  383|      2|   initialize_state();
  384|       |
  385|      2|   if(length == 0) {
  ------------------
  |  Branch (385:7): [True: 2, False: 0]
  ------------------
  386|       |      // Treat zero length IV same as an all-zero IV
  387|      2|      m_state[14] = 0;
  388|      2|      m_state[15] = 0;
  389|      2|   } else if(length == 8) {
  ------------------
  |  Branch (389:14): [True: 0, False: 0]
  ------------------
  390|      0|      m_state[14] = load_le<uint32_t>(iv, 0);
  391|      0|      m_state[15] = load_le<uint32_t>(iv, 1);
  392|      0|   } else if(length == 12) {
  ------------------
  |  Branch (392:14): [True: 0, False: 0]
  ------------------
  393|      0|      m_state[13] = load_le<uint32_t>(iv, 0);
  394|      0|      m_state[14] = load_le<uint32_t>(iv, 1);
  395|      0|      m_state[15] = load_le<uint32_t>(iv, 2);
  396|      0|   } else if(length == 24) {
  ------------------
  |  Branch (396:14): [True: 0, False: 0]
  ------------------
  397|      0|      m_state[12] = load_le<uint32_t>(iv, 0);
  398|      0|      m_state[13] = load_le<uint32_t>(iv, 1);
  399|      0|      m_state[14] = load_le<uint32_t>(iv, 2);
  400|      0|      m_state[15] = load_le<uint32_t>(iv, 3);
  401|       |
  402|      0|      secure_vector<uint32_t> hc(8);
  403|      0|      hchacha(hc.data(), m_state.data(), m_rounds);
  404|       |
  405|      0|      m_state[4] = hc[0];
  406|      0|      m_state[5] = hc[1];
  407|      0|      m_state[6] = hc[2];
  408|      0|      m_state[7] = hc[3];
  409|      0|      m_state[8] = hc[4];
  410|      0|      m_state[9] = hc[5];
  411|      0|      m_state[10] = hc[6];
  412|      0|      m_state[11] = hc[7];
  413|      0|      m_state[12] = 0;
  414|      0|      m_state[13] = 0;
  415|      0|      m_state[14] = load_le<uint32_t>(iv, 4);
  416|      0|      m_state[15] = load_le<uint32_t>(iv, 5);
  417|      0|   }
  418|       |
  419|      2|   m_iv_length = length;
  420|      2|   m_state13_post_iv = m_state[13];
  421|      2|   if(length == 12) {
  ------------------
  |  Branch (421:7): [True: 0, False: 2]
  ------------------
  422|      0|      m_bytes_remaining = chacha_96bit_nonce_cap;
  423|      0|   }
  424|       |
  425|      2|   chacha(m_buffer.data(), m_buffer.size() / 64, m_state.data(), m_rounds);
  426|      2|   m_position = 0;
  427|      2|}

_ZN5Botan6ChaCha18chacha_simd8x32_x8EPhPjm:
   15|      5|void BOTAN_FN_ISA_SIMD_8X32 ChaCha::chacha_simd8x32_x8(uint8_t output[64 * 8], uint32_t state[16], size_t rounds) {
   16|      5|   SIMD_8x32::reset_registers();
   17|       |
   18|      5|   BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds");
  ------------------
  |  |   71|      5|   do {                                                                                 \
  |  |   72|      5|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                                     \
  |  |   73|      5|      if(!(expr)) {                                                                     \
  |  |  ------------------
  |  |  |  Branch (73:10): [True: 0, False: 5]
  |  |  ------------------
  |  |   74|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                            \
  |  |   75|      0|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   76|      0|      }                                                                                 \
  |  |   77|      5|   } while(0)
  |  |  ------------------
  |  |  |  Branch (77:12): [Folded, False: 5]
  |  |  ------------------
  ------------------
   19|       |
   20|      5|   const SIMD_8x32 CTR_LO = SIMD_8x32::splat(state[12]) + SIMD_8x32(0, 1, 2, 3, 4, 5, 6, 7);
   21|       |   // Carry into the high counter word for lanes whose low word wrapped
   22|      5|   const SIMD_8x32 CTR_HI = SIMD_8x32::splat(state[13]) - CTR_LO.unsigned_lt(SIMD_8x32::splat(state[12]));
   23|       |
   24|      5|   SIMD_8x32 R00 = SIMD_8x32::splat(state[0]);
   25|      5|   SIMD_8x32 R01 = SIMD_8x32::splat(state[1]);
   26|      5|   SIMD_8x32 R02 = SIMD_8x32::splat(state[2]);
   27|      5|   SIMD_8x32 R03 = SIMD_8x32::splat(state[3]);
   28|      5|   SIMD_8x32 R04 = SIMD_8x32::splat(state[4]);
   29|      5|   SIMD_8x32 R05 = SIMD_8x32::splat(state[5]);
   30|      5|   SIMD_8x32 R06 = SIMD_8x32::splat(state[6]);
   31|      5|   SIMD_8x32 R07 = SIMD_8x32::splat(state[7]);
   32|      5|   SIMD_8x32 R08 = SIMD_8x32::splat(state[8]);
   33|      5|   SIMD_8x32 R09 = SIMD_8x32::splat(state[9]);
   34|      5|   SIMD_8x32 R10 = SIMD_8x32::splat(state[10]);
   35|      5|   SIMD_8x32 R11 = SIMD_8x32::splat(state[11]);
   36|      5|   SIMD_8x32 R12 = CTR_LO;
   37|      5|   SIMD_8x32 R13 = CTR_HI;
   38|      5|   SIMD_8x32 R14 = SIMD_8x32::splat(state[14]);
   39|      5|   SIMD_8x32 R15 = SIMD_8x32::splat(state[15]);
   40|       |
   41|     55|   for(size_t r = 0; r != rounds / 2; ++r) {
  ------------------
  |  Branch (41:22): [True: 50, False: 5]
  ------------------
   42|     50|      R00 += R04;
   43|     50|      R01 += R05;
   44|     50|      R02 += R06;
   45|     50|      R03 += R07;
   46|       |
   47|     50|      R12 ^= R00;
   48|     50|      R13 ^= R01;
   49|     50|      R14 ^= R02;
   50|     50|      R15 ^= R03;
   51|       |
   52|     50|      R12 = R12.rotl<16>();
   53|     50|      R13 = R13.rotl<16>();
   54|     50|      R14 = R14.rotl<16>();
   55|     50|      R15 = R15.rotl<16>();
   56|       |
   57|     50|      R08 += R12;
   58|     50|      R09 += R13;
   59|     50|      R10 += R14;
   60|     50|      R11 += R15;
   61|       |
   62|     50|      R04 ^= R08;
   63|     50|      R05 ^= R09;
   64|     50|      R06 ^= R10;
   65|     50|      R07 ^= R11;
   66|       |
   67|     50|      R04 = R04.rotl<12>();
   68|     50|      R05 = R05.rotl<12>();
   69|     50|      R06 = R06.rotl<12>();
   70|     50|      R07 = R07.rotl<12>();
   71|       |
   72|     50|      R00 += R04;
   73|     50|      R01 += R05;
   74|     50|      R02 += R06;
   75|     50|      R03 += R07;
   76|       |
   77|     50|      R12 ^= R00;
   78|     50|      R13 ^= R01;
   79|     50|      R14 ^= R02;
   80|     50|      R15 ^= R03;
   81|       |
   82|     50|      R12 = R12.rotl<8>();
   83|     50|      R13 = R13.rotl<8>();
   84|     50|      R14 = R14.rotl<8>();
   85|     50|      R15 = R15.rotl<8>();
   86|       |
   87|     50|      R08 += R12;
   88|     50|      R09 += R13;
   89|     50|      R10 += R14;
   90|     50|      R11 += R15;
   91|       |
   92|     50|      R04 ^= R08;
   93|     50|      R05 ^= R09;
   94|     50|      R06 ^= R10;
   95|     50|      R07 ^= R11;
   96|       |
   97|     50|      R04 = R04.rotl<7>();
   98|     50|      R05 = R05.rotl<7>();
   99|     50|      R06 = R06.rotl<7>();
  100|     50|      R07 = R07.rotl<7>();
  101|       |
  102|     50|      R00 += R05;
  103|     50|      R01 += R06;
  104|     50|      R02 += R07;
  105|     50|      R03 += R04;
  106|       |
  107|     50|      R15 ^= R00;
  108|     50|      R12 ^= R01;
  109|     50|      R13 ^= R02;
  110|     50|      R14 ^= R03;
  111|       |
  112|     50|      R15 = R15.rotl<16>();
  113|     50|      R12 = R12.rotl<16>();
  114|     50|      R13 = R13.rotl<16>();
  115|     50|      R14 = R14.rotl<16>();
  116|       |
  117|     50|      R10 += R15;
  118|     50|      R11 += R12;
  119|     50|      R08 += R13;
  120|     50|      R09 += R14;
  121|       |
  122|     50|      R05 ^= R10;
  123|     50|      R06 ^= R11;
  124|     50|      R07 ^= R08;
  125|     50|      R04 ^= R09;
  126|       |
  127|     50|      R05 = R05.rotl<12>();
  128|     50|      R06 = R06.rotl<12>();
  129|     50|      R07 = R07.rotl<12>();
  130|     50|      R04 = R04.rotl<12>();
  131|       |
  132|     50|      R00 += R05;
  133|     50|      R01 += R06;
  134|     50|      R02 += R07;
  135|     50|      R03 += R04;
  136|       |
  137|     50|      R15 ^= R00;
  138|     50|      R12 ^= R01;
  139|     50|      R13 ^= R02;
  140|     50|      R14 ^= R03;
  141|       |
  142|     50|      R15 = R15.rotl<8>();
  143|     50|      R12 = R12.rotl<8>();
  144|     50|      R13 = R13.rotl<8>();
  145|     50|      R14 = R14.rotl<8>();
  146|       |
  147|     50|      R10 += R15;
  148|     50|      R11 += R12;
  149|     50|      R08 += R13;
  150|     50|      R09 += R14;
  151|       |
  152|     50|      R05 ^= R10;
  153|     50|      R06 ^= R11;
  154|     50|      R07 ^= R08;
  155|     50|      R04 ^= R09;
  156|       |
  157|     50|      R05 = R05.rotl<7>();
  158|     50|      R06 = R06.rotl<7>();
  159|     50|      R07 = R07.rotl<7>();
  160|     50|      R04 = R04.rotl<7>();
  161|     50|   }
  162|       |
  163|      5|   R00 += SIMD_8x32::splat(state[0]);
  164|      5|   R01 += SIMD_8x32::splat(state[1]);
  165|      5|   R02 += SIMD_8x32::splat(state[2]);
  166|      5|   R03 += SIMD_8x32::splat(state[3]);
  167|      5|   R04 += SIMD_8x32::splat(state[4]);
  168|      5|   R05 += SIMD_8x32::splat(state[5]);
  169|      5|   R06 += SIMD_8x32::splat(state[6]);
  170|      5|   R07 += SIMD_8x32::splat(state[7]);
  171|      5|   R08 += SIMD_8x32::splat(state[8]);
  172|      5|   R09 += SIMD_8x32::splat(state[9]);
  173|      5|   R10 += SIMD_8x32::splat(state[10]);
  174|      5|   R11 += SIMD_8x32::splat(state[11]);
  175|      5|   R12 += CTR_LO;
  176|      5|   R13 += CTR_HI;
  177|      5|   R14 += SIMD_8x32::splat(state[14]);
  178|      5|   R15 += SIMD_8x32::splat(state[15]);
  179|       |
  180|      5|   SIMD_8x32::transpose(R00, R01, R02, R03, R04, R05, R06, R07);
  181|      5|   SIMD_8x32::transpose(R08, R09, R10, R11, R12, R13, R14, R15);
  182|       |
  183|      5|   R00.store_le(output);
  184|      5|   R08.store_le(output + 32 * 1);
  185|      5|   R01.store_le(output + 32 * 2);
  186|      5|   R09.store_le(output + 32 * 3);
  187|      5|   R02.store_le(output + 32 * 4);
  188|      5|   R10.store_le(output + 32 * 5);
  189|      5|   R03.store_le(output + 32 * 6);
  190|      5|   R11.store_le(output + 32 * 7);
  191|      5|   R04.store_le(output + 32 * 8);
  192|      5|   R12.store_le(output + 32 * 9);
  193|      5|   R05.store_le(output + 32 * 10);
  194|      5|   R13.store_le(output + 32 * 11);
  195|      5|   R06.store_le(output + 32 * 12);
  196|      5|   R14.store_le(output + 32 * 13);
  197|      5|   R07.store_le(output + 32 * 14);
  198|      5|   R15.store_le(output + 32 * 15);
  199|       |
  200|      5|   SIMD_8x32::zero_registers();
  201|       |
  202|      5|   state[12] += 8;
  203|      5|   if(state[12] < 8) {
  ------------------
  |  Branch (203:7): [True: 0, False: 5]
  ------------------
  204|      0|      state[13]++;
  205|      0|   }
  206|      5|}

_ZN5Botan12StreamCipher6createENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_:
   41|      1|std::unique_ptr<StreamCipher> StreamCipher::create(std::string_view algo_spec, std::string_view provider) {
   42|      1|#if defined(BOTAN_HAS_SHAKE_CIPHER)
   43|      1|   if(algo_spec == "SHAKE-128" || algo_spec == "SHAKE-128-XOF") {
  ------------------
  |  Branch (43:7): [True: 0, False: 1]
  |  Branch (43:35): [True: 0, False: 1]
  ------------------
   44|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (44:10): [True: 0, False: 0]
  |  Branch (44:30): [True: 0, False: 0]
  ------------------
   45|      0|         return std::make_unique<SHAKE_128_Cipher>();
   46|      0|      }
   47|      0|   }
   48|       |
   49|      1|   if(algo_spec == "SHAKE-256" || algo_spec == "SHAKE-256-XOF") {
  ------------------
  |  Branch (49:7): [True: 0, False: 1]
  |  Branch (49:35): [True: 0, False: 1]
  ------------------
   50|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (50:10): [True: 0, False: 0]
  |  Branch (50:30): [True: 0, False: 0]
  ------------------
   51|      0|         return std::make_unique<SHAKE_256_Cipher>();
   52|      0|      }
   53|      0|   }
   54|      1|#endif
   55|       |
   56|      1|#if defined(BOTAN_HAS_CHACHA)
   57|      1|   if(algo_spec == "ChaCha20") {
  ------------------
  |  Branch (57:7): [True: 0, False: 1]
  ------------------
   58|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (58:10): [True: 0, False: 0]
  |  Branch (58:30): [True: 0, False: 0]
  ------------------
   59|      0|         return std::make_unique<ChaCha>(20);
   60|      0|      }
   61|      0|   }
   62|      1|#endif
   63|       |
   64|      1|#if defined(BOTAN_HAS_SALSA20)
   65|      1|   if(algo_spec == "Salsa20") {
  ------------------
  |  Branch (65:7): [True: 0, False: 1]
  ------------------
   66|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (66:10): [True: 0, False: 0]
  |  Branch (66:30): [True: 0, False: 0]
  ------------------
   67|      0|         return std::make_unique<Salsa20>();
   68|      0|      }
   69|      0|   }
   70|      1|#endif
   71|       |
   72|      1|   const AlgorithmSpec req(algo_spec);
   73|       |
   74|      1|#if defined(BOTAN_HAS_CTR_BE)
   75|      1|   if(auto m = req.match("CTR-BE|CTR({cipher},{ctr_size:int?})")) {
  ------------------
  |  Branch (75:12): [True: 0, False: 1]
  ------------------
   76|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (76:10): [True: 0, False: 0]
  |  Branch (76:30): [True: 0, False: 0]
  ------------------
   77|      0|         if(auto cipher = BlockCipher::create(m->str("cipher"))) {
  ------------------
  |  Branch (77:18): [True: 0, False: 0]
  ------------------
   78|      0|            const size_t ctr_size = m->has("ctr_size") ? m->integer("ctr_size") : cipher->block_size();
  ------------------
  |  Branch (78:37): [True: 0, False: 0]
  ------------------
   79|      0|            return std::make_unique<CTR_BE>(std::move(cipher), ctr_size);
   80|      0|         }
   81|      0|      }
   82|      0|   }
   83|      1|#endif
   84|       |
   85|      1|#if defined(BOTAN_HAS_CHACHA)
   86|      1|   if(auto m = req.match("ChaCha({rounds:int=20})")) {
  ------------------
  |  Branch (86:12): [True: 1, False: 0]
  ------------------
   87|      1|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (87:10): [True: 1, False: 0]
  |  Branch (87:30): [True: 0, False: 0]
  ------------------
   88|      1|         return std::make_unique<ChaCha>(m->integer("rounds"));
   89|      1|      }
   90|      1|   }
   91|      0|#endif
   92|       |
   93|      0|#if defined(BOTAN_HAS_OFB)
   94|      0|   if(auto m = req.match("OFB({cipher})")) {
  ------------------
  |  Branch (94:12): [True: 0, False: 0]
  ------------------
   95|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (95:10): [True: 0, False: 0]
  |  Branch (95:30): [True: 0, False: 0]
  ------------------
   96|      0|         if(auto cipher = BlockCipher::create(m->str("cipher"))) {
  ------------------
  |  Branch (96:18): [True: 0, False: 0]
  ------------------
   97|      0|            return std::make_unique<OFB>(std::move(cipher));
   98|      0|         }
   99|      0|      }
  100|      0|   }
  101|      0|#endif
  102|       |
  103|      0|#if defined(BOTAN_HAS_RC4)
  104|      0|   if(auto m = req.match("RC4|ARC4({skip:int=0})")) {
  ------------------
  |  Branch (104:12): [True: 0, False: 0]
  ------------------
  105|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (105:10): [True: 0, False: 0]
  |  Branch (105:30): [True: 0, False: 0]
  ------------------
  106|      0|         return std::make_unique<RC4>(m->integer("skip"));
  107|      0|      }
  108|      0|   }
  109|       |
  110|      0|   if(req.matches("MARK-4")) {
  ------------------
  |  Branch (110:7): [True: 0, False: 0]
  ------------------
  111|      0|      if(provider.empty() || provider == "base") {
  ------------------
  |  Branch (111:10): [True: 0, False: 0]
  |  Branch (111:30): [True: 0, False: 0]
  ------------------
  112|      0|         return std::make_unique<RC4>(256);
  113|      0|      }
  114|      0|   }
  115|      0|#endif
  116|       |
  117|      0|   BOTAN_UNUSED(req);
  ------------------
  |  |  151|      0|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
  118|      0|   BOTAN_UNUSED(provider);
  ------------------
  |  |  151|      0|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
  119|       |
  120|      0|   return nullptr;
  121|      0|}
_ZN5Botan12StreamCipher15create_or_throwENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_:
  124|      1|std::unique_ptr<StreamCipher> StreamCipher::create_or_throw(std::string_view algo, std::string_view provider) {
  125|      1|   if(auto sc = StreamCipher::create(algo, provider)) {
  ------------------
  |  Branch (125:12): [True: 1, False: 0]
  ------------------
  126|      1|      return sc;
  127|      1|   }
  128|      0|   throw Lookup_Error("Stream cipher", algo, provider);
  129|      1|}

_ZN5Botan13AlgorithmSpec10parse_nameENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEERmmb:
   28|      4|AlgorithmSpec AlgorithmSpec::parse_name(std::string_view text, size_t& pos, size_t depth, bool mode_syntax) {
   29|      4|   if(depth > MaxNestingDepth) {
  ------------------
  |  Branch (29:7): [True: 0, False: 4]
  ------------------
   30|      0|      throw Invalid_Algorithm_Name(text);
   31|      0|   }
   32|       |
   33|       |   // The '/' separator is only significant at the top level of a cipher mode
   34|      4|   const bool slash_separates = mode_syntax && (depth == 0);
  ------------------
  |  Branch (34:33): [True: 0, False: 4]
  |  Branch (34:48): [True: 0, False: 0]
  ------------------
   35|      4|   const size_t start = pos;
   36|       |
   37|     23|   while(pos < text.size() && !is_spec_separator(text[pos], slash_separates)) {
  ------------------
  |  Branch (37:10): [True: 23, False: 0]
  |  Branch (37:31): [True: 19, False: 4]
  ------------------
   38|     19|      ++pos;
   39|     19|   }
   40|       |
   41|      4|   AlgorithmSpec node;
   42|      4|   node.m_head = std::string(text.substr(start, pos - start));
   43|       |
   44|      4|   if(node.m_head.empty()) {
  ------------------
  |  Branch (44:7): [True: 0, False: 4]
  ------------------
   45|      0|      throw Invalid_Algorithm_Name(text);
   46|      0|   }
   47|       |
   48|      4|   if(pos < text.size() && text[pos] == '(') {
  ------------------
  |  Branch (48:7): [True: 4, False: 0]
  |  Branch (48:28): [True: 2, False: 2]
  ------------------
   49|      2|      do {       // NOLINT(*-avoid-do-while)
   50|      2|         ++pos;  // skip the '(' or ','
   51|      2|         node.m_args.push_back(parse_name(text, pos, depth + 1, mode_syntax));
   52|      2|      } while(pos < text.size() && text[pos] == ',');
  ------------------
  |  Branch (52:15): [True: 2, False: 0]
  |  Branch (52:36): [True: 0, False: 2]
  ------------------
   53|       |
   54|      2|      if(pos >= text.size() || text[pos] != ')') {
  ------------------
  |  Branch (54:10): [True: 0, False: 2]
  |  Branch (54:32): [True: 0, False: 2]
  ------------------
   55|      0|         throw Invalid_Algorithm_Name(text);
   56|      0|      }
   57|      2|      ++pos;
   58|      2|   }
   59|       |
   60|      4|   node.m_text = std::string(text.substr(start, pos - start));
   61|      4|   return node;
   62|      4|}
_ZN5Botan13AlgorithmSpecC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEENS0_6SyntaxE:
   64|      2|AlgorithmSpec::AlgorithmSpec(std::string_view spec, Syntax syntax) {
   65|      2|   if(spec.empty()) {
  ------------------
  |  Branch (65:7): [True: 0, False: 2]
  ------------------
   66|      0|      throw Invalid_Algorithm_Name(spec);
   67|      0|   }
   68|       |
   69|      2|   const bool mode_syntax = (syntax == Syntax::CipherMode);
   70|       |
   71|       |   // Fast path for a bare name such as "SHA-256", which is the common case
   72|      2|   if(spec.find_first_of(mode_syntax ? "(),/" : "(),") == std::string_view::npos) {
  ------------------
  |  Branch (72:7): [True: 0, False: 2]
  |  Branch (72:26): [True: 0, False: 2]
  ------------------
   73|      0|      m_text = std::string(spec);
   74|      0|      m_head = std::string(spec);
   75|      0|      return;
   76|      0|   }
   77|       |
   78|      2|   size_t pos = 0;
   79|      2|   std::vector<AlgorithmSpec> parts;
   80|      2|   parts.push_back(parse_name(spec, pos, 0, mode_syntax));
   81|       |
   82|      2|   while(mode_syntax && pos < spec.size() && spec[pos] == '/') {
  ------------------
  |  Branch (82:10): [True: 0, False: 2]
  |  Branch (82:25): [True: 0, False: 0]
  |  Branch (82:46): [True: 0, False: 0]
  ------------------
   83|      0|      ++pos;
   84|      0|      parts.push_back(parse_name(spec, pos, 0, mode_syntax));
   85|      0|   }
   86|       |
   87|      2|   if(pos != spec.size()) {
  ------------------
  |  Branch (87:7): [True: 0, False: 2]
  ------------------
   88|      0|      throw Invalid_Algorithm_Name(spec);
   89|      0|   }
   90|       |
   91|      2|   if(parts.size() == 1) {
  ------------------
  |  Branch (91:7): [True: 2, False: 0]
  ------------------
   92|      2|      m_head = std::move(parts[0].m_head);
   93|      2|      m_args = std::move(parts[0].m_args);
   94|      2|   } else {
   95|       |      // Cipher/Mode(args)/Pad becomes Mode(Cipher,args,Pad)
   96|      0|      AlgorithmSpec& mode = parts[1];
   97|      0|      m_head = std::move(mode.m_head);
   98|      0|      m_args.push_back(std::move(parts[0]));
   99|      0|      for(auto& mode_arg : mode.m_args) {
  ------------------
  |  Branch (99:26): [True: 0, False: 0]
  ------------------
  100|      0|         m_args.push_back(std::move(mode_arg));
  101|      0|      }
  102|      0|      for(size_t i = 2; i < parts.size(); ++i) {
  ------------------
  |  Branch (102:25): [True: 0, False: 0]
  ------------------
  103|      0|         m_args.push_back(std::move(parts[i]));
  104|      0|      }
  105|      0|   }
  106|       |
  107|      2|   m_text = std::string(spec);
  108|      2|}
_ZNKR5Botan13AlgorithmSpec5matchERKNS_16AlgorithmPatternE:
  132|      5|std::optional<AlgorithmMatch> AlgorithmSpec::match(const AlgorithmPattern& pattern) const& {
  133|       |   // Factories try many patterns in turn, so reject on the head before
  134|       |   // setting up the (fairly large) match object
  135|      5|   if(!pattern.any_head()) {
  ------------------
  |  Branch (135:7): [True: 5, False: 0]
  ------------------
  136|      5|      bool head_matches = false;
  137|      7|      for(const auto alt : pattern.head_alternatives()) {
  ------------------
  |  Branch (137:26): [True: 7, False: 3]
  ------------------
  138|      7|         if(alt == m_head) {
  ------------------
  |  Branch (138:13): [True: 2, False: 5]
  ------------------
  139|      2|            head_matches = true;
  140|      2|            break;
  141|      2|         }
  142|      7|      }
  143|      5|      if(!head_matches) {
  ------------------
  |  Branch (143:10): [True: 3, False: 2]
  ------------------
  144|      3|         return std::nullopt;
  145|      3|      }
  146|      5|   }
  147|       |
  148|      2|   AlgorithmMatch m(pattern, *this);
  149|       |
  150|      2|   size_t idx = 0;
  151|      2|   if(!match_args(pattern.elements(), idx, 0, m)) {
  ------------------
  |  Branch (151:7): [True: 0, False: 2]
  ------------------
  152|      0|      return std::nullopt;
  153|      0|   }
  154|       |
  155|      2|   return m;
  156|      2|}
_ZNK5Botan13AlgorithmSpec10match_argsENSt3__14spanIKNS_16AlgorithmPattern7ElementELm18446744073709551615EEERmhRNS_14AlgorithmMatchE:
  161|      2|                               AlgorithmMatch& m) const {
  162|      2|   using Type = AlgorithmPattern::Type;
  163|       |
  164|      2|   size_t arg_idx = 0;
  165|       |
  166|      4|   while(idx < elems.size() && elems[idx].depth == depth) {
  ------------------
  |  Branch (166:10): [True: 2, False: 2]
  |  Branch (166:32): [True: 2, False: 0]
  ------------------
  167|      2|      const auto& e = elems[idx];
  168|      2|      ++idx;
  169|       |
  170|      2|      if(arg_idx >= m_args.size()) {
  ------------------
  |  Branch (170:10): [True: 0, False: 2]
  ------------------
  171|       |         // No argument was provided for this element
  172|      0|         if(!e.optional) {
  ------------------
  |  Branch (172:13): [True: 0, False: 0]
  ------------------
  173|      0|            return false;
  174|      0|         }
  175|       |
  176|      0|         if(e.placeholder && e.has_default) {
  ------------------
  |  Branch (176:13): [True: 0, False: 0]
  |  Branch (176:30): [True: 0, False: 0]
  ------------------
  177|      0|            auto& b = m.declared(e.text);
  178|      0|            b.bound = true;
  179|      0|            b.text = e.default_value;
  180|      0|            if(e.type == Type::Int) {
  ------------------
  |  Branch (180:16): [True: 0, False: 0]
  ------------------
  181|       |               // The pattern parser already checked this is a canonical decimal
  182|      0|               const auto v = parse_sz(e.default_value, true);
  183|      0|               BOTAN_ASSERT_NOMSG(v.has_value());
  ------------------
  |  |   84|      0|   do {                                                                     \
  |  |   85|      0|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   86|      0|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (86:10): [True: 0, False: 0]
  |  |  ------------------
  |  |   87|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   88|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   89|      0|      }                                                                     \
  |  |   90|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  ------------------
  ------------------
  184|      0|               b.integer = *v;
  185|      0|            }
  186|      0|         }
  187|       |
  188|      0|         continue;
  189|      0|      }
  190|       |
  191|      2|      const AlgorithmSpec& arg = m_args[arg_idx];
  192|       |
  193|      2|      if(e.variadic) {
  ------------------
  |  Branch (193:10): [True: 0, False: 2]
  ------------------
  194|      0|         auto& b = m.declared(e.text);
  195|      0|         b.bound = true;
  196|      0|         b.rest = std::span(m_args).subspan(arg_idx);
  197|      0|         arg_idx = m_args.size();
  198|      0|         continue;
  199|      0|      }
  200|       |
  201|      2|      if(e.placeholder) {
  ------------------
  |  Branch (201:10): [True: 2, False: 0]
  ------------------
  202|      2|         auto& b = m.declared(e.text);
  203|       |
  204|      2|         if(e.type == Type::Int) {
  ------------------
  |  Branch (204:13): [True: 1, False: 1]
  ------------------
  205|      1|            if(!arg.m_args.empty()) {
  ------------------
  |  Branch (205:16): [True: 0, False: 1]
  ------------------
  206|      0|               return false;
  207|      0|            }
  208|      1|            const auto v = parse_sz(arg.m_text, true);
  209|      1|            if(!v) {
  ------------------
  |  Branch (209:16): [True: 0, False: 1]
  ------------------
  210|      0|               return false;
  211|      0|            }
  212|      1|            b.integer = *v;
  213|      1|         }
  214|       |
  215|      2|         b.bound = true;
  216|      2|         b.text = arg.m_text;
  217|      2|         b.node = &arg;
  218|      2|      } else if(e.optional) {
  ------------------
  |  Branch (218:17): [True: 0, False: 0]
  ------------------
  219|       |         // An optional literal which is not present is skipped without consuming the argument
  220|      0|         if(arg.m_head != e.text || !arg.m_args.empty()) {
  ------------------
  |  Branch (220:13): [True: 0, False: 0]
  |  Branch (220:37): [True: 0, False: 0]
  ------------------
  221|      0|            continue;
  222|      0|         }
  223|      0|      } else {
  224|      0|         if(arg.m_head != e.text) {
  ------------------
  |  Branch (224:13): [True: 0, False: 0]
  ------------------
  225|      0|            return false;
  226|      0|         }
  227|       |
  228|      0|         if(idx < elems.size() && elems[idx].depth == depth + 1) {
  ------------------
  |  Branch (228:13): [True: 0, False: 0]
  |  Branch (228:35): [True: 0, False: 0]
  ------------------
  229|      0|            if(!arg.match_args(elems, idx, depth + 1, m)) {
  ------------------
  |  Branch (229:16): [True: 0, False: 0]
  ------------------
  230|      0|               return false;
  231|      0|            }
  232|      0|         } else if(!arg.m_args.empty()) {
  ------------------
  |  Branch (232:20): [True: 0, False: 0]
  ------------------
  233|      0|            return false;
  234|      0|         }
  235|      0|      }
  236|       |
  237|      2|      ++arg_idx;
  238|      2|   }
  239|       |
  240|      2|   return arg_idx == m_args.size();
  241|      2|}
_ZN5Botan14AlgorithmMatchC2ERKNS_16AlgorithmPatternERKNS_13AlgorithmSpecE:
  244|      2|      m_pattern(pattern.to_string()), m_head(spec.head()) {
  245|      2|   for(const auto& e : pattern.elements()) {
  ------------------
  |  Branch (245:22): [True: 2, False: 2]
  ------------------
  246|      2|      if(e.placeholder) {
  ------------------
  |  Branch (246:10): [True: 2, False: 0]
  ------------------
  247|      2|         Binding b;
  248|      2|         b.var = e.text;
  249|      2|         b.type = e.type;
  250|      2|         b.variadic = e.variadic;
  251|      2|         m_bindings[m_binding_count++] = b;
  252|      2|      }
  253|      2|   }
  254|      2|}
_ZN5Botan14AlgorithmMatch8declaredENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  256|      2|AlgorithmMatch::Binding& AlgorithmMatch::declared(std::string_view var) {
  257|      2|   for(size_t i = 0; i != m_binding_count; ++i) {
  ------------------
  |  Branch (257:22): [True: 2, False: 0]
  ------------------
  258|      2|      if(m_bindings[i].var == var) {
  ------------------
  |  Branch (258:10): [True: 2, False: 0]
  ------------------
  259|      2|         return m_bindings[i];
  260|      2|      }
  261|      2|   }
  262|      0|   throw Internal_Error(fmt("AlgorithmMatch: no variable '{}' in pattern '{}'", var, m_pattern));
  263|      2|}
_ZNK5Botan14AlgorithmMatch5boundENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEPKc:
  265|      2|const AlgorithmMatch::Binding& AlgorithmMatch::bound(std::string_view var, const char* accessor) const {
  266|      2|   for(size_t i = 0; i != m_binding_count; ++i) {
  ------------------
  |  Branch (266:22): [True: 2, False: 0]
  ------------------
  267|      2|      if(m_bindings[i].var == var) {
  ------------------
  |  Branch (267:10): [True: 2, False: 0]
  ------------------
  268|      2|         if(!m_bindings[i].bound) {
  ------------------
  |  Branch (268:13): [True: 0, False: 2]
  ------------------
  269|      0|            throw Internal_Error(
  270|      0|               fmt("AlgorithmMatch::{}: variable '{}' in pattern '{}' was not bound; check has() first",
  271|      0|                   accessor,
  272|      0|                   var,
  273|      0|                   m_pattern));
  274|      0|         }
  275|      2|         return m_bindings[i];
  276|      2|      }
  277|      2|   }
  278|      0|   throw Internal_Error(fmt("AlgorithmMatch::{}: no variable '{}' in pattern '{}'", accessor, var, m_pattern));
  279|      2|}
_ZNK5Botan14AlgorithmMatch3strENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  290|      1|std::string_view AlgorithmMatch::str(std::string_view var) const {
  291|      1|   const auto& b = bound(var, "str");
  292|      1|   if(b.variadic) {
  ------------------
  |  Branch (292:7): [True: 0, False: 1]
  ------------------
  293|      0|      throw Internal_Error(fmt("AlgorithmMatch::str: variable '{}' in pattern '{}' is variadic", var, m_pattern));
  294|      0|   }
  295|      1|   return b.text;
  296|      1|}
_ZNK5Botan14AlgorithmMatch7integerENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  298|      1|size_t AlgorithmMatch::integer(std::string_view var) const {
  299|      1|   const auto& b = bound(var, "integer");
  300|      1|   if(b.type != AlgorithmPattern::Type::Int) {
  ------------------
  |  Branch (300:7): [True: 0, False: 1]
  ------------------
  301|      0|      throw Internal_Error(fmt("AlgorithmMatch::integer: variable '{}' in pattern '{}' is not an int", var, m_pattern));
  302|      0|   }
  303|      1|   return b.integer;
  304|      1|}
algorithm_spec.cpp:_ZN5Botan12_GLOBAL__N_117is_spec_separatorEcb:
   21|     23|bool is_spec_separator(char c, bool slash_separates) {
   22|     23|   return c == '(' || c == ')' || c == ',' || (slash_separates && c == '/');
  ------------------
  |  Branch (22:11): [True: 2, False: 21]
  |  Branch (22:23): [True: 2, False: 19]
  |  Branch (22:35): [True: 0, False: 19]
  |  Branch (22:48): [True: 0, False: 19]
  |  Branch (22:67): [True: 0, False: 0]
  ------------------
   23|     23|}

_ZN5Botan15allocate_memoryEmm:
   21|   124k|BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size) {
   22|   124k|   if(elems == 0 || elem_size == 0) {
  ------------------
  |  Branch (22:7): [True: 0, False: 124k]
  |  Branch (22:21): [True: 0, False: 124k]
  ------------------
   23|      0|      return nullptr;
   24|      0|   }
   25|       |
   26|       |   // Some calloc implementations do not check for overflow (?!?)
   27|   124k|   if(!checked_mul(elems, elem_size).has_value()) {
  ------------------
  |  Branch (27:7): [True: 0, False: 124k]
  ------------------
   28|      0|      throw std::bad_alloc();
   29|      0|   }
   30|       |
   31|       |#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
   32|       |   // NOLINTNEXTLINE(*-const-correctness) bug in clang-tidy
   33|       |   if(void* p = mlock_allocator::instance().allocate(elems, elem_size)) {
   34|       |      return p;
   35|       |   }
   36|       |#endif
   37|       |
   38|       |#if defined(BOTAN_TARGET_OS_HAS_ALLOC_CONCEAL)
   39|       |   void* ptr = ::calloc_conceal(elems, elem_size);
   40|       |#else
   41|       |   // NOLINTNEXTLINE(*-const-correctness) bug in clang-tidy
   42|   124k|   void* ptr = std::calloc(elems, elem_size);  // NOLINT(*-no-malloc,*-owning-memory)
   43|   124k|#endif
   44|   124k|   if(ptr == nullptr) {
  ------------------
  |  Branch (44:7): [True: 0, False: 124k]
  ------------------
   45|      0|      [[unlikely]] throw std::bad_alloc();
   46|      0|   }
   47|   124k|   return ptr;
   48|   124k|}
_ZN5Botan17deallocate_memoryEPvmm:
   50|   124k|void deallocate_memory(void* p, size_t elems, size_t elem_size) {
   51|   124k|   if(p == nullptr) {
  ------------------
  |  Branch (51:7): [True: 0, False: 124k]
  ------------------
   52|      0|      [[unlikely]] return;
   53|      0|   }
   54|       |
   55|   124k|   secure_scrub_memory(p, elems * elem_size);
   56|       |
   57|       |#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
   58|       |   if(mlock_allocator::instance().deallocate(p, elems, elem_size)) {
   59|       |      return;
   60|       |   }
   61|       |#endif
   62|       |
   63|   124k|   std::free(p);  // NOLINT(*-no-malloc,*-owning-memory)
   64|   124k|}

_ZN5Botan22throw_invalid_argumentEPKcS1_S1_:
   23|      1|void throw_invalid_argument(const char* message, const char* func, const char* file) {
   24|      1|   throw Invalid_Argument(fmt("{} in {}:{}", message, func, file));
   25|      1|}

_ZN5Botan5CPUID10CPUID_DataC2Ev:
   80|      1|CPUID::CPUID_Data::CPUID_Data() {
   81|       |   // NOLINTBEGIN(*-prefer-member-initializer)
   82|      1|#if defined(BOTAN_HAS_CPUID_DETECTION)
   83|      1|   m_processor_features = detect_cpu_features(~cleared_cpuid_bits());
   84|       |#else
   85|       |   m_processor_features = 0;
   86|       |#endif
   87|       |   // NOLINTEND(*-prefer-member-initializer)
   88|      1|}
cpuid.cpp:_ZN5Botan12_GLOBAL__N_118cleared_cpuid_bitsEv:
   59|      1|uint32_t cleared_cpuid_bits() {
   60|      1|   uint32_t cleared = 0;
   61|       |
   62|      1|   #if defined(BOTAN_HAS_OS_UTILS)
   63|      1|   std::string clear_cpuid_env;
   64|      1|   if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID")) {
  ------------------
  |  Branch (64:7): [True: 0, False: 1]
  ------------------
   65|      0|      for(const auto& cpuid : split_on(clear_cpuid_env, ',')) {
  ------------------
  |  Branch (65:29): [True: 0, False: 0]
  ------------------
   66|      0|         if(auto bit = CPUID::bit_from_string(cpuid)) {
  ------------------
  |  Branch (66:18): [True: 0, False: 0]
  ------------------
   67|      0|            cleared |= bit->as_u32();
   68|      0|         }
   69|      0|      }
   70|      0|   }
   71|      1|   #endif
   72|       |
   73|      1|   return cleared;
   74|      1|}

_ZN5Botan5CPUID10CPUID_Data19detect_cpu_featuresEj:
   62|      1|uint32_t CPUID::CPUID_Data::detect_cpu_features(uint32_t allowed) {
   63|      1|   enum class x86_CPUID_1_bits : uint64_t {
   64|      1|      RDTSC = (1ULL << 4),
   65|      1|      SSE2 = (1ULL << 26),
   66|      1|      CLMUL = (1ULL << 33),
   67|      1|      SSSE3 = (1ULL << 41),
   68|      1|      SSE41 = (1ULL << 51),
   69|      1|      POPCNT = (1ULL << 55),
   70|      1|      AESNI = (1ULL << 57),
   71|       |      // AVX + OSXSAVE
   72|      1|      OSXSAVE = (1ULL << 59) | (1ULL << 60),
   73|      1|      RDRAND = (1ULL << 62)
   74|      1|   };
   75|       |
   76|      1|   enum class x86_CPUID_7_bits : uint64_t {
   77|      1|      BMI1 = (1ULL << 3),
   78|      1|      AVX2 = (1ULL << 5),
   79|      1|      BMI2 = (1ULL << 8),
   80|      1|      BMI_1_AND_2 = BMI1 | BMI2,
   81|      1|      AVX512_F = (1ULL << 16),
   82|      1|      AVX512_DQ = (1ULL << 17),
   83|      1|      RDSEED = (1ULL << 18),
   84|      1|      ADX = (1ULL << 19),
   85|      1|      AVX512_IFMA = (1ULL << 21),
   86|      1|      SHA = (1ULL << 29),
   87|      1|      AVX512_BW = (1ULL << 30),
   88|      1|      AVX512_VL = (1ULL << 31),
   89|      1|      AVX512_VBMI = (1ULL << 33),
   90|      1|      AVX512_VBMI2 = (1ULL << 38),
   91|      1|      GFNI = (1ULL << 40),
   92|      1|      AVX512_VAES = (1ULL << 41),
   93|      1|      AVX512_VCLMUL = (1ULL << 42),
   94|      1|      AVX512_VBITALG = (1ULL << 44),
   95|       |
   96|       |      /*
   97|       |      We only enable AVX512 support if all of the below flags are available
   98|       |
   99|       |      This is more than we strictly need for most uses, however it also has
  100|       |      the effect of preventing execution of AVX512 codepaths on cores that
  101|       |      have serious downclocking problems when AVX512 code executes,
  102|       |      especially Intel Skylake.
  103|       |
  104|       |      VBMI2/VBITALG are the key flags here as they restrict us to Intel Ice
  105|       |      Lake/Rocket Lake, or AMD Zen4, all of which do not have penalties for
  106|       |      executing AVX512.
  107|       |
  108|       |      There is nothing stopping some future processor from supporting the
  109|       |      above flags and having AVX512 penalties, but maybe you should not have
  110|       |      bought such a processor.
  111|       |      */
  112|      1|      AVX512_PROFILE =
  113|      1|         AVX512_F | AVX512_DQ | AVX512_IFMA | AVX512_BW | AVX512_VL | AVX512_VBMI | AVX512_VBMI2 | AVX512_VBITALG,
  114|      1|   };
  115|       |
  116|       |   // NOLINTNEXTLINE(performance-enum-size)
  117|      1|   enum class x86_CPUID_7_1_bits : uint64_t {
  118|      1|      SHA512 = (1 << 0),
  119|      1|      SM3 = (1 << 1),
  120|      1|      SM4 = (1 << 2),
  121|      1|   };
  122|       |
  123|      1|   uint32_t feat = 0;
  124|      1|   uint32_t cpuid[4] = {0};
  125|      1|   bool has_sse41 = false;
  126|      1|   bool has_os_ymm_support = false;
  127|      1|   bool has_os_zmm_support = false;
  128|       |
  129|       |   // CPUID 0: vendor identification, max sublevel
  130|      1|   invoke_cpuid(0, cpuid);
  131|       |
  132|      1|   const uint32_t max_supported_sublevel = cpuid[0];
  133|       |
  134|      1|   if(max_supported_sublevel >= 1) {
  ------------------
  |  Branch (134:7): [True: 1, False: 0]
  ------------------
  135|       |      // CPUID 1: feature bits
  136|      1|      invoke_cpuid(1, cpuid);
  137|      1|      const uint64_t flags0 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[3];
  138|       |
  139|      1|      feat |= if_set(flags0, x86_CPUID_1_bits::RDTSC, CPUFeature::Bit::RDTSC, allowed);
  140|       |
  141|      1|      feat |= if_set(flags0, x86_CPUID_1_bits::RDRAND, CPUFeature::Bit::RDRAND, allowed);
  142|       |
  143|      1|      feat |= if_set(flags0, x86_CPUID_1_bits::POPCNT, CPUFeature::Bit::POPCNT, allowed);
  144|       |
  145|      1|      feat |= if_set(flags0, x86_CPUID_1_bits::SSE2, CPUFeature::Bit::SSE2, allowed);
  146|       |
  147|      1|      if(is_set(feat, CPUFeature::Bit::SSE2)) {
  ------------------
  |  Branch (147:10): [True: 1, False: 0]
  ------------------
  148|      1|         feat |= if_set(flags0, x86_CPUID_1_bits::SSSE3, CPUFeature::Bit::SSSE3, allowed);
  149|       |
  150|      1|         if(is_set(feat, CPUFeature::Bit::SSSE3)) {
  ------------------
  |  Branch (150:13): [True: 1, False: 0]
  ------------------
  151|      1|            feat |= if_set(flags0, x86_CPUID_1_bits::CLMUL, CPUFeature::Bit::CLMUL, allowed);
  152|      1|            feat |= if_set(flags0, x86_CPUID_1_bits::AESNI, CPUFeature::Bit::AESNI, allowed);
  153|       |
  154|       |            // SSE4.1 is not tracked as a feature, but is required by the SHA-NI code
  155|      1|            const uint64_t sse41 = static_cast<uint64_t>(x86_CPUID_1_bits::SSE41);
  156|      1|            has_sse41 = (flags0 & sse41) == sse41;
  157|      1|         }
  158|       |
  159|      1|         const uint64_t osxsave64 = static_cast<uint64_t>(x86_CPUID_1_bits::OSXSAVE);
  160|      1|         if((flags0 & osxsave64) == osxsave64) {
  ------------------
  |  Branch (160:13): [True: 1, False: 0]
  ------------------
  161|      1|            const uint64_t xcr_flags = xgetbv();
  162|      1|            if((xcr_flags & 0x6) == 0x6) {
  ------------------
  |  Branch (162:16): [True: 1, False: 0]
  ------------------
  163|      1|               has_os_ymm_support = true;
  164|      1|               has_os_zmm_support = (xcr_flags & 0xE0) == 0xE0;
  165|      1|            }
  166|      1|         }
  167|      1|      }
  168|      1|   }
  169|       |
  170|      1|   if(max_supported_sublevel >= 7) {
  ------------------
  |  Branch (170:7): [True: 1, False: 0]
  ------------------
  171|      1|      clear_mem(cpuid, 4);
  172|      1|      invoke_cpuid_sublevel(7, 0, cpuid);
  173|       |
  174|      1|      const uint64_t flags7 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[1];
  175|       |
  176|      1|      clear_mem(cpuid, 4);
  177|      1|      invoke_cpuid_sublevel(7, 1, cpuid);
  178|      1|      const uint32_t flags7_1 = cpuid[0];
  179|       |
  180|      1|      feat |= if_set(flags7, x86_CPUID_7_bits::RDSEED, CPUFeature::Bit::RDSEED, allowed);
  181|      1|      feat |= if_set(flags7, x86_CPUID_7_bits::ADX, CPUFeature::Bit::ADX, allowed);
  182|       |
  183|       |      /*
  184|       |      We only set the BMI bit if both BMI1 and BMI2 are supported, since
  185|       |      typically we want to use both extensions in the same code.
  186|       |      */
  187|      1|      feat |= if_set(flags7, x86_CPUID_7_bits::BMI_1_AND_2, CPUFeature::Bit::BMI, allowed);
  188|       |
  189|      1|      if(is_set(feat, CPUFeature::Bit::SSSE3)) {
  ------------------
  |  Branch (189:10): [True: 1, False: 0]
  ------------------
  190|       |         // The SHA-NI code uses SSE4.1 instructions in addition to SSSE3
  191|      1|         if(has_sse41) {
  ------------------
  |  Branch (191:13): [True: 1, False: 0]
  ------------------
  192|      1|            feat |= if_set(flags7, x86_CPUID_7_bits::SHA, CPUFeature::Bit::SHA, allowed);
  193|      1|         }
  194|       |
  195|       |         // We only consider AVX2 if SSSE3 is supported
  196|      1|         if(has_os_ymm_support) {
  ------------------
  |  Branch (196:13): [True: 1, False: 0]
  ------------------
  197|      1|            feat |= if_set(flags7, x86_CPUID_7_bits::AVX2, CPUFeature::Bit::AVX2, allowed);
  198|       |
  199|      1|            if(is_set(feat, CPUFeature::Bit::AVX2)) {
  ------------------
  |  Branch (199:16): [True: 1, False: 0]
  ------------------
  200|      1|               feat |= if_set(flags7, x86_CPUID_7_bits::GFNI, CPUFeature::Bit::GFNI, allowed);
  201|      1|               feat |= if_set(flags7, x86_CPUID_7_bits::AVX512_VAES, CPUFeature::Bit::AVX2_AES, allowed);
  202|      1|               feat |= if_set(flags7_1, x86_CPUID_7_1_bits::SHA512, CPUFeature::Bit::SHA512, allowed);
  203|       |               // The SM3/SM4 instructions are VEX encoded and the code using them also uses AVX2
  204|      1|               feat |= if_set(flags7_1, x86_CPUID_7_1_bits::SM3, CPUFeature::Bit::SM3, allowed);
  205|      1|               feat |= if_set(flags7_1, x86_CPUID_7_1_bits::SM4, CPUFeature::Bit::SM4, allowed);
  206|       |
  207|       |               // The VPCLMULQDQ code also uses the legacy 128-bit PCLMULQDQ instruction
  208|      1|               if(is_set(feat, CPUFeature::Bit::CLMUL)) {
  ------------------
  |  Branch (208:19): [True: 1, False: 0]
  ------------------
  209|      1|                  feat |= if_set(flags7, x86_CPUID_7_bits::AVX512_VCLMUL, CPUFeature::Bit::AVX2_CLMUL, allowed);
  210|      1|               }
  211|       |
  212|       |               // Likewise we only consider AVX-512 if AVX2 is supported
  213|      1|               if(has_os_zmm_support) {
  ------------------
  |  Branch (213:19): [True: 0, False: 1]
  ------------------
  214|      0|                  feat |= if_set(flags7, x86_CPUID_7_bits::AVX512_PROFILE, CPUFeature::Bit::AVX512, allowed);
  215|       |
  216|      0|                  if(is_set(feat, CPUFeature::Bit::AVX512)) {
  ------------------
  |  Branch (216:22): [True: 0, False: 0]
  ------------------
  217|      0|                     feat |= if_set(flags7, x86_CPUID_7_bits::AVX512_VAES, CPUFeature::Bit::AVX512_AES, allowed);
  218|      0|                     if(is_set(feat, CPUFeature::Bit::CLMUL)) {
  ------------------
  |  Branch (218:25): [True: 0, False: 0]
  ------------------
  219|      0|                        feat |= if_set(flags7, x86_CPUID_7_bits::AVX512_VCLMUL, CPUFeature::Bit::AVX512_CLMUL, allowed);
  220|      0|                     }
  221|      0|                  }
  222|      0|               }
  223|      1|            }
  224|      1|         }
  225|      1|      }
  226|      1|   }
  227|       |
  228|       |/*
  229|       |   * If we don't have access to CPUID, we can still safely assume that
  230|       |   * any x86-64 processor has SSE2 and RDTSC
  231|       |   */
  232|      1|#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
  233|      1|   if(feat == 0) {
  ------------------
  |  Branch (233:7): [True: 0, False: 1]
  ------------------
  234|      0|      feat |= CPUFeature::Bit::SSE2 & allowed;
  235|      0|      feat |= CPUFeature::Bit::RDTSC & allowed;
  236|      0|   }
  237|      1|#endif
  238|       |
  239|      1|   return feat;
  240|      1|}
cpuid_x86.cpp:_ZN5Botan12_GLOBAL__N_112invoke_cpuidEjPj:
   24|      2|void invoke_cpuid(uint32_t type, uint32_t out[4]) {
   25|      2|   clear_mem(out, 4);
   26|       |
   27|      2|#if defined(BOTAN_USE_GCC_INLINE_ASM)
   28|       |   // NOLINTNEXTLINE(*-no-assembler)
   29|      2|   asm volatile("cpuid\n\t" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "0"(type));
   30|       |
   31|       |#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   32|       |   __cpuid((int*)out, type);
   33|       |
   34|       |#else
   35|       |   BOTAN_UNUSED(type);
   36|       |   #warning "No way of calling x86 cpuid instruction for this compiler"
   37|       |#endif
   38|      2|}
cpuid_x86.cpp:_ZN5Botan12_GLOBAL__N_16xgetbvEv:
   56|      1|BOTAN_FUNC_ISA("xsave") uint64_t xgetbv() {
   57|       |   return _xgetbv(0);
   58|      1|}
cpuid_x86.cpp:_ZN5Botan12_GLOBAL__N_121invoke_cpuid_sublevelEjjPj:
   40|      2|void invoke_cpuid_sublevel(uint32_t type, uint32_t level, uint32_t out[4]) {
   41|      2|   clear_mem(out, 4);
   42|       |
   43|      2|#if defined(BOTAN_USE_GCC_INLINE_ASM)
   44|       |   // NOLINTNEXTLINE(*-no-assembler)
   45|      2|   asm volatile("cpuid\n\t" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "0"(type), "2"(level));
   46|       |
   47|       |#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   48|       |   __cpuidex((int*)out, type, level);
   49|       |
   50|       |#else
   51|       |   BOTAN_UNUSED(type, level);
   52|       |   #warning "No way of calling x86 cpuid instruction for this compiler"
   53|       |#endif
   54|      2|}

_ZN5Botan9ExceptionC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   71|      1|Exception::Exception(std::string_view msg) : m_msg(msg) {}
_ZN5Botan16Invalid_ArgumentC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   77|      1|Invalid_Argument::Invalid_Argument(std::string_view msg) : Exception(msg) {}

_ZN5Botan19secure_scrub_memoryEPvm:
   24|   124k|void secure_scrub_memory(void* ptr, size_t n) {
   25|   124k|   return secure_zeroize_buffer(ptr, n);
   26|   124k|}
_ZN5Botan21secure_zeroize_bufferEPvm:
   28|   124k|void secure_zeroize_buffer(void* ptr, size_t n) {
   29|   124k|   if(n == 0) {
  ------------------
  |  Branch (29:7): [True: 0, False: 124k]
  ------------------
   30|      0|      return;
   31|      0|   }
   32|       |
   33|       |#if defined(BOTAN_TARGET_OS_HAS_RTLSECUREZEROMEMORY)
   34|       |   ::RtlSecureZeroMemory(ptr, n);
   35|       |
   36|       |#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_BZERO)
   37|   124k|   ::explicit_bzero(ptr, n);
   38|       |
   39|       |#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_MEMSET)
   40|       |   (void)::explicit_memset(ptr, 0, n);
   41|       |
   42|       |#else
   43|       |   /*
   44|       |   * Call memset through a static volatile pointer, which the compiler should
   45|       |   * not elide. This construct should be safe in conforming compilers, but who
   46|       |   * knows. This has been checked to generate the expected code, which saves the
   47|       |   * memset address in the data segment and unconditionally loads and jumps to
   48|       |   * that address, with the following targets:
   49|       |   *
   50|       |   * x86-64: Clang 19, GCC 6, 11, 13, 14
   51|       |   * riscv64: GCC 14
   52|       |   * aarch64: GCC 14
   53|       |   * armv7: GCC 14
   54|       |   *
   55|       |   * Actually all of them generated the expected jump even without marking the
   56|       |   * function pointer as volatile. However this seems worth including as an
   57|       |   * additional precaution.
   58|       |   */
   59|       |   static void* (*const volatile memset_ptr)(void*, int, size_t) = std::memset;
   60|       |   (memset_ptr)(ptr, 0, n);
   61|       |#endif
   62|   124k|}

_ZN5Botan2OS14get_process_idEv:
   78|     56|uint32_t OS::get_process_id() {
   79|     56|#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   80|     56|   return ::getpid();
   81|       |#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
   82|       |   return ::GetCurrentProcessId();
   83|       |#elif defined(BOTAN_TARGET_OS_IS_LLVM) || defined(BOTAN_TARGET_OS_IS_NONE)
   84|       |   return 0;  // truly no meaningful value
   85|       |#else
   86|       |   #error "Missing get_process_id"
   87|       |#endif
   88|     56|}
_ZN5Botan2OS17read_env_variableERNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_17basic_string_viewIcS4_EE:
  471|      1|bool OS::read_env_variable(std::string& value_out, std::string_view name_view) {
  472|      1|   value_out = "";
  473|       |
  474|      1|   if(running_in_privileged_state()) {
  ------------------
  |  Branch (474:7): [True: 0, False: 1]
  ------------------
  475|      0|      return false;
  476|      0|   }
  477|       |
  478|       |#if defined(BOTAN_TARGET_OS_HAS_WIN32) && \
  479|       |   (defined(BOTAN_BUILD_COMPILER_IS_MSVC) || defined(BOTAN_BUILD_COMPILER_IS_CLANGCL))
  480|       |   const std::string name(name_view);
  481|       |
  482|       |   // First query the required buffer size; req_size is 0 if the variable is not set
  483|       |   size_t req_size = 0;
  484|       |   if(getenv_s(&req_size, nullptr, 0, name.c_str()) != 0 || req_size == 0) {
  485|       |      return false;
  486|       |   }
  487|       |
  488|       |   // The reported size includes the terminating \0
  489|       |   std::string val(req_size, '\0');
  490|       |   if(getenv_s(&req_size, val.data(), val.size(), name.c_str()) != 0) {
  491|       |      return false;
  492|       |   }
  493|       |
  494|       |   value_out = std::string(val.c_str());
  495|       |   return true;
  496|       |#else
  497|      1|   const std::string name(name_view);
  498|      1|   if(const char* val = std::getenv(name.c_str())) {
  ------------------
  |  Branch (498:19): [True: 0, False: 1]
  ------------------
  499|      0|      value_out = val;
  500|      0|      return true;
  501|      0|   }
  502|      1|#endif
  503|       |
  504|      1|   return false;
  505|      1|}
_ZN5Botan2OS19get_fork_generationEv:
  704|     56|uint64_t OS::get_fork_generation() {
  705|     56|#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
  706|     56|   static std::once_flag g_atfork_initialized;
  707|     56|   std::call_once(g_atfork_initialized, setup_atfork);
  708|     56|   return g_fork_generation;
  709|       |#else
  710|       |   return 0;
  711|       |#endif
  712|     56|}
_ZN5Botan2OS13Fork_DetectorC2Ev:
  714|      3|OS::Fork_Detector::Fork_Detector() : m_process_id(OS::get_process_id()), m_fork_generation(OS::get_fork_generation()) {}
_ZN5Botan2OS13Fork_Detector10rebaselineEv:
  716|      2|void OS::Fork_Detector::rebaseline() {
  717|      2|   *this = Fork_Detector();
  718|      2|}
_ZNK5Botan2OS13Fork_Detector13fork_detectedEv:
  720|     53|bool OS::Fork_Detector::fork_detected() const {
  721|       |   // The PID check also catches clones which bypass the pthread_atfork handlers
  722|     53|   return OS::get_process_id() != m_process_id || OS::get_fork_generation() != m_fork_generation;
  ------------------
  |  Branch (722:11): [True: 0, False: 53]
  |  Branch (722:51): [True: 0, False: 53]
  ------------------
  723|     53|}
os_utils.cpp:_ZN5Botan12_GLOBAL__N_110get_auxvalENSt3__18optionalImEE:
  120|      1|std::optional<unsigned long> get_auxval(std::optional<unsigned long> id) {
  121|      1|   if(id) {
  ------------------
  |  Branch (121:7): [True: 1, False: 0]
  ------------------
  122|      1|#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
  123|      1|      return ::getauxval(*id);
  124|       |#elif defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
  125|       |      unsigned long auxinfo = 0;
  126|       |      if(::elf_aux_info(static_cast<int>(*id), &auxinfo, sizeof(auxinfo)) == 0) {
  127|       |         return auxinfo;
  128|       |      }
  129|       |#endif
  130|      1|   }
  131|       |
  132|      0|   return {};
  133|      1|}
os_utils.cpp:_ZN5Botan12_GLOBAL__N_127running_in_privileged_stateEv:
  154|      1|bool running_in_privileged_state() {
  155|      1|#if defined(AT_SECURE)
  156|      1|   if(const auto at_secure = get_auxval(AT_SECURE)) {
  ------------------
  |  Branch (156:18): [True: 1, False: 0]
  ------------------
  157|      1|      return at_secure != 0;
  158|      1|   }
  159|      0|#endif
  160|       |
  161|      0|#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
  162|      0|   return (::getuid() != ::geteuid()) || (::getgid() != ::getegid());
  ------------------
  |  Branch (162:11): [True: 0, False: 0]
  |  Branch (162:42): [True: 0, False: 0]
  ------------------
  163|       |#else
  164|       |   return false;
  165|       |#endif
  166|      1|}
os_utils.cpp:_ZN5Botan12_GLOBAL__N_112setup_atforkEv:
  691|      1|void setup_atfork() {
  692|      1|   const int rc = ::pthread_atfork(/*prepare=*/nullptr,
  693|      1|                                   /*parent=*/nullptr,
  694|      1|                                   /*child=*/atfork_in_child);
  695|       |
  696|      1|   if(rc != 0) {
  ------------------
  |  Branch (696:7): [True: 0, False: 1]
  ------------------
  697|      0|      throw Internal_Error("Failed to setup pthread_atfork handler");
  698|      0|   }
  699|      1|}

_ZN5Botan8parse_szENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEEb:
   71|      1|std::optional<size_t> parse_sz(std::string_view input, bool require_canonical) {
   72|      1|   return parse_decimal_integer<size_t>(input, require_canonical);
   73|      1|}
parsing.cpp:_ZN5Botan12_GLOBAL__N_116digit_from_asciiEc:
   22|      2|std::optional<size_t> digit_from_ascii(char c) {
   23|      2|   if(c >= '0' && c <= '9') {
  ------------------
  |  Branch (23:7): [True: 2, False: 0]
  |  Branch (23:19): [True: 2, False: 0]
  ------------------
   24|      2|      return c - '0';
   25|      2|   } else {
   26|      0|      return {};
   27|      0|   }
   28|      2|}
parsing.cpp:_ZN5Botan12_GLOBAL__N_121parse_decimal_integerITkNSt3__117unsigned_integralEmEENS2_8optionalIT_EENS2_17basic_string_viewIcNS2_11char_traitsIcEEEEb:
   31|      1|std::optional<T> parse_decimal_integer(std::string_view input, bool require_canonical) {
   32|      1|   if(input.empty() || input.size() > (std::numeric_limits<T>::digits10 + 1)) {
  ------------------
  |  Branch (32:7): [True: 0, False: 1]
  |  Branch (32:24): [True: 0, False: 1]
  ------------------
   33|      0|      return {};
   34|      0|   }
   35|       |
   36|       |   // The canonical encoding of zero is "0"; no other value starts with a zero
   37|      1|   if(require_canonical && input.size() > 1 && input.front() == '0') {
  ------------------
  |  Branch (37:7): [True: 1, False: 0]
  |  Branch (37:28): [True: 1, False: 0]
  |  Branch (37:48): [True: 0, False: 1]
  ------------------
   38|      0|      return {};
   39|      0|   }
   40|       |
   41|      1|   T accum = 0;
   42|       |
   43|      2|   for(const char c : input) {
  ------------------
  |  Branch (43:21): [True: 2, False: 1]
  ------------------
   44|      2|      if(const auto digit = digit_from_ascii(c)) {
  ------------------
  |  Branch (44:21): [True: 2, False: 0]
  ------------------
   45|      2|         if(accum > (std::numeric_limits<T>::max() - static_cast<T>(*digit)) / 10) {
  ------------------
  |  Branch (45:13): [True: 0, False: 2]
  ------------------
   46|      0|            return {};
   47|      0|         }
   48|      2|         accum = accum * 10 + static_cast<T>(*digit);
   49|      2|      } else {
   50|      0|         return {};
   51|      0|      }
   52|      2|   }
   53|       |
   54|      1|   return accum;
   55|      1|}

