]>
Commit | Line | Data |
---|---|---|
b7cd3db6 AK |
1 | #ifndef INT128_H |
2 | #define INT128_H | |
3 | ||
0846beb3 RH |
4 | #ifdef CONFIG_INT128 |
5 | ||
6 | typedef __int128_t Int128; | |
7 | ||
8 | static inline Int128 int128_make64(uint64_t a) | |
9 | { | |
10 | return a; | |
11 | } | |
12 | ||
1edaeee0 RH |
13 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
14 | { | |
15 | return (__uint128_t)hi << 64 | lo; | |
16 | } | |
17 | ||
0846beb3 RH |
18 | static inline uint64_t int128_get64(Int128 a) |
19 | { | |
20 | uint64_t r = a; | |
21 | assert(r == a); | |
22 | return r; | |
23 | } | |
24 | ||
25 | static inline uint64_t int128_getlo(Int128 a) | |
26 | { | |
27 | return a; | |
28 | } | |
29 | ||
30 | static inline int64_t int128_gethi(Int128 a) | |
31 | { | |
32 | return a >> 64; | |
33 | } | |
34 | ||
35 | static inline Int128 int128_zero(void) | |
36 | { | |
37 | return 0; | |
38 | } | |
39 | ||
40 | static inline Int128 int128_one(void) | |
41 | { | |
42 | return 1; | |
43 | } | |
44 | ||
45 | static inline Int128 int128_2_64(void) | |
46 | { | |
47 | return (Int128)1 << 64; | |
48 | } | |
49 | ||
50 | static inline Int128 int128_exts64(int64_t a) | |
51 | { | |
52 | return a; | |
53 | } | |
54 | ||
55 | static inline Int128 int128_and(Int128 a, Int128 b) | |
56 | { | |
57 | return a & b; | |
58 | } | |
59 | ||
60 | static inline Int128 int128_rshift(Int128 a, int n) | |
61 | { | |
62 | return a >> n; | |
63 | } | |
64 | ||
65 | static inline Int128 int128_add(Int128 a, Int128 b) | |
66 | { | |
67 | return a + b; | |
68 | } | |
69 | ||
70 | static inline Int128 int128_neg(Int128 a) | |
71 | { | |
72 | return -a; | |
73 | } | |
74 | ||
75 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
76 | { | |
77 | return a - b; | |
78 | } | |
79 | ||
80 | static inline bool int128_nonneg(Int128 a) | |
81 | { | |
82 | return a >= 0; | |
83 | } | |
84 | ||
85 | static inline bool int128_eq(Int128 a, Int128 b) | |
86 | { | |
87 | return a == b; | |
88 | } | |
89 | ||
90 | static inline bool int128_ne(Int128 a, Int128 b) | |
91 | { | |
92 | return a != b; | |
93 | } | |
94 | ||
95 | static inline bool int128_ge(Int128 a, Int128 b) | |
96 | { | |
97 | return a >= b; | |
98 | } | |
99 | ||
100 | static inline bool int128_lt(Int128 a, Int128 b) | |
101 | { | |
102 | return a < b; | |
103 | } | |
104 | ||
105 | static inline bool int128_le(Int128 a, Int128 b) | |
106 | { | |
107 | return a <= b; | |
108 | } | |
109 | ||
110 | static inline bool int128_gt(Int128 a, Int128 b) | |
111 | { | |
112 | return a > b; | |
113 | } | |
114 | ||
115 | static inline bool int128_nz(Int128 a) | |
116 | { | |
117 | return a != 0; | |
118 | } | |
119 | ||
120 | static inline Int128 int128_min(Int128 a, Int128 b) | |
121 | { | |
122 | return a < b ? a : b; | |
123 | } | |
124 | ||
125 | static inline Int128 int128_max(Int128 a, Int128 b) | |
126 | { | |
127 | return a > b ? a : b; | |
128 | } | |
129 | ||
130 | static inline void int128_addto(Int128 *a, Int128 b) | |
131 | { | |
132 | *a += b; | |
133 | } | |
134 | ||
135 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
136 | { | |
137 | *a -= b; | |
138 | } | |
139 | ||
140 | #else /* !CONFIG_INT128 */ | |
6046c620 | 141 | |
b7cd3db6 AK |
142 | typedef struct Int128 Int128; |
143 | ||
144 | struct Int128 { | |
145 | uint64_t lo; | |
146 | int64_t hi; | |
147 | }; | |
148 | ||
149 | static inline Int128 int128_make64(uint64_t a) | |
150 | { | |
151 | return (Int128) { a, 0 }; | |
152 | } | |
153 | ||
1edaeee0 RH |
154 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
155 | { | |
156 | return (Int128) { lo, hi }; | |
157 | } | |
158 | ||
b7cd3db6 AK |
159 | static inline uint64_t int128_get64(Int128 a) |
160 | { | |
161 | assert(!a.hi); | |
162 | return a.lo; | |
163 | } | |
164 | ||
258dfaaa RH |
165 | static inline uint64_t int128_getlo(Int128 a) |
166 | { | |
167 | return a.lo; | |
168 | } | |
169 | ||
170 | static inline int64_t int128_gethi(Int128 a) | |
171 | { | |
172 | return a.hi; | |
173 | } | |
174 | ||
b7cd3db6 AK |
175 | static inline Int128 int128_zero(void) |
176 | { | |
177 | return int128_make64(0); | |
178 | } | |
179 | ||
180 | static inline Int128 int128_one(void) | |
181 | { | |
182 | return int128_make64(1); | |
183 | } | |
184 | ||
185 | static inline Int128 int128_2_64(void) | |
186 | { | |
187 | return (Int128) { 0, 1 }; | |
188 | } | |
189 | ||
12e1129b AK |
190 | static inline Int128 int128_exts64(int64_t a) |
191 | { | |
192 | return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; | |
193 | } | |
194 | ||
052e87b0 PB |
195 | static inline Int128 int128_and(Int128 a, Int128 b) |
196 | { | |
197 | return (Int128) { a.lo & b.lo, a.hi & b.hi }; | |
198 | } | |
199 | ||
200 | static inline Int128 int128_rshift(Int128 a, int n) | |
201 | { | |
202 | int64_t h; | |
203 | if (!n) { | |
204 | return a; | |
205 | } | |
206 | h = a.hi >> (n & 63); | |
207 | if (n >= 64) { | |
1edaeee0 | 208 | return int128_make128(h, h >> 63); |
052e87b0 | 209 | } else { |
1edaeee0 | 210 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); |
052e87b0 PB |
211 | } |
212 | } | |
213 | ||
b7cd3db6 AK |
214 | static inline Int128 int128_add(Int128 a, Int128 b) |
215 | { | |
6046c620 PB |
216 | uint64_t lo = a.lo + b.lo; |
217 | ||
218 | /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, | |
219 | * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. | |
220 | * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. | |
221 | * | |
222 | * So the carry is lo < a.lo. | |
223 | */ | |
1edaeee0 | 224 | return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); |
b7cd3db6 AK |
225 | } |
226 | ||
227 | static inline Int128 int128_neg(Int128 a) | |
228 | { | |
6046c620 | 229 | uint64_t lo = -a.lo; |
1edaeee0 | 230 | return int128_make128(lo, ~(uint64_t)a.hi + !lo); |
b7cd3db6 AK |
231 | } |
232 | ||
233 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
234 | { | |
1edaeee0 | 235 | return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); |
b7cd3db6 AK |
236 | } |
237 | ||
238 | static inline bool int128_nonneg(Int128 a) | |
239 | { | |
240 | return a.hi >= 0; | |
241 | } | |
242 | ||
243 | static inline bool int128_eq(Int128 a, Int128 b) | |
244 | { | |
245 | return a.lo == b.lo && a.hi == b.hi; | |
246 | } | |
247 | ||
248 | static inline bool int128_ne(Int128 a, Int128 b) | |
249 | { | |
250 | return !int128_eq(a, b); | |
251 | } | |
252 | ||
253 | static inline bool int128_ge(Int128 a, Int128 b) | |
254 | { | |
6046c620 | 255 | return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); |
b7cd3db6 AK |
256 | } |
257 | ||
258 | static inline bool int128_lt(Int128 a, Int128 b) | |
259 | { | |
260 | return !int128_ge(a, b); | |
261 | } | |
262 | ||
263 | static inline bool int128_le(Int128 a, Int128 b) | |
264 | { | |
265 | return int128_ge(b, a); | |
266 | } | |
267 | ||
268 | static inline bool int128_gt(Int128 a, Int128 b) | |
269 | { | |
270 | return !int128_le(a, b); | |
271 | } | |
272 | ||
273 | static inline bool int128_nz(Int128 a) | |
274 | { | |
275 | return a.lo || a.hi; | |
276 | } | |
277 | ||
278 | static inline Int128 int128_min(Int128 a, Int128 b) | |
279 | { | |
280 | return int128_le(a, b) ? a : b; | |
281 | } | |
282 | ||
283 | static inline Int128 int128_max(Int128 a, Int128 b) | |
284 | { | |
285 | return int128_ge(a, b) ? a : b; | |
286 | } | |
287 | ||
288 | static inline void int128_addto(Int128 *a, Int128 b) | |
289 | { | |
290 | *a = int128_add(*a, b); | |
291 | } | |
292 | ||
293 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
294 | { | |
295 | *a = int128_sub(*a, b); | |
296 | } | |
297 | ||
0846beb3 RH |
298 | #endif /* CONFIG_INT128 */ |
299 | #endif /* INT128_H */ |