Lbug C++ API
Loading...
Searching...
No Matches
uint128_t.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <string>
5
6#include "api.h"
7#include "overflow.h"
8#include "types.h"
9
10namespace lbug {
11namespace common {
12
13struct int128_t;
14
16 uint64_t low;
17 uint64_t high;
18
19 uint128_t() noexcept = default;
20 uint128_t(int64_t value); // NOLINT: Allow implicit conversion from numeric values
21 uint128_t(int32_t value); // NOLINT: Allow implicit conversion from numeric values
22 uint128_t(int16_t value); // NOLINT: Allow implicit conversion from numeric values
23 uint128_t(int8_t value); // NOLINT: Allow implicit conversion from numeric values
24 uint128_t(uint64_t value); // NOLINT: Allow implicit conversion from numeric values
25 uint128_t(uint32_t value); // NOLINT: Allow implicit conversion from numeric values
26 uint128_t(uint16_t value); // NOLINT: Allow implicit conversion from numeric values
27 uint128_t(uint8_t value); // NOLINT: Allow implicit conversion from numeric values
28 uint128_t(double value); // NOLINT: Allow implicit conversion from numeric values
29 uint128_t(float value); // NOLINT: Allow implicit conversion from numeric values
30
31 constexpr uint128_t(uint64_t low, uint64_t high) noexcept : low(low), high(high) {}
32
33 constexpr uint128_t(const uint128_t&) noexcept = default;
34 constexpr uint128_t(uint128_t&&) noexcept = default;
35 uint128_t& operator=(const uint128_t&) noexcept = default;
36 uint128_t& operator=(uint128_t&&) noexcept = default;
37
38 uint128_t operator-() const;
39
40 // inplace arithmetic operators
41 uint128_t& operator+=(const uint128_t& rhs);
42 uint128_t& operator*=(const uint128_t& rhs);
43 uint128_t& operator|=(const uint128_t& rhs);
44 uint128_t& operator&=(const uint128_t& rhs);
45
46 // cast operators
47 explicit operator int64_t() const;
48 explicit operator int32_t() const;
49 explicit operator int16_t() const;
50 explicit operator int8_t() const;
51 explicit operator uint64_t() const;
52 explicit operator uint32_t() const;
53 explicit operator uint16_t() const;
54 explicit operator uint8_t() const;
55 explicit operator double() const;
56 explicit operator float() const;
57
58 operator int128_t() const; // NOLINT: Allow implicit conversion from uint128 to int128
59};
60
61// arithmetic operators
62LBUG_API uint128_t operator+(const uint128_t& lhs, const uint128_t& rhs);
63LBUG_API uint128_t operator-(const uint128_t& lhs, const uint128_t& rhs);
64LBUG_API uint128_t operator*(const uint128_t& lhs, const uint128_t& rhs);
65LBUG_API uint128_t operator/(const uint128_t& lhs, const uint128_t& rhs);
66LBUG_API uint128_t operator%(const uint128_t& lhs, const uint128_t& rhs);
67LBUG_API uint128_t operator^(const uint128_t& lhs, const uint128_t& rhs);
68LBUG_API uint128_t operator&(const uint128_t& lhs, const uint128_t& rhs);
69LBUG_API uint128_t operator~(const uint128_t& val);
70LBUG_API uint128_t operator|(const uint128_t& lhs, const uint128_t& rhs);
71LBUG_API uint128_t operator<<(const uint128_t& lhs, int amount);
72LBUG_API uint128_t operator>>(const uint128_t& lhs, int amount);
73
74// comparison operators
75LBUG_API bool operator==(const uint128_t& lhs, const uint128_t& rhs);
76LBUG_API bool operator!=(const uint128_t& lhs, const uint128_t& rhs);
77LBUG_API bool operator>(const uint128_t& lhs, const uint128_t& rhs);
78LBUG_API bool operator>=(const uint128_t& lhs, const uint128_t& rhs);
79LBUG_API bool operator<(const uint128_t& lhs, const uint128_t& rhs);
80LBUG_API bool operator<=(const uint128_t& lhs, const uint128_t& rhs);
81
82class UInt128_t {
83public:
84 static std::string toString(uint128_t input);
85
86 template<class T>
87 static bool tryCast(uint128_t input, T& result);
88
89 template<class T>
90 static T cast(uint128_t input) {
91 T result;
92 tryCast(input, result);
93 return result;
94 }
95
96 template<class T>
97 static bool tryCastTo(T value, uint128_t& result);
98
99 template<class T>
100 static uint128_t castTo(T value) {
101 uint128_t result{};
102 if (!tryCastTo(value, result)) {
103 throw common::OverflowException("UINT128 is out of range");
104 }
105 return result;
106 }
107
108 // negate (required by function/arithmetic/negate.h)
109 static void negateInPlace(uint128_t& input) {
110 input.low = UINT64_MAX + 1 - input.low;
111 input.high = -input.high - 1 + (input.low == 0);
112 }
113
114 static uint128_t negate(uint128_t input) {
115 negateInPlace(input);
116 return input;
117 }
118
119 static bool tryMultiply(uint128_t lhs, uint128_t rhs, uint128_t& result);
120
127 static uint128_t LeftShift(uint128_t lhs, int amount);
128 static uint128_t RightShift(uint128_t lhs, int amount);
132
133 static uint128_t divMod(uint128_t lhs, uint128_t rhs, uint128_t& remainder);
134 static uint128_t divModPositive(uint128_t lhs, uint64_t rhs, uint64_t& remainder);
135
136 static bool addInPlace(uint128_t& lhs, uint128_t rhs);
137 static bool subInPlace(uint128_t& lhs, uint128_t rhs);
138
139 // comparison operators
140 static bool equals(uint128_t lhs, uint128_t rhs) {
141 return lhs.low == rhs.low && lhs.high == rhs.high;
142 }
143
144 static bool notEquals(uint128_t lhs, uint128_t rhs) {
145 return lhs.low != rhs.low || lhs.high != rhs.high;
146 }
147
148 static bool greaterThan(uint128_t lhs, uint128_t rhs) {
149 return (lhs.high > rhs.high) || (lhs.high == rhs.high && lhs.low > rhs.low);
150 }
151
153 return (lhs.high > rhs.high) || (lhs.high == rhs.high && lhs.low >= rhs.low);
154 }
155
156 static bool lessThan(uint128_t lhs, uint128_t rhs) {
157 return (lhs.high < rhs.high) || (lhs.high == rhs.high && lhs.low < rhs.low);
158 }
159
160 static bool lessThanOrEquals(uint128_t lhs, uint128_t rhs) {
161 return (lhs.high < rhs.high) || (lhs.high == rhs.high && lhs.low <= rhs.low);
162 }
163};
164
165template<>
166bool UInt128_t::tryCast(uint128_t input, int8_t& result);
167template<>
168bool UInt128_t::tryCast(uint128_t input, int16_t& result);
169template<>
170bool UInt128_t::tryCast(uint128_t input, int32_t& result);
171template<>
172bool UInt128_t::tryCast(uint128_t input, int64_t& result);
173template<>
174bool UInt128_t::tryCast(uint128_t input, uint8_t& result);
175template<>
176bool UInt128_t::tryCast(uint128_t input, uint16_t& result);
177template<>
178bool UInt128_t::tryCast(uint128_t input, uint32_t& result);
179template<>
180bool UInt128_t::tryCast(uint128_t input, uint64_t& result);
181template<>
182bool UInt128_t::tryCast(uint128_t input, int128_t& result); // unsigned to signed
183template<>
184bool UInt128_t::tryCast(uint128_t input, float& result);
185template<>
186bool UInt128_t::tryCast(uint128_t input, double& result);
187template<>
188bool UInt128_t::tryCast(uint128_t input, long double& result);
189
190template<>
191bool UInt128_t::tryCastTo(int8_t value, uint128_t& result);
192template<>
193bool UInt128_t::tryCastTo(int16_t value, uint128_t& result);
194template<>
195bool UInt128_t::tryCastTo(int32_t value, uint128_t& result);
196template<>
197bool UInt128_t::tryCastTo(int64_t value, uint128_t& result);
198template<>
199bool UInt128_t::tryCastTo(uint8_t value, uint128_t& result);
200template<>
201bool UInt128_t::tryCastTo(uint16_t value, uint128_t& result);
202template<>
203bool UInt128_t::tryCastTo(uint32_t value, uint128_t& result);
204template<>
205bool UInt128_t::tryCastTo(uint64_t value, uint128_t& result);
206template<>
208template<>
209bool UInt128_t::tryCastTo(float value, uint128_t& result);
210template<>
211bool UInt128_t::tryCastTo(double value, uint128_t& result);
212template<>
213bool UInt128_t::tryCastTo(long double value, uint128_t& result);
214
215} // namespace common
216} // namespace lbug
217
218template<>
219struct std::hash<lbug::common::uint128_t> {
220 std::size_t operator()(const lbug::common::uint128_t& v) const noexcept;
221};
#define LBUG_API
Definition api.h:25
Definition overflow.h:9
Definition uint128_t.h:82
static std::string toString(uint128_t input)
static uint128_t castTo(T value)
Definition uint128_t.h:100
static uint128_t RightShift(uint128_t lhs, int amount)
static uint128_t BinaryOr(uint128_t lhs, uint128_t rhs)
static void negateInPlace(uint128_t &input)
Definition uint128_t.h:109
static uint128_t LeftShift(uint128_t lhs, int amount)
static uint128_t negate(uint128_t input)
Definition uint128_t.h:114
static bool notEquals(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:144
static bool equals(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:140
static uint128_t Add(uint128_t lhs, uint128_t rhs)
static uint128_t BinaryNot(uint128_t val)
static uint128_t Mod(uint128_t lhs, uint128_t rhs)
static bool tryMultiply(uint128_t lhs, uint128_t rhs, uint128_t &result)
static bool greaterThan(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:148
static uint128_t divModPositive(uint128_t lhs, uint64_t rhs, uint64_t &remainder)
static bool lessThan(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:156
static bool lessThanOrEquals(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:160
static bool tryCastTo(T value, uint128_t &result)
static uint128_t Div(uint128_t lhs, uint128_t rhs)
static uint128_t Mul(uint128_t lhs, uint128_t rhs)
static bool tryCast(uint128_t input, T &result)
static bool greaterThanOrEquals(uint128_t lhs, uint128_t rhs)
Definition uint128_t.h:152
static uint128_t BinaryAnd(uint128_t lhs, uint128_t rhs)
static uint128_t Xor(uint128_t lhs, uint128_t rhs)
static uint128_t Sub(uint128_t lhs, uint128_t rhs)
static bool subInPlace(uint128_t &lhs, uint128_t rhs)
static uint128_t divMod(uint128_t lhs, uint128_t rhs, uint128_t &remainder)
static bool addInPlace(uint128_t &lhs, uint128_t rhs)
static T cast(uint128_t input)
Definition uint128_t.h:90
Definition array_utils.h:7
Definition array_utils.h:7
Definition int128_t.h:21
Definition uint128_t.h:15
constexpr uint128_t(uint128_t &&) noexcept=default
uint128_t() noexcept=default
uint64_t low
Definition uint128_t.h:16
constexpr uint128_t(const uint128_t &) noexcept=default
uint64_t high
Definition uint128_t.h:17
std::size_t operator()(const lbug::common::uint128_t &v) const noexcept