Coverage Report

Created: 2026-06-30 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/build/include/internal/botan/internal/donna128.h
Line
Count
Source
1
/*
2
* A minimal 128-bit integer type
3
* (C) 2014 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#ifndef BOTAN_DONNA128_H_
9
#define BOTAN_DONNA128_H_
10
11
#include <botan/internal/ct_utils.h>
12
#include <botan/internal/mul128.h>
13
#include <concepts>
14
15
namespace Botan {
16
17
class donna128 final {
18
   public:
19
0
      constexpr explicit donna128(uint64_t l = 0, uint64_t h = 0) : m_lo(l), m_hi(h) {}
20
21
      template <std::unsigned_integral T>
22
0
      constexpr friend donna128 operator>>(const donna128& x, T shift) {
23
0
         donna128 z = x;
24
0
25
0
         if(shift > 64) {
26
0
            z.m_lo = z.m_hi >> (shift - 64);
27
0
            z.m_hi = 0;
28
0
         } else if(shift == 64) {
29
0
            z.m_lo = z.m_hi;
30
0
            z.m_hi = 0;
31
0
         } else if(shift > 0) {
32
0
            const uint64_t carry = z.m_hi << static_cast<size_t>(64 - shift);
33
0
            z.m_hi >>= shift;
34
0
            z.m_lo >>= shift;
35
0
            z.m_lo |= carry;
36
0
         }
37
0
38
0
         return z;
39
0
      }
40
41
      template <std::unsigned_integral T>
42
0
      constexpr friend donna128 operator<<(const donna128& x, T shift) {
43
0
         donna128 z = x;
44
0
         if(shift > 64) {
45
0
            z.m_hi = z.m_lo << (shift - 64);
46
0
            z.m_lo = 0;
47
0
         } else if(shift == 64) {
48
0
            z.m_hi = z.m_lo;
49
0
            z.m_lo = 0;
50
0
         } else if(shift > 0) {
51
0
            const uint64_t carry = z.m_lo >> static_cast<size_t>(64 - shift);
52
0
            z.m_lo = (z.m_lo << shift);
53
0
            z.m_hi = (z.m_hi << shift) | carry;
54
0
         }
55
0
56
0
         return z;
57
0
      }
58
59
0
      constexpr friend uint64_t operator&(const donna128& x, uint64_t mask) { return x.m_lo & mask; }
60
61
0
      constexpr uint64_t operator&=(uint64_t mask) {
62
0
         m_hi = 0;
63
0
         m_lo &= mask;
64
0
         return m_lo;
65
0
      }
66
67
0
      constexpr donna128& operator+=(const donna128& x) {
68
0
         m_lo += x.m_lo;
69
0
         m_hi += x.m_hi;
70
0
71
0
         const uint64_t carry = CT::Mask<uint64_t>::is_lt(m_lo, x.m_lo).if_set_return(1);
72
0
         m_hi += carry;
73
0
         return *this;
74
0
      }
75
76
0
      constexpr donna128& operator+=(uint64_t x) {
77
0
         m_lo += x;
78
0
         const uint64_t carry = CT::Mask<uint64_t>::is_lt(m_lo, x).if_set_return(1);
79
0
         m_hi += carry;
80
0
         return *this;
81
0
      }
82
83
0
      constexpr uint64_t lo() const { return m_lo; }
84
85
0
      constexpr uint64_t hi() const { return m_hi; }
86
87
0
      constexpr explicit operator uint64_t() const { return lo(); }
88
89
   private:
90
      uint64_t m_lo = 0;
91
      uint64_t m_hi = 0;
92
};
93
94
template <std::integral T>
95
constexpr inline donna128 operator*(const donna128& x, T y) {
96
   BOTAN_ARG_CHECK(x.hi() == 0, "High 64 bits of donna128 set to zero during multiply");
97
98
   uint64_t lo = 0;
99
   uint64_t hi = 0;
100
   mul64x64_128(x.lo(), static_cast<uint64_t>(y), &lo, &hi);
101
   return donna128(lo, hi);
102
}
103
104
template <std::integral T>
105
constexpr inline donna128 operator*(T y, const donna128& x) {
106
   return x * y;
107
}
108
109
0
constexpr inline donna128 operator+(const donna128& x, const donna128& y) {
110
0
   donna128 z = x;
111
0
   z += y;
112
0
   return z;
113
0
}
114
115
0
constexpr inline donna128 operator+(const donna128& x, uint64_t y) {
116
0
   donna128 z = x;
117
0
   z += y;
118
0
   return z;
119
0
}
120
121
0
constexpr inline donna128 operator|(const donna128& x, const donna128& y) {
122
0
   return donna128(x.lo() | y.lo(), x.hi() | y.hi());
123
0
}
124
125
0
constexpr inline donna128 operator|(const donna128& x, uint64_t y) {
126
0
   return donna128(x.lo() | y, x.hi());
127
0
}
128
129
0
constexpr inline uint64_t carry_shift(const donna128& a, size_t shift) {
130
0
   return (a >> shift).lo();
131
0
}
132
133
0
constexpr inline uint64_t combine_lower(const donna128& a, size_t s1, const donna128& b, size_t s2) {
134
0
   donna128 z = (a >> s1) | (b << s2);
135
0
   return z.lo();
136
0
}
137
138
#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
139
0
inline uint64_t carry_shift(const uint128_t a, size_t shift) {
140
0
   return static_cast<uint64_t>(a >> shift);
141
0
}
142
143
0
inline uint64_t combine_lower(const uint128_t a, size_t s1, const uint128_t b, size_t s2) {
144
0
   return static_cast<uint64_t>((a >> s1) | (b << s2));
145
0
}
146
#endif
147
148
}  // namespace Botan
149
150
#endif