Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
int128.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * int128.h
4 * Roll-our-own 128-bit integer arithmetic.
5 *
6 * We make use of the native int128 type if there is one, otherwise
7 * implement things the hard way based on two int64 halves.
8 *
9 * See src/test/modules/test_int128 for a simple test harness for this file.
10 *
11 * Copyright (c) 2017-2025, PostgreSQL Global Development Group
12 *
13 * src/include/common/int128.h
14 *
15 *-------------------------------------------------------------------------
16 */
17#ifndef INT128_H
18#define INT128_H
19
20/*
21 * For testing purposes, use of native int128 can be switched on/off by
22 * predefining USE_NATIVE_INT128.
23 */
24#ifndef USE_NATIVE_INT128
25#ifdef HAVE_INT128
26#define USE_NATIVE_INT128 1
27#else
28#define USE_NATIVE_INT128 0
29#endif
30#endif
31
32/*
33 * If native int128 support is enabled, INT128 is just int128. Otherwise, it
34 * is a structure with separate 64-bit high and low parts.
35 *
36 * We lay out the INT128 structure with the same content and byte ordering
37 * that a native int128 type would (probably) have. This makes no difference
38 * for ordinary use of INT128, but allows union'ing INT128 with int128 for
39 * testing purposes.
40 *
41 * PG_INT128_HI_INT64 and PG_INT128_LO_UINT64 allow the (signed) high and
42 * (unsigned) low 64-bit integer parts to be extracted portably on all
43 * platforms.
44 */
45#if USE_NATIVE_INT128
46
47typedef int128 INT128;
48
49#define PG_INT128_HI_INT64(i128) ((int64) ((i128) >> 64))
50#define PG_INT128_LO_UINT64(i128) ((uint64) (i128))
51
52#else
53
54typedef struct
55{
56#ifdef WORDS_BIGENDIAN
57 int64 hi; /* most significant 64 bits, including sign */
58 uint64 lo; /* least significant 64 bits, without sign */
59#else
60 uint64 lo; /* least significant 64 bits, without sign */
61 int64 hi; /* most significant 64 bits, including sign */
62#endif
63} INT128;
64
65#define PG_INT128_HI_INT64(i128) ((i128).hi)
66#define PG_INT128_LO_UINT64(i128) ((i128).lo)
67
68#endif
69
70/*
71 * Construct an INT128 from (signed) high and (unsigned) low 64-bit integer
72 * parts.
73 */
74static inline INT128
76{
77#if USE_NATIVE_INT128
78 return (((int128) hi) << 64) + lo;
79#else
80 INT128 val;
81
82 val.hi = hi;
83 val.lo = lo;
84 return val;
85#endif
86}
87
88/*
89 * Add an unsigned int64 value into an INT128 variable.
90 */
91static inline void
93{
94#if USE_NATIVE_INT128
95 *i128 += v;
96#else
97 /*
98 * First add the value to the .lo part, then check to see if a carry needs
99 * to be propagated into the .hi part. Since this is unsigned integer
100 * arithmetic, which is just modular arithmetic, a carry is needed if the
101 * new .lo part is less than the old .lo part (i.e., if modular
102 * wrap-around occurred). Writing this in the form below, rather than
103 * using an "if" statement causes modern compilers to produce branchless
104 * machine code identical to the native code.
105 */
106 uint64 oldlo = i128->lo;
107
108 i128->lo += v;
109 i128->hi += (i128->lo < oldlo);
110#endif
111}
112
113/*
114 * Add a signed int64 value into an INT128 variable.
115 */
116static inline void
118{
119#if USE_NATIVE_INT128
120 *i128 += v;
121#else
122 /*
123 * This is much like the above except that the carry logic differs for
124 * negative v -- we need to subtract 1 from the .hi part if the new .lo
125 * value is greater than the old .lo value. That can be achieved without
126 * any branching by adding the sign bit from v (v >> 63 = 0 or -1) to the
127 * previous result (for negative v, if the new .lo value is less than the
128 * old .lo value, the two terms cancel and we leave the .hi part
129 * unchanged, otherwise we subtract 1 from the .hi part). With modern
130 * compilers this often produces machine code identical to the native
131 * code.
132 */
133 uint64 oldlo = i128->lo;
134
135 i128->lo += v;
136 i128->hi += (i128->lo < oldlo) + (v >> 63);
137#endif
138}
139
140/*
141 * Add an INT128 value into an INT128 variable.
142 */
143static inline void
145{
146#if USE_NATIVE_INT128
147 *i128 += v;
148#else
149 int128_add_uint64(i128, v.lo);
150 i128->hi += v.hi;
151#endif
152}
153
154/*
155 * Subtract an unsigned int64 value from an INT128 variable.
156 */
157static inline void
159{
160#if USE_NATIVE_INT128
161 *i128 -= v;
162#else
163 /*
164 * This is like int128_add_uint64(), except we must propagate a borrow to
165 * (subtract 1 from) the .hi part if the new .lo part is greater than the
166 * old .lo part.
167 */
168 uint64 oldlo = i128->lo;
169
170 i128->lo -= v;
171 i128->hi -= (i128->lo > oldlo);
172#endif
173}
174
175/*
176 * Subtract a signed int64 value from an INT128 variable.
177 */
178static inline void
180{
181#if USE_NATIVE_INT128
182 *i128 -= v;
183#else
184 /* Like int128_add_int64() with the sign of v inverted */
185 uint64 oldlo = i128->lo;
186
187 i128->lo -= v;
188 i128->hi -= (i128->lo > oldlo) + (v >> 63);
189#endif
190}
191
192/*
193 * INT64_HI_INT32 extracts the most significant 32 bits of int64 as int32.
194 * INT64_LO_UINT32 extracts the least significant 32 bits as uint32.
195 */
196#define INT64_HI_INT32(i64) ((int32) ((i64) >> 32))
197#define INT64_LO_UINT32(i64) ((uint32) (i64))
198
199/*
200 * Add the 128-bit product of two int64 values into an INT128 variable.
201 */
202static inline void
204{
205#if USE_NATIVE_INT128
206 /*
207 * XXX with a stupid compiler, this could actually be less efficient than
208 * the non-native implementation; maybe we should do it by hand always?
209 */
210 *i128 += (int128) x * (int128) y;
211#else
212 /* INT64_HI_INT32 must use arithmetic right shift */
213 StaticAssertDecl(((int64) -1 >> 1) == (int64) -1,
214 "arithmetic right shift is needed");
215
216 /*----------
217 * Form the 128-bit product x * y using 64-bit arithmetic.
218 * Considering each 64-bit input as having 32-bit high and low parts,
219 * we can compute
220 *
221 * x * y = ((x.hi << 32) + x.lo) * (((y.hi << 32) + y.lo)
222 * = (x.hi * y.hi) << 64 +
223 * (x.hi * y.lo) << 32 +
224 * (x.lo * y.hi) << 32 +
225 * x.lo * y.lo
226 *
227 * Each individual product is of 32-bit terms so it won't overflow when
228 * computed in 64-bit arithmetic. Then we just have to shift it to the
229 * correct position while adding into the 128-bit result. We must also
230 * keep in mind that the "lo" parts must be treated as unsigned.
231 *----------
232 */
233
234 /* No need to work hard if product must be zero */
235 if (x != 0 && y != 0)
236 {
237 int32 x_hi = INT64_HI_INT32(x);
238 uint32 x_lo = INT64_LO_UINT32(x);
239 int32 y_hi = INT64_HI_INT32(y);
240 uint32 y_lo = INT64_LO_UINT32(y);
241 int64 tmp;
242
243 /* the first term */
244 i128->hi += (int64) x_hi * (int64) y_hi;
245
246 /* the second term: sign-extended with the sign of x */
247 tmp = (int64) x_hi * (int64) y_lo;
248 i128->hi += INT64_HI_INT32(tmp);
249 int128_add_uint64(i128, ((uint64) INT64_LO_UINT32(tmp)) << 32);
250
251 /* the third term: sign-extended with the sign of y */
252 tmp = (int64) x_lo * (int64) y_hi;
253 i128->hi += INT64_HI_INT32(tmp);
254 int128_add_uint64(i128, ((uint64) INT64_LO_UINT32(tmp)) << 32);
255
256 /* the fourth term: always unsigned */
257 int128_add_uint64(i128, (uint64) x_lo * (uint64) y_lo);
258 }
259#endif
260}
261
262/*
263 * Subtract the 128-bit product of two int64 values from an INT128 variable.
264 */
265static inline void
267{
268#if USE_NATIVE_INT128
269 *i128 -= (int128) x * (int128) y;
270#else
271 /* As above, except subtract the 128-bit product */
272 if (x != 0 && y != 0)
273 {
274 int32 x_hi = INT64_HI_INT32(x);
275 uint32 x_lo = INT64_LO_UINT32(x);
276 int32 y_hi = INT64_HI_INT32(y);
277 uint32 y_lo = INT64_LO_UINT32(y);
278 int64 tmp;
279
280 /* the first term */
281 i128->hi -= (int64) x_hi * (int64) y_hi;
282
283 /* the second term: sign-extended with the sign of x */
284 tmp = (int64) x_hi * (int64) y_lo;
285 i128->hi -= INT64_HI_INT32(tmp);
286 int128_sub_uint64(i128, ((uint64) INT64_LO_UINT32(tmp)) << 32);
287
288 /* the third term: sign-extended with the sign of y */
289 tmp = (int64) x_lo * (int64) y_hi;
290 i128->hi -= INT64_HI_INT32(tmp);
291 int128_sub_uint64(i128, ((uint64) INT64_LO_UINT32(tmp)) << 32);
292
293 /* the fourth term: always unsigned */
294 int128_sub_uint64(i128, (uint64) x_lo * (uint64) y_lo);
295 }
296#endif
297}
298
299/*
300 * Divide an INT128 variable by a signed int32 value, returning the quotient
301 * and remainder. The remainder will have the same sign as *i128.
302 *
303 * Note: This provides no protection against dividing by 0, or dividing
304 * INT128_MIN by -1, which overflows. It is the caller's responsibility to
305 * guard against those.
306 */
307static inline void
309{
310#if USE_NATIVE_INT128
311 int128 old_i128 = *i128;
312
313 *i128 /= v;
314 *remainder = (int32) (old_i128 - *i128 * v);
315#else
316 /*
317 * To avoid any intermediate values overflowing (as happens if INT64_MIN
318 * is divided by -1), we first compute the quotient abs(*i128) / abs(v)
319 * using unsigned 64-bit arithmetic, and then fix the signs up at the end.
320 *
321 * The quotient is computed using the short division algorithm described
322 * in Knuth volume 2, section 4.3.1 exercise 16 (cf. div_var_int() in
323 * numeric.c). Since the absolute value of the divisor is known to be at
324 * most 2^31, the remainder carried from one digit to the next is at most
325 * 2^31 - 1, and so there is no danger of overflow when this is combined
326 * with the next digit (a 32-bit unsigned integer).
327 */
328 uint64 n_hi;
329 uint64 n_lo;
330 uint32 d;
331 uint64 q;
332 uint64 r;
333 uint64 tmp;
334
335 /* numerator: absolute value of *i128 */
336 if (i128->hi < 0)
337 {
338 n_hi = 0 - ((uint64) i128->hi);
339 n_lo = 0 - i128->lo;
340 if (n_lo != 0)
341 n_hi--;
342 }
343 else
344 {
345 n_hi = i128->hi;
346 n_lo = i128->lo;
347 }
348
349 /* denomimator: absolute value of v */
350 d = abs(v);
351
352 /* quotient and remainder of high 64 bits */
353 q = n_hi / d;
354 r = n_hi % d;
355 n_hi = q;
356
357 /* quotient and remainder of next 32 bits (upper half of n_lo) */
358 tmp = (r << 32) + (n_lo >> 32);
359 q = tmp / d;
360 r = tmp % d;
361
362 /* quotient and remainder of last 32 bits (lower half of n_lo) */
363 tmp = (r << 32) + (uint32) n_lo;
364 n_lo = q << 32;
365 q = tmp / d;
366 r = tmp % d;
367 n_lo += q;
368
369 /* final remainder should have the same sign as *i128 */
370 *remainder = i128->hi < 0 ? (int32) (0 - r) : (int32) r;
371
372 /* store the quotient in *i128, negating it if necessary */
373 if ((i128->hi < 0) != (v < 0))
374 {
375 n_hi = 0 - n_hi;
376 n_lo = 0 - n_lo;
377 if (n_lo != 0)
378 n_hi--;
379 }
380 i128->hi = (int64) n_hi;
381 i128->lo = n_lo;
382#endif
383}
384
385/*
386 * Test if an INT128 value is zero.
387 */
388static inline bool
390{
391#if USE_NATIVE_INT128
392 return x == 0;
393#else
394 return x.hi == 0 && x.lo == 0;
395#endif
396}
397
398/*
399 * Return the sign of an INT128 value (returns -1, 0, or +1).
400 */
401static inline int
403{
404#if USE_NATIVE_INT128
405 if (x < 0)
406 return -1;
407 if (x > 0)
408 return 1;
409 return 0;
410#else
411 if (x.hi < 0)
412 return -1;
413 if (x.hi > 0)
414 return 1;
415 if (x.lo > 0)
416 return 1;
417 return 0;
418#endif
419}
420
421/*
422 * Compare two INT128 values, return -1, 0, or +1.
423 */
424static inline int
426{
427#if USE_NATIVE_INT128
428 if (x < y)
429 return -1;
430 if (x > y)
431 return 1;
432 return 0;
433#else
434 if (x.hi < y.hi)
435 return -1;
436 if (x.hi > y.hi)
437 return 1;
438 if (x.lo < y.lo)
439 return -1;
440 if (x.lo > y.lo)
441 return 1;
442 return 0;
443#endif
444}
445
446/*
447 * Widen int64 to INT128.
448 */
449static inline INT128
451{
452#if USE_NATIVE_INT128
453 return (INT128) v;
454#else
455 INT128 val;
456
457 val.lo = (uint64) v;
458 val.hi = (v < 0) ? -INT64CONST(1) : INT64CONST(0);
459 return val;
460#endif
461}
462
463/*
464 * Convert INT128 to int64 (losing any high-order bits).
465 * This also works fine for casting down to uint64.
466 */
467static inline int64
469{
470#if USE_NATIVE_INT128
471 return (int64) val;
472#else
473 return (int64) val.lo;
474#endif
475}
476
477#endif /* INT128_H */
#define INT64CONST(x)
Definition: c.h:553
int64_t int64
Definition: c.h:536
int32_t int32
Definition: c.h:535
uint64_t uint64
Definition: c.h:540
uint32_t uint32
Definition: c.h:539
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:936
size_t remainder
long val
Definition: informix.c:689
static void int128_sub_uint64(INT128 *i128, uint64 v)
Definition: int128.h:158
static void int128_add_uint64(INT128 *i128, uint64 v)
Definition: int128.h:92
static INT128 make_int128(int64 hi, uint64 lo)
Definition: int128.h:75
static bool int128_is_zero(INT128 x)
Definition: int128.h:389
static void int128_sub_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:266
#define INT64_HI_INT32(i64)
Definition: int128.h:196
static int int128_sign(INT128 x)
Definition: int128.h:402
static void int128_add_int128(INT128 *i128, INT128 v)
Definition: int128.h:144
static void int128_sub_int64(INT128 *i128, int64 v)
Definition: int128.h:179
static int int128_compare(INT128 x, INT128 y)
Definition: int128.h:425
static INT128 int64_to_int128(int64 v)
Definition: int128.h:450
static void int128_add_int64(INT128 *i128, int64 v)
Definition: int128.h:117
#define INT64_LO_UINT32(i64)
Definition: int128.h:197
static int64 int128_to_int64(INT128 val)
Definition: int128.h:468
static void int128_div_mod_int32(INT128 *i128, int32 v, int32 *remainder)
Definition: int128.h:308
static void int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:203
int y
Definition: isn.c:76
int x
Definition: isn.c:75
Definition: int128.h:55
uint64 lo
Definition: int128.h:60
int64 hi
Definition: int128.h:61