/src/serenity/AK/UFixedBigInt.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com> |
3 | | * Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/BigIntBase.h> |
11 | | #include <AK/BuiltinWrappers.h> |
12 | | #include <AK/Checked.h> |
13 | | #include <AK/Concepts.h> |
14 | | #include <AK/Endian.h> |
15 | | #include <AK/Format.h> |
16 | | #include <AK/NumericLimits.h> |
17 | | #include <AK/StdLibExtraDetails.h> |
18 | | #include <AK/StdLibExtras.h> |
19 | | #include <AK/StringBuilder.h> |
20 | | |
21 | | namespace AK { |
22 | | |
23 | | namespace Detail { |
24 | | // As noted near the declaration of StaticStorage, bit_size is more like a hint for a storage size. |
25 | | // The effective bit size is `sizeof(StaticStorage<...>) * 8`. It is a programmer's responsibility |
26 | | // to ensure that the hinted bit_size is always greater than the actual integer size. |
27 | | // That said, do not use unaligned (bit_size % 64 != 0) `UFixedBigInt`s if you do not know what you |
28 | | // are doing. |
29 | | template<size_t bit_size, typename Storage = StaticStorage<false, bit_size>> |
30 | | class UFixedBigInt; |
31 | | |
32 | | // ===== Concepts ===== |
33 | | template<typename T> |
34 | | constexpr inline size_t assumed_bit_size = 0; |
35 | | template<> |
36 | | constexpr inline size_t assumed_bit_size<IntegerWrapper> = bit_width<int>; |
37 | | template<size_t bit_size> |
38 | | constexpr inline size_t assumed_bit_size<UFixedBigInt<bit_size>> = bit_size; |
39 | | template<BuiltInUFixedInt T> |
40 | | constexpr inline size_t assumed_bit_size<T> = bit_width<T>; |
41 | | |
42 | | template<typename T> |
43 | | concept ConvertibleToUFixedInt = (assumed_bit_size<T> != 0); |
44 | | |
45 | | template<typename T> |
46 | | concept UFixedInt = (ConvertibleToUFixedInt<T> && !IsSame<T, IntegerWrapper>); |
47 | | |
48 | | template<typename T> |
49 | | concept NotBuiltInUFixedInt = (UFixedInt<T> && !BuiltInUFixedInt<T>); |
50 | | |
51 | | // ===== UFixedBigInt itself ===== |
52 | | template<size_t bit_size> |
53 | 0 | constexpr auto& get_storage_of(UFixedBigInt<bit_size>& value) { return value.m_data; }Unexecuted instantiation: auto& AK::Detail::get_storage_of<4096ul>(AK::Detail::UFixedBigInt<4096ul, AK::Detail::StaticStorage<false, 4096ul> >&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<128ul>(AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> >&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<257ul>(AK::Detail::UFixedBigInt<257ul, AK::Detail::StaticStorage<false, 257ul> >&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<256ul>(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<385ul>(AK::Detail::UFixedBigInt<385ul, AK::Detail::StaticStorage<false, 385ul> >&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<384ul>(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >&) |
54 | | |
55 | | template<size_t bit_size> |
56 | 0 | constexpr auto& get_storage_of(UFixedBigInt<bit_size> const& value) { return value.m_data; }Unexecuted instantiation: auto& AK::Detail::get_storage_of<4096ul>(AK::Detail::UFixedBigInt<4096ul, AK::Detail::StaticStorage<false, 4096ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<128ul>(AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<256ul>(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<512ul>(AK::Detail::UFixedBigInt<512ul, AK::Detail::StaticStorage<false, 512ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<384ul>(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<768ul>(AK::Detail::UFixedBigInt<768ul, AK::Detail::StaticStorage<false, 768ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<257ul>(AK::Detail::UFixedBigInt<257ul, AK::Detail::StaticStorage<false, 257ul> > const&) Unexecuted instantiation: auto& AK::Detail::get_storage_of<385ul>(AK::Detail::UFixedBigInt<385ul, AK::Detail::StaticStorage<false, 385ul> > const&) |
57 | | |
58 | | template<typename Operand1, typename Operand2, typename Result> |
59 | | constexpr void mul_internal(Operand1 const& operand1, Operand2 const& operand2, Result& result) |
60 | 2.95M | { |
61 | 2.95M | StorageOperations<>::baseline_mul(operand1, operand2, result, g_null_allocator); |
62 | 2.95M | } void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 64ul>, AK::Detail::StaticStorage<false, 64ul>, AK::Detail::StaticStorage<false, 128ul> >(AK::Detail::StaticStorage<false, 64ul> const&, AK::Detail::StaticStorage<false, 64ul> const&, AK::Detail::StaticStorage<false, 128ul>&) Line | Count | Source | 60 | 2.95M | { | 61 | 2.95M | StorageOperations<>::baseline_mul(operand1, operand2, result, g_null_allocator); | 62 | 2.95M | } |
Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 4096ul>, AK::Detail::StaticStorage<false, 32ul>, AK::Detail::StaticStorage<false, 4096ul> >(AK::Detail::StaticStorage<false, 4096ul> const&, AK::Detail::StaticStorage<false, 32ul> const&, AK::Detail::StaticStorage<false, 4096ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 256ul>, AK::Detail::StaticStorage<false, 256ul>, AK::Detail::StaticStorage<false, 512ul> >(AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 512ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 256ul>, AK::Detail::StaticStorage<false, 256ul>, AK::Detail::StaticStorage<false, 256ul> >(AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 256ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 384ul>, AK::Detail::StaticStorage<false, 384ul>, AK::Detail::StaticStorage<false, 768ul> >(AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 768ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 384ul>, AK::Detail::StaticStorage<false, 384ul>, AK::Detail::StaticStorage<false, 384ul> >(AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 384ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 257ul>, AK::Detail::StaticStorage<false, 257ul>, AK::Detail::StaticStorage<false, 257ul> >(AK::Detail::StaticStorage<false, 257ul> const&, AK::Detail::StaticStorage<false, 257ul> const&, AK::Detail::StaticStorage<false, 257ul>&) Unexecuted instantiation: void AK::Detail::mul_internal<AK::Detail::StaticStorage<false, 385ul>, AK::Detail::StaticStorage<false, 385ul>, AK::Detail::StaticStorage<false, 385ul> >(AK::Detail::StaticStorage<false, 385ul> const&, AK::Detail::StaticStorage<false, 385ul> const&, AK::Detail::StaticStorage<false, 385ul>&) |
63 | | |
64 | | template<size_t dividend_size, size_t divisor_size, bool restore_remainder> |
65 | | constexpr void div_mod_internal( // Include AK/UFixedBigIntDivision.h to use UFixedBigInt division |
66 | | StaticStorage<false, dividend_size> const& dividend, |
67 | | StaticStorage<false, divisor_size> const& divisor, |
68 | | StaticStorage<false, dividend_size>& quotient, |
69 | | StaticStorage<false, divisor_size>& remainder); |
70 | | |
71 | | template<size_t bit_size, typename Storage> |
72 | | class UFixedBigInt { |
73 | | constexpr static size_t static_size = Storage::static_size; |
74 | | constexpr static size_t part_size = static_size / 2; |
75 | | using UFixedBigIntPart = Conditional<part_size * native_word_size <= 64, u64, UFixedBigInt<part_size * native_word_size>>; |
76 | | using Ops = StorageOperations<>; |
77 | | |
78 | | public: |
79 | | constexpr UFixedBigInt() = default; |
80 | | |
81 | | explicit constexpr UFixedBigInt(IntegerWrapper value) { Ops::copy(value.m_data, m_data); } |
82 | | consteval UFixedBigInt(int value) |
83 | | { |
84 | | Ops::copy(IntegerWrapper(value).m_data, m_data); |
85 | | } |
86 | | |
87 | | template<UFixedInt T> |
88 | | requires(sizeof(T) > sizeof(Storage)) explicit constexpr UFixedBigInt(T const& value) |
89 | 0 | { |
90 | 0 | Ops::copy(get_storage_of(value), m_data); |
91 | 0 | } Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEC2ITkNS0_9UFixedIntENS1_ILm512ENS2_ILb0ELm512EEEEEQgtstTL0__stT0_EERKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEC2ITkNS0_9UFixedIntENS1_ILm768ENS2_ILb0ELm768EEEEEQgtstTL0__stT0_EERKT_ |
92 | | |
93 | | template<UFixedInt T> |
94 | | requires(sizeof(T) <= sizeof(Storage)) constexpr UFixedBigInt(T const& value) |
95 | 2.95M | { |
96 | 2.95M | Ops::copy(get_storage_of(value), m_data); |
97 | 2.95M | } _ZN2AK6Detail12UFixedBigIntILm64ENS0_13StaticStorageILb0ELm64EEEEC2ITkNS0_9UFixedIntEmQlestTL0__stT0_EERKT_ Line | Count | Source | 95 | 2.95M | { | 96 | 2.95M | Ops::copy(get_storage_of(value), m_data); | 97 | 2.95M | } |
Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEC2ITkNS0_9UFixedIntEjQlestTL0__stT0_EERKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEC2ITkNS0_9UFixedIntEbQlestTL0__stT0_EERKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEC2ITkNS0_9UFixedIntEjQlestTL0__stT0_EERKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEC2ITkNS0_9UFixedIntEbQlestTL0__stT0_EERKT_ |
98 | | |
99 | | constexpr UFixedBigInt(UFixedBigIntPart const& low, UFixedBigIntPart const& high) |
100 | | requires(static_size % 2 == 0) |
101 | 0 | { |
102 | 0 | decltype(auto) low_storage = get_storage_of(low); |
103 | 0 | decltype(auto) high_storage = get_storage_of(high); |
104 | 0 | for (size_t i = 0; i < part_size; ++i) |
105 | 0 | m_data[i] = low_storage[i]; |
106 | 0 | for (size_t i = 0; i < part_size; ++i) |
107 | 0 | m_data[i + part_size] = high_storage[i]; |
108 | 0 | } |
109 | | |
110 | | template<UFixedInt T, size_t n> |
111 | | requires((assumed_bit_size<T> * n) <= bit_size) constexpr UFixedBigInt(T const (&value)[n]) |
112 | | { |
113 | | size_t offset = 0; |
114 | | |
115 | | for (size_t i = 0; i < n; ++i) { |
116 | | if (offset % native_word_size == 0) { |
117 | | // Aligned initialization (i. e. u256 from two u128) |
118 | | decltype(auto) storage = get_storage_of(value[i]); |
119 | | for (size_t i = 0; i < storage.size(); ++i) |
120 | | m_data[i + offset / native_word_size] = storage[i]; |
121 | | } else if (offset % native_word_size == 32 && IsSame<T, u32>) { |
122 | | // u32 vector initialization on 64-bit platforms |
123 | | m_data[offset / native_word_size] |= static_cast<NativeDoubleWord>(value[i]) << 32; |
124 | | } else { |
125 | | VERIFY_NOT_REACHED(); |
126 | | } |
127 | | offset += assumed_bit_size<T>; |
128 | | } |
129 | | |
130 | | for (size_t i = (offset + native_word_size - 1) / native_word_size; i < m_data.size(); ++i) |
131 | | m_data[i] = 0; |
132 | | } |
133 | | |
134 | | // Casts & parts extraction |
135 | | template<NotBuiltInUFixedInt T> |
136 | | constexpr explicit operator T() const |
137 | | { |
138 | | T result; |
139 | | Ops::copy(m_data, result.m_data); |
140 | | return result; |
141 | | } |
142 | | |
143 | | template<BuiltInUFixedInt T> |
144 | | requires(sizeof(T) <= sizeof(NativeWord)) constexpr explicit operator T() const |
145 | 0 | { |
146 | 0 | return m_data[0]; |
147 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEcvT_ITkNS0_16BuiltInUFixedIntEmQlestTL0__Lm8EEEv Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEcvT_ITkNS0_16BuiltInUFixedIntEhQlestTL0__Lm8EEEv |
148 | | |
149 | | template<BuiltInUFixedInt T> |
150 | | requires(sizeof(T) == sizeof(NativeDoubleWord)) constexpr explicit operator T() const |
151 | | { |
152 | | return (static_cast<NativeDoubleWord>(m_data[1]) << native_word_size) + m_data[0]; |
153 | | } |
154 | | |
155 | | constexpr UFixedBigIntPart low() const |
156 | | requires(static_size % 2 == 0) |
157 | 2.93M | { |
158 | 2.93M | if constexpr (part_size == 1) { |
159 | 2.93M | return m_data[0]; |
160 | | } else if constexpr (IsSame<UFixedBigIntPart, NativeDoubleWord>) { |
161 | | return m_data[0] + (static_cast<NativeDoubleWord>(m_data[1]) << native_word_size); |
162 | | } else { |
163 | | UFixedBigInt<part_size * native_word_size> result; |
164 | | Ops::copy(m_data, result.m_data); |
165 | | return result; |
166 | | } |
167 | 2.93M | } |
168 | | |
169 | | constexpr UFixedBigIntPart high() const |
170 | | requires(static_size % 2 == 0) |
171 | 3.64M | { |
172 | 3.64M | if constexpr (part_size == 1) { |
173 | 3.64M | return m_data[part_size]; |
174 | | } else if constexpr (IsSame<UFixedBigIntPart, NativeDoubleWord>) { |
175 | | return m_data[part_size] + (static_cast<NativeDoubleWord>(m_data[part_size + 1]) << native_word_size); |
176 | | } else { |
177 | | UFixedBigInt<part_size * native_word_size> result; |
178 | | Ops::copy(m_data, result.m_data, part_size); |
179 | | return result; |
180 | | } |
181 | 3.64M | } |
182 | | |
183 | | Bytes bytes() |
184 | | { |
185 | | return Bytes(reinterpret_cast<u8*>(this), sizeof(Storage)); |
186 | | } |
187 | | |
188 | | ReadonlyBytes bytes() const |
189 | | { |
190 | | return ReadonlyBytes(reinterpret_cast<u8 const*>(this), sizeof(Storage)); |
191 | | } |
192 | | |
193 | | constexpr UnsignedStorageSpan span() |
194 | 0 | { |
195 | 0 | return { m_data.data(), static_size }; |
196 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::span() Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::span() |
197 | | |
198 | | constexpr UnsignedStorageReadonlySpan span() const |
199 | 0 | { |
200 | 0 | return { m_data.data(), static_size }; |
201 | 0 | } |
202 | | |
203 | | // Binary utils |
204 | | constexpr size_t popcnt() const |
205 | | { |
206 | | size_t result = 0; |
207 | | for (size_t i = 0; i < m_data.size(); ++i) |
208 | | result += popcount(m_data[i]); |
209 | | return result; |
210 | | } |
211 | | |
212 | | constexpr size_t ctz() const |
213 | | { |
214 | | size_t result = 0; |
215 | | for (size_t i = 0; i < m_data.size(); ++i) { |
216 | | if (m_data[i]) { |
217 | | result += count_trailing_zeroes(m_data[i]); |
218 | | break; |
219 | | } else { |
220 | | result += native_word_size; |
221 | | } |
222 | | } |
223 | | return result; |
224 | | } |
225 | | |
226 | | constexpr size_t clz() const |
227 | 0 | { |
228 | 0 | size_t result = 0; |
229 | 0 | for (size_t i = m_data.size(); i--;) { |
230 | 0 | if (m_data[i]) { |
231 | 0 | result += count_leading_zeroes(m_data[i]); |
232 | 0 | break; |
233 | 0 | } else { |
234 | 0 | result += native_word_size; |
235 | 0 | } |
236 | 0 | } |
237 | 0 | return result + bit_size - native_word_size * static_size; |
238 | 0 | } |
239 | | |
240 | | // Comparisons |
241 | | constexpr bool operator!() const |
242 | | { |
243 | | bool result = true; |
244 | | for (size_t i = 0; i < m_data.size(); ++i) |
245 | | result &= !m_data[i]; |
246 | | return result; |
247 | | } |
248 | | |
249 | | constexpr explicit operator bool() const |
250 | | { |
251 | | bool result = false; |
252 | | for (size_t i = 0; i < m_data.size(); ++i) |
253 | | result |= m_data[i]; |
254 | | return result; |
255 | | } |
256 | | |
257 | | constexpr bool operator==(UFixedInt auto const& other) const |
258 | 0 | { |
259 | 0 | return Ops::compare(m_data, get_storage_of(other), true) == 0; |
260 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEeqITkNS0_9UFixedIntEjEEbRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEeqITkNS0_9UFixedIntEjEEbRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEeqITkNS0_9UFixedIntES4_EEbRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEeqITkNS0_9UFixedIntES4_EEbRKT_ |
261 | | |
262 | | constexpr bool operator==(IntegerWrapper other) const |
263 | 0 | { |
264 | 0 | return Ops::compare(m_data, get_storage_of(other), true) == 0; |
265 | 0 | } |
266 | | |
267 | | constexpr int operator<=>(UFixedInt auto const& other) const |
268 | 0 | { |
269 | 0 | return Ops::compare(m_data, get_storage_of(other), false); |
270 | 0 | } |
271 | | |
272 | | constexpr int operator<=>(IntegerWrapper other) const |
273 | | { |
274 | | return Ops::compare(m_data, get_storage_of(other), false); |
275 | | } |
276 | | |
277 | | #define DEFINE_STANDARD_BINARY_OPERATOR(op, function) \ |
278 | | constexpr auto operator op(UFixedInt auto const& other) const \ |
279 | 2.73M | { \ |
280 | 2.73M | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \_ZZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEplITkNS0_9UFixedIntEmEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm64EEERS3_EEDaS9_SB_SD_ Line | Count | Source | 280 | 2.73M | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \ |
Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEEmlITkNS0_9UFixedIntEjEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm32EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEorITkNS0_9UFixedIntEhEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm8EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEplITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEanITkNS0_9UFixedIntEjEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm32EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEplITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEanITkNS0_9UFixedIntEjEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm32EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmiITkNS0_9UFixedIntEjEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm32EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmiITkNS0_9UFixedIntEjEEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_NS2_ILb0ELm32EEERS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEeoITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ Unexecuted instantiation: _ZZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ENKUlOS6_OT0_OT1_E_clIRKS3_SH_RS3_EEDaS9_SB_SD_ |
281 | 2.73M | return do_standard_binary_operation(other, func); \ |
282 | 2.73M | } \ _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEplITkNS0_9UFixedIntEmEEDaRKT_ Line | Count | Source | 279 | 2.73M | { \ | 280 | 2.73M | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \ | 281 | 2.73M | return do_standard_binary_operation(other, func); \ | 282 | 2.73M | } \ |
Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEEmlITkNS0_9UFixedIntEjEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEorITkNS0_9UFixedIntEhEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEplITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEanITkNS0_9UFixedIntEjEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEplITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEanITkNS0_9UFixedIntEjEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEmiITkNS0_9UFixedIntEjEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEEmlITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEEmiITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEmiITkNS0_9UFixedIntEjEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEeoITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEanITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEorITkNS0_9UFixedIntES4_EEDaRKT_ |
283 | | \ |
284 | | constexpr auto operator op(IntegerWrapper other) const \ |
285 | 0 | { \ |
286 | 0 | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \Unexecuted instantiation: auto AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator-(AK::Detail::IntegerWrapper) const::{lambda(auto:1&&, auto:2&&, auto:3&&)#1}::operator()<AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 32ul>, AK::Detail::StaticStorage<false, 256ul>&>(AK::Detail::StaticStorage<false, 256ul> const&, AK::Detail::StaticStorage<false, 32ul>&&, AK::Detail::StaticStorage<false, 256ul>&) constUnexecuted instantiation: auto AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator-(AK::Detail::IntegerWrapper) const::{lambda(auto:1&&, auto:2&&, auto:3&&)#1}::operator()<AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 32ul>, AK::Detail::StaticStorage<false, 384ul>&>(AK::Detail::StaticStorage<false, 384ul> const&, AK::Detail::StaticStorage<false, 32ul>&&, AK::Detail::StaticStorage<false, 384ul>&) const |
287 | 0 | return do_standard_binary_operation(other, func); \ |
288 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator-(AK::Detail::IntegerWrapper) const Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator-(AK::Detail::IntegerWrapper) const |
289 | | |
290 | | #define DEFINE_STANDARD_COMPOUND_ASSIGNMENT(op, function) \ |
291 | | constexpr auto& operator op(UFixedInt auto const& other) \ |
292 | 11.6k | { \ |
293 | 11.6k | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \_ZZN2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEpLITkNS0_9UFixedIntEmEERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_NS2_ILb0ELm64EEESH_EEDaSA_SC_SE_ Line | Count | Source | 293 | 11.6k | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \ |
Unexecuted instantiation: _ZZN2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEEpLITkNS0_9UFixedIntEjEERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_NS2_ILb0ELm32EEESH_EEDaSA_SC_SE_ Unexecuted instantiation: _ZZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEoRITkNS0_9UFixedIntES4_EERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_RKS3_SH_EEDaSA_SC_SE_ Unexecuted instantiation: _ZZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEoRITkNS0_9UFixedIntEhEERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_NS2_ILb0ELm8EEESH_EEDaSA_SC_SE_ Unexecuted instantiation: _ZZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEoRITkNS0_9UFixedIntES4_EERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_RKS3_SH_EEDaSA_SC_SE_ Unexecuted instantiation: _ZZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEoRITkNS0_9UFixedIntEhEERDaRKT_ENKUlOS7_OT0_OT1_E_clIRS3_NS2_ILb0ELm8EEESH_EEDaSA_SC_SE_ |
294 | 11.6k | do_standard_compound_assignment(other, func); \ |
295 | 11.6k | return *this; \ |
296 | 11.6k | } \ _ZN2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEEpLITkNS0_9UFixedIntEmEERDaRKT_ Line | Count | Source | 292 | 11.6k | { \ | 293 | 11.6k | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \ | 294 | 11.6k | do_standard_compound_assignment(other, func); \ | 295 | 11.6k | return *this; \ | 296 | 11.6k | } \ |
Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEEpLITkNS0_9UFixedIntEjEERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEoRITkNS0_9UFixedIntES4_EERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEoRITkNS0_9UFixedIntEhEERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEoRITkNS0_9UFixedIntES4_EERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEoRITkNS0_9UFixedIntEhEERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEEoRITkNS0_9UFixedIntEjEERDaRKT_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEEoRITkNS0_9UFixedIntEjEERDaRKT_ |
297 | | \ |
298 | | constexpr auto& operator op(IntegerWrapper other) \ |
299 | | { \ |
300 | | auto func = [](auto&& a, auto&& b, auto&& c) { function(a, b, c); }; \ |
301 | | do_standard_compound_assignment(other, func); \ |
302 | | return *this; \ |
303 | | } |
304 | | |
305 | | // Binary operators |
306 | | DEFINE_STANDARD_BINARY_OPERATOR(^, Ops::compute_bitwise<Ops::Bitwise::XOR>) |
307 | | DEFINE_STANDARD_BINARY_OPERATOR(&, Ops::compute_bitwise<Ops::Bitwise::AND>) |
308 | | DEFINE_STANDARD_BINARY_OPERATOR(|, Ops::compute_bitwise<Ops::Bitwise::OR>) |
309 | | DEFINE_STANDARD_COMPOUND_ASSIGNMENT(^=, Ops::compute_inplace_bitwise<Ops::Bitwise::XOR>) |
310 | | DEFINE_STANDARD_COMPOUND_ASSIGNMENT(&=, Ops::compute_inplace_bitwise<Ops::Bitwise::AND>) |
311 | | DEFINE_STANDARD_COMPOUND_ASSIGNMENT(|=, Ops::compute_inplace_bitwise<Ops::Bitwise::OR>) |
312 | | |
313 | | constexpr auto operator~() const |
314 | 0 | { |
315 | 0 | UFixedBigInt<bit_size> result; |
316 | 0 | Ops::compute_bitwise<Ops::Bitwise::INVERT>(m_data, m_data, result.m_data); |
317 | 0 | return result; |
318 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator~() const Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator~() const Unexecuted instantiation: AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> >::operator~() const |
319 | | |
320 | | constexpr auto operator<<(size_t shift) const |
321 | 0 | { |
322 | 0 | UFixedBigInt<bit_size> result; |
323 | 0 | Ops::shift_left(m_data, shift, result.m_data); |
324 | 0 | return result; |
325 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<4096ul, AK::Detail::StaticStorage<false, 4096ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<257ul, AK::Detail::StaticStorage<false, 257ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<513ul, AK::Detail::StaticStorage<false, 513ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<385ul, AK::Detail::StaticStorage<false, 385ul> >::operator<<(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<769ul, AK::Detail::StaticStorage<false, 769ul> >::operator<<(unsigned long) const |
326 | | |
327 | | constexpr auto& operator<<=(size_t shift) |
328 | 0 | { |
329 | 0 | Ops::shift_left(m_data, shift, m_data); |
330 | 0 | return *this; |
331 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<4096ul, AK::Detail::StaticStorage<false, 4096ul> >::operator<<=(unsigned long) Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator<<=(unsigned long) Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator<<=(unsigned long) |
332 | | |
333 | | constexpr auto operator>>(size_t shift) const |
334 | 0 | { |
335 | 0 | UFixedBigInt<bit_size> result; |
336 | 0 | Ops::shift_right(m_data, shift, result.m_data); |
337 | 0 | return result; |
338 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> >::operator>>(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<512ul, AK::Detail::StaticStorage<false, 512ul> >::operator>>(unsigned long) const Unexecuted instantiation: AK::Detail::UFixedBigInt<768ul, AK::Detail::StaticStorage<false, 768ul> >::operator>>(unsigned long) const |
339 | | |
340 | | constexpr auto& operator>>=(size_t shift) |
341 | 0 | { |
342 | 0 | Ops::shift_right(m_data, shift, m_data); |
343 | 0 | return *this; |
344 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<4096ul, AK::Detail::StaticStorage<false, 4096ul> >::operator>>=(unsigned long) Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::operator>>=(unsigned long) Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::operator>>=(unsigned long) |
345 | | |
346 | | // Arithmetic |
347 | | template<UFixedInt T> |
348 | | constexpr auto addc(T const& other, bool& carry) const |
349 | 0 | { |
350 | 0 | UFixedBigInt<max(bit_size, assumed_bit_size<T>)> result; |
351 | 0 | carry = Ops::add<false>(m_data, get_storage_of(other), result.m_data, carry); |
352 | 0 | return result; |
353 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE4addcITkNS0_9UFixedIntES4_EEDaRKT_Rb Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE4addcITkNS0_9UFixedIntES4_EEDaRKT_Rb |
354 | | |
355 | | template<UFixedInt T> |
356 | | constexpr auto subc(T const& other, bool& borrow) const |
357 | 0 | { |
358 | 0 | UFixedBigInt<max(bit_size, assumed_bit_size<T>)> result; |
359 | 0 | borrow = Ops::add<true>(m_data, get_storage_of(other), result.m_data, borrow); |
360 | 0 | return result; |
361 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE4subcITkNS0_9UFixedIntES4_EEDaRKT_Rb Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE4subcITkNS0_9UFixedIntES4_EEDaRKT_Rb |
362 | | |
363 | | DEFINE_STANDARD_BINARY_OPERATOR(+, Ops::add<false>) |
364 | | DEFINE_STANDARD_BINARY_OPERATOR(-, Ops::add<true>) |
365 | | DEFINE_STANDARD_COMPOUND_ASSIGNMENT(+=, Ops::add<false>) |
366 | | DEFINE_STANDARD_COMPOUND_ASSIGNMENT(-=, Ops::add<true>) |
367 | | |
368 | | constexpr auto& operator++() |
369 | | { |
370 | | Ops::increment<false>(m_data); |
371 | | return *this; |
372 | | } |
373 | | |
374 | | constexpr auto& operator--() |
375 | | { |
376 | | Ops::increment<true>(m_data); |
377 | | return *this; |
378 | | } |
379 | | |
380 | | constexpr auto operator++(int) |
381 | | { |
382 | | UFixedBigInt<bit_size> result = *this; |
383 | | Ops::increment<false>(m_data); |
384 | | return result; |
385 | | } |
386 | | |
387 | | constexpr auto operator--(int) |
388 | | { |
389 | | UFixedBigInt<bit_size> result = *this; |
390 | | Ops::increment<true>(m_data); |
391 | | return result; |
392 | | } |
393 | | |
394 | | DEFINE_STANDARD_BINARY_OPERATOR(*, mul_internal) |
395 | | |
396 | 0 | constexpr auto& operator*=(UFixedInt auto const& other) { return *this = *this * other; } |
397 | | constexpr auto& operator*=(IntegerWrapper const& other) { return *this = *this * other; } |
398 | | |
399 | | template<UFixedInt T> |
400 | | constexpr auto wide_multiply(T const& other) const |
401 | 2.95M | { |
402 | 2.95M | UFixedBigInt<bit_size + assumed_bit_size<T>> result; |
403 | 2.95M | mul_internal(m_data, get_storage_of(other), result.m_data); |
404 | 2.95M | return result; |
405 | 2.95M | } _ZNK2AK6Detail12UFixedBigIntILm64ENS0_13StaticStorageILb0ELm64EEEE13wide_multiplyITkNS0_9UFixedIntEmEEDaRKT_ Line | Count | Source | 401 | 2.95M | { | 402 | 2.95M | UFixedBigInt<bit_size + assumed_bit_size<T>> result; | 403 | 2.95M | mul_internal(m_data, get_storage_of(other), result.m_data); | 404 | 2.95M | return result; | 405 | 2.95M | } |
Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE13wide_multiplyITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE13wide_multiplyITkNS0_9UFixedIntES4_EEDaRKT_ |
406 | | |
407 | | template<NotBuiltInUFixedInt T> |
408 | | constexpr UFixedBigInt<bit_size> div_mod(T const& divisor, T& remainder) const |
409 | 0 | { |
410 | 0 | UFixedBigInt<bit_size> quotient; |
411 | 0 | UFixedBigInt<assumed_bit_size<T>> resulting_remainder; |
412 | 0 | div_mod_internal<bit_size, assumed_bit_size<T>, true>(m_data, get_storage_of(divisor), get_storage_of(quotient), get_storage_of(resulting_remainder)); |
413 | 0 | remainder = resulting_remainder; |
414 | 0 | return quotient; |
415 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEE7div_modITkNS0_19NotBuiltInUFixedIntES4_EES4_RKT_RS6_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEE7div_modITkNS0_19NotBuiltInUFixedIntES4_EES4_RKT_RS6_ |
416 | | |
417 | | template<UFixedInt T> |
418 | | constexpr auto operator/(T const& other) const |
419 | 0 | { |
420 | 0 | UFixedBigInt<bit_size> quotient; |
421 | 0 | StaticStorage<false, assumed_bit_size<T>> remainder; // unused |
422 | 0 | div_mod_internal<bit_size, assumed_bit_size<T>, false>(m_data, get_storage_of(other), get_storage_of(quotient), remainder); |
423 | 0 | return quotient; |
424 | 0 | } |
425 | | |
426 | | template<UFixedInt T> |
427 | | constexpr auto operator%(T const& other) const |
428 | 0 | { |
429 | 0 | StaticStorage<false, bit_size> quotient; // unused |
430 | 0 | UFixedBigInt<assumed_bit_size<T>> remainder; |
431 | 0 | div_mod_internal<bit_size, assumed_bit_size<T>, true>(m_data, get_storage_of(other), quotient, get_storage_of(remainder)); |
432 | 0 | return remainder; |
433 | 0 | } Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEErmITkNS0_9UFixedIntES4_EEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm513ENS0_13StaticStorageILb0ELm513EEEErmITkNS0_9UFixedIntENS1_ILm256ENS2_ILb0ELm256EEEEEEEDaRKT_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm769ENS0_13StaticStorageILb0ELm769EEEErmITkNS0_9UFixedIntENS1_ILm384ENS2_ILb0ELm384EEEEEEEDaRKT_ |
434 | | |
435 | | constexpr auto operator/(IntegerWrapper const& other) const { return *this / static_cast<UFixedBigInt<32>>(other); } |
436 | | constexpr auto operator%(IntegerWrapper const& other) const { return *this % static_cast<UFixedBigInt<32>>(other); } |
437 | | |
438 | | template<UFixedInt T> |
439 | 0 | constexpr auto& operator/=(T const& other) { return *this = *this / other; } |
440 | | constexpr auto& operator/=(IntegerWrapper const& other) { return *this = *this / other; } |
441 | | |
442 | | template<Unsigned U> |
443 | 0 | constexpr auto& operator%=(U const& other) { return *this = *this % other; } |
444 | | constexpr auto& operator%=(IntegerWrapper const& other) { return *this = *this % other; } |
445 | | |
446 | | // Note: If there ever be need for non side-channel proof sqrt/pow/pow_mod of UFixedBigInt, you |
447 | | // can restore them from Git history. |
448 | | |
449 | | #undef DEFINE_STANDARD_BINARY_OPERATOR |
450 | | #undef DEFINE_STANDARD_COMPOUND_ASSIGNMENT |
451 | | |
452 | | // These functions are intended to be used in LibCrypto for equality checks without branching. |
453 | | constexpr bool is_zero_constant_time() const |
454 | 0 | { |
455 | 0 | NativeWord fold = 0; |
456 | 0 | for (size_t i = 0; i < m_data.size(); ++i) |
457 | 0 | taint_for_optimizer(fold |= m_data[i]); |
458 | 0 | return !fold; |
459 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::is_zero_constant_time() const Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::is_zero_constant_time() const Unexecuted instantiation: AK::Detail::UFixedBigInt<257ul, AK::Detail::StaticStorage<false, 257ul> >::is_zero_constant_time() const Unexecuted instantiation: AK::Detail::UFixedBigInt<385ul, AK::Detail::StaticStorage<false, 385ul> >::is_zero_constant_time() const |
460 | | |
461 | | constexpr bool is_equal_to_constant_time(UFixedBigInt<bit_size> other) const |
462 | 0 | { |
463 | 0 | NativeWord fold = 0; |
464 | 0 | for (size_t i = 0; i < m_data.size(); ++i) |
465 | 0 | taint_for_optimizer(fold |= m_data[i] ^ other.m_data[i]); |
466 | 0 | return !fold; |
467 | 0 | } Unexecuted instantiation: AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >::is_equal_to_constant_time(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >) const Unexecuted instantiation: AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >::is_equal_to_constant_time(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >) const |
468 | | |
469 | | private: |
470 | | template<ConvertibleToUFixedInt T, typename Function> |
471 | | constexpr auto do_standard_binary_operation(T const& other, Function function) const |
472 | 2.73M | { |
473 | 2.73M | UFixedBigInt<max(bit_size, assumed_bit_size<T>)> result; |
474 | 2.73M | function(m_data, get_storage_of(other), result.m_data); |
475 | 2.73M | return result; |
476 | 2.73M | } _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEmZNKS4_plITkNS0_9UFixedIntEmEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Line | Count | Source | 472 | 2.73M | { | 473 | 2.73M | UFixedBigInt<max(bit_size, assumed_bit_size<T>)> result; | 474 | 2.73M | function(m_data, get_storage_of(other), result.m_data); | 475 | 2.73M | return result; | 476 | 2.73M | } |
Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEjZNKS4_mlITkNS0_9UFixedIntEjEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEhZNKS4_orITkNS0_9UFixedIntEhEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_mlITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_plITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_miITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEjZNKS4_anITkNS0_9UFixedIntEjEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntENS0_14IntegerWrapperEZNKS4_miES6_EUlOT_OT0_OT1_E_EEDaRKS7_S9_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_anITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_orITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_mlITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_plITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_miITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEjZNKS4_anITkNS0_9UFixedIntEjEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntENS0_14IntegerWrapperEZNKS4_miES6_EUlOT_OT0_OT1_E_EEDaRKS7_S9_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_anITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_orITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_mlITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm257ENS0_13StaticStorageILb0ELm257EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_miITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEjZNKS4_miITkNS0_9UFixedIntEjEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_mlITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm385ENS0_13StaticStorageILb0ELm385EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_miITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntEjZNKS4_miITkNS0_9UFixedIntEjEEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_eoITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_anITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ Unexecuted instantiation: _ZNK2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE28do_standard_binary_operationITkNS0_22ConvertibleToUFixedIntES4_ZNKS4_orITkNS0_9UFixedIntES4_EEDaRKT_EUlOS7_OT0_OT1_E_EEDaS9_SB_ |
477 | | |
478 | | template<ConvertibleToUFixedInt T, typename Function> |
479 | | constexpr void do_standard_compound_assignment(T const& other, Function function) |
480 | 11.6k | { |
481 | 11.6k | static_assert(bit_size >= assumed_bit_size<T>, "Requested operation requires integer size to be expanded."); |
482 | 11.6k | function(m_data, get_storage_of(other), m_data); |
483 | 11.6k | } _ZN2AK6Detail12UFixedBigIntILm128ENS0_13StaticStorageILb0ELm128EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEmZNS4_pLITkNS0_9UFixedIntEmEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Line | Count | Source | 480 | 11.6k | { | 481 | 11.6k | static_assert(bit_size >= assumed_bit_size<T>, "Requested operation requires integer size to be expanded."); | 482 | 11.6k | function(m_data, get_storage_of(other), m_data); | 483 | 11.6k | } |
Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm4096ENS0_13StaticStorageILb0ELm4096EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEjZNS4_pLITkNS0_9UFixedIntEjEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntES4_ZNS4_oRITkNS0_9UFixedIntES4_EERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEhZNS4_oRITkNS0_9UFixedIntEhEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntES4_ZNS4_oRITkNS0_9UFixedIntES4_EERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEhZNS4_oRITkNS0_9UFixedIntEhEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm256ENS0_13StaticStorageILb0ELm256EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEjZNS4_oRITkNS0_9UFixedIntEjEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ Unexecuted instantiation: _ZN2AK6Detail12UFixedBigIntILm384ENS0_13StaticStorageILb0ELm384EEEE31do_standard_compound_assignmentITkNS0_22ConvertibleToUFixedIntEjZNS4_oRITkNS0_9UFixedIntEjEERDaRKT_EUlOS8_OT0_OT1_E_EEvSA_SC_ |
484 | | |
485 | | template<size_t other_bit_size, typename OtherStorage> |
486 | | friend class UFixedBigInt; |
487 | | |
488 | | friend constexpr auto& get_storage_of<bit_size>(UFixedBigInt<bit_size>&); |
489 | | friend constexpr auto& get_storage_of<bit_size>(UFixedBigInt<bit_size> const&); |
490 | | |
491 | | Storage m_data; |
492 | | }; |
493 | | |
494 | | // FIXME: There is a bug in LLVM (https://github.com/llvm/llvm-project/issues/59783) which doesn't |
495 | | // allow to use the following comparisons. |
496 | | bool operator==(BuiltInUFixedInt auto const& a, NotBuiltInUFixedInt auto const& b) { return b.operator==(a); } |
497 | | int operator<=>(BuiltInUFixedInt auto const& a, NotBuiltInUFixedInt auto const& b) { return -b.operator<=>(a); } |
498 | | bool operator==(IntegerWrapper const& a, NotBuiltInUFixedInt auto const& b) { return b.operator==(a); } |
499 | | int operator<=>(IntegerWrapper const& a, NotBuiltInUFixedInt auto const& b) { return -b.operator<=>(a); } |
500 | | } |
501 | | |
502 | | using Detail::UFixedBigInt; |
503 | | |
504 | | template<size_t bit_size> |
505 | | constexpr inline bool IsUnsigned<UFixedBigInt<bit_size>> = true; |
506 | | template<size_t bit_size> |
507 | | constexpr inline bool IsSigned<UFixedBigInt<bit_size>> = false; |
508 | | |
509 | | template<size_t bit_size> |
510 | | struct NumericLimits<UFixedBigInt<bit_size>> { |
511 | | using T = UFixedBigInt<bit_size>; |
512 | | |
513 | | static constexpr T min() { return T {}; } |
514 | | static constexpr T max() { return --T {}; } |
515 | | static constexpr bool is_signed() { return false; } |
516 | | }; |
517 | | |
518 | | template<size_t N> |
519 | | class LittleEndian<UFixedBigInt<N>> { |
520 | | template<size_t M> |
521 | | constexpr static auto byte_swap_if_not_little_endian(UFixedBigInt<M> value) |
522 | 361 | { |
523 | 361 | if constexpr (HostIsLittleEndian) { |
524 | 361 | return value; |
525 | | } else { |
526 | | auto words = value.span(); |
527 | | auto front_it = words.begin(); |
528 | | auto ending_half_words = words.slice(ceil_div(words.size(), static_cast<size_t>(2))); |
529 | | for (size_t i = 0; i < ending_half_words.size(); ++i, ++front_it) |
530 | | *front_it = convert_between_host_and_little_endian(exchange(ending_half_words[ending_half_words.size() - i - 1], convert_between_host_and_little_endian(*front_it))); |
531 | | if (words.size() % 2) |
532 | | words[words.size() / 2] = convert_between_host_and_little_endian(*front_it); |
533 | | return value; |
534 | | } |
535 | 361 | } |
536 | | |
537 | | public: |
538 | | constexpr LittleEndian() = default; |
539 | | |
540 | | constexpr LittleEndian(UFixedBigInt<N> value) |
541 | 0 | : m_value(byte_swap_if_not_little_endian(value)) |
542 | 0 | { |
543 | 0 | } |
544 | | |
545 | 361 | constexpr operator UFixedBigInt<N>() const { return byte_swap_if_not_little_endian(m_value); } |
546 | | |
547 | | private: |
548 | | UFixedBigInt<N> m_value { 0 }; |
549 | | }; |
550 | | |
551 | | template<size_t N> |
552 | | class BigEndian<UFixedBigInt<N>> { |
553 | | template<size_t M> |
554 | | constexpr static auto byte_swap_if_not_big_endian(UFixedBigInt<M> value) |
555 | 0 | { |
556 | | if constexpr (!HostIsLittleEndian) { |
557 | | return value; |
558 | 0 | } else { |
559 | 0 | auto words = value.span(); |
560 | 0 | auto front_it = words.begin(); |
561 | 0 | auto ending_half_words = words.slice(ceil_div(words.size(), static_cast<size_t>(2))); |
562 | 0 | for (size_t i = 0; i < ending_half_words.size(); ++i, ++front_it) |
563 | 0 | *front_it = convert_between_host_and_big_endian(exchange(ending_half_words[ending_half_words.size() - i - 1], convert_between_host_and_big_endian(*front_it))); |
564 | 0 | if (words.size() % 2) |
565 | 0 | words[words.size() / 2] = convert_between_host_and_big_endian(*front_it); |
566 | 0 | return value; |
567 | 0 | } |
568 | 0 | } Unexecuted instantiation: auto AK::BigEndian<AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > >::byte_swap_if_not_big_endian<256ul>(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >) Unexecuted instantiation: auto AK::BigEndian<AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > >::byte_swap_if_not_big_endian<384ul>(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >) |
569 | | |
570 | | public: |
571 | | constexpr BigEndian() = default; |
572 | | |
573 | | constexpr BigEndian(UFixedBigInt<N> value) |
574 | 0 | : m_value(byte_swap_if_not_big_endian(value)) |
575 | 0 | { |
576 | 0 | } Unexecuted instantiation: AK::BigEndian<AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > >::BigEndian(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >) Unexecuted instantiation: AK::BigEndian<AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > >::BigEndian(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >) |
577 | | |
578 | 0 | constexpr operator UFixedBigInt<N>() const { return byte_swap_if_not_big_endian(m_value); }Unexecuted instantiation: AK::BigEndian<AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > >::operator AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >() const Unexecuted instantiation: AK::BigEndian<AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > >::operator AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >() const |
579 | | |
580 | | private: |
581 | | UFixedBigInt<N> m_value { 0 }; |
582 | | }; |
583 | | |
584 | | template<size_t M> |
585 | | struct Traits<UFixedBigInt<M>> : public DefaultTraits<UFixedBigInt<M>> { |
586 | 0 | static constexpr bool is_trivially_serializable() { return true; }Unexecuted instantiation: AK::Traits<AK::Detail::UFixedBigInt<128ul, AK::Detail::StaticStorage<false, 128ul> > >::is_trivially_serializable() Unexecuted instantiation: AK::Traits<AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > >::is_trivially_serializable() Unexecuted instantiation: AK::Traits<AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > >::is_trivially_serializable() |
587 | | static constexpr bool is_trivial() { return true; } |
588 | | }; |
589 | | |
590 | | // ===== Formatting ===== |
591 | | // FIXME: This does not work for size != 2 ** x |
592 | | template<Detail::NotBuiltInUFixedInt T> |
593 | | struct Formatter<T> : StandardFormatter { |
594 | 0 | Formatter() = default; |
595 | | explicit Formatter(StandardFormatter formatter) |
596 | | : StandardFormatter(formatter) |
597 | | { |
598 | | } |
599 | | |
600 | | ErrorOr<void> format(FormatBuilder& builder, T const& value) |
601 | 0 | { |
602 | 0 | using U = decltype(value.low()); |
603 | |
|
604 | 0 | if (m_precision.has_value()) |
605 | 0 | VERIFY_NOT_REACHED(); |
606 | | |
607 | 0 | if (m_mode == Mode::Pointer) { |
608 | | // these are way to big for a pointer |
609 | 0 | VERIFY_NOT_REACHED(); |
610 | 0 | } |
611 | 0 | if (m_mode == Mode::Default) |
612 | 0 | m_mode = Mode::Hexadecimal; |
613 | |
|
614 | 0 | if (!value.high()) { |
615 | 0 | Formatter<U> formatter { *this }; |
616 | 0 | return formatter.format(builder, value.low()); |
617 | 0 | } |
618 | | |
619 | 0 | u8 base = 0; |
620 | 0 | if (m_mode == Mode::Binary) { |
621 | 0 | base = 2; |
622 | 0 | } else if (m_mode == Mode::BinaryUppercase) { |
623 | 0 | base = 2; |
624 | 0 | } else if (m_mode == Mode::Octal) { |
625 | 0 | TODO(); |
626 | 0 | } else if (m_mode == Mode::Decimal) { |
627 | 0 | TODO(); |
628 | 0 | } else if (m_mode == Mode::Hexadecimal) { |
629 | 0 | base = 16; |
630 | 0 | } else if (m_mode == Mode::HexadecimalUppercase) { |
631 | 0 | base = 16; |
632 | 0 | } else { |
633 | 0 | VERIFY_NOT_REACHED(); |
634 | 0 | } |
635 | 0 | ssize_t width = m_width.value_or(0); |
636 | 0 | ssize_t lower_length = ceil_div(Detail::assumed_bit_size<U>, (ssize_t)base); |
637 | 0 | Formatter<U> formatter { *this }; |
638 | 0 | formatter.m_width = max(width - lower_length, (ssize_t)0); |
639 | 0 | TRY(formatter.format(builder, value.high())); |
640 | 0 | TRY(builder.put_literal("'"sv)); |
641 | 0 | formatter.m_zero_pad = true; |
642 | 0 | formatter.m_alternative_form = false; |
643 | 0 | formatter.m_width = lower_length; |
644 | 0 | TRY(formatter.format(builder, value.low())); |
645 | 0 | return {}; |
646 | 0 | } |
647 | | }; |
648 | | } |
649 | | |
650 | | // these sizes should suffice for most usecases |
651 | | using u128 = AK::UFixedBigInt<128>; |
652 | | using u256 = AK::UFixedBigInt<256>; |
653 | | using u384 = AK::UFixedBigInt<384>; |
654 | | using u512 = AK::UFixedBigInt<512>; |
655 | | using u768 = AK::UFixedBigInt<768>; |
656 | | using u1024 = AK::UFixedBigInt<1024>; |
657 | | using u1536 = AK::UFixedBigInt<1536>; |
658 | | using u2048 = AK::UFixedBigInt<2048>; |
659 | | using u4096 = AK::UFixedBigInt<4096>; |