PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
int128.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  INT128
 

Macros

#define USE_NATIVE_INT128   0
 
#define INT64_AU32(i64)   ((i64) >> 32)
 
#define INT64_AL32(i64)   ((i64) & UINT64CONST(0xFFFFFFFF))
 

Functions

static void int128_add_uint64 (INT128 *i128, uint64 v)
 
static void int128_add_int64 (INT128 *i128, int64 v)
 
static void int128_add_int64_mul_int64 (INT128 *i128, int64 x, int64 y)
 
static int int128_compare (INT128 x, INT128 y)
 
static INT128 int64_to_int128 (int64 v)
 
static int64 int128_to_int64 (INT128 val)
 

Macro Definition Documentation

◆ INT64_AL32

#define INT64_AL32 (   i64)    ((i64) & UINT64CONST(0xFFFFFFFF))

Definition at line 171 of file int128.h.

◆ INT64_AU32

#define INT64_AU32 (   i64)    ((i64) >> 32)

Definition at line 170 of file int128.h.

◆ USE_NATIVE_INT128

#define USE_NATIVE_INT128   0

Definition at line 28 of file int128.h.

Function Documentation

◆ int128_add_int64()

static void int128_add_int64 ( INT128 i128,
int64  v 
)
inlinestatic

Definition at line 143 of file int128.h.

144{
145 /*
146 * This is much like the above except that the carry logic differs for
147 * negative v. Ordinarily we'd need to subtract 1 from the .hi part
148 * (corresponding to adding the sign-extended bits of v to it); but if
149 * there is a carry out of the .lo part, that cancels and we do nothing.
150 */
151 uint64 oldlo = i128->lo;
152
153 i128->lo += v;
154 if (v >= 0)
155 {
156 if ((int64) oldlo < 0 && (int64) i128->lo >= 0)
157 i128->hi++;
158 }
159 else
160 {
161 if (!((int64) oldlo < 0 || (int64) i128->lo >= 0))
162 i128->hi--;
163 }
164}
int64_t int64
Definition: c.h:485
uint64_t uint64
Definition: c.h:489
uint64 lo
Definition: int128.h:113
int64 hi
Definition: int128.h:114

References INT128::hi, and INT128::lo.

Referenced by main().

◆ int128_add_int64_mul_int64()

static void int128_add_int64_mul_int64 ( INT128 i128,
int64  x,
int64  y 
)
inlinestatic

Definition at line 177 of file int128.h.

178{
179 /* INT64_AU32 must use arithmetic right shift */
180 StaticAssertDecl(((int64) -1 >> 1) == (int64) -1,
181 "arithmetic right shift is needed");
182
183 /*----------
184 * Form the 128-bit product x * y using 64-bit arithmetic.
185 * Considering each 64-bit input as having 32-bit high and low parts,
186 * we can compute
187 *
188 * x * y = ((x.hi << 32) + x.lo) * (((y.hi << 32) + y.lo)
189 * = (x.hi * y.hi) << 64 +
190 * (x.hi * y.lo) << 32 +
191 * (x.lo * y.hi) << 32 +
192 * x.lo * y.lo
193 *
194 * Each individual product is of 32-bit terms so it won't overflow when
195 * computed in 64-bit arithmetic. Then we just have to shift it to the
196 * correct position while adding into the 128-bit result. We must also
197 * keep in mind that the "lo" parts must be treated as unsigned.
198 *----------
199 */
200
201 /* No need to work hard if product must be zero */
202 if (x != 0 && y != 0)
203 {
204 int64 x_u32 = INT64_AU32(x);
205 uint64 x_l32 = INT64_AL32(x);
206 int64 y_u32 = INT64_AU32(y);
207 uint64 y_l32 = INT64_AL32(y);
208 int64 tmp;
209
210 /* the first term */
211 i128->hi += x_u32 * y_u32;
212
213 /* the second term: sign-extend it only if x is negative */
214 tmp = x_u32 * y_l32;
215 if (x < 0)
216 i128->hi += INT64_AU32(tmp);
217 else
218 i128->hi += ((uint64) tmp) >> 32;
219 int128_add_uint64(i128, ((uint64) INT64_AL32(tmp)) << 32);
220
221 /* the third term: sign-extend it only if y is negative */
222 tmp = x_l32 * y_u32;
223 if (y < 0)
224 i128->hi += INT64_AU32(tmp);
225 else
226 i128->hi += ((uint64) tmp) >> 32;
227 int128_add_uint64(i128, ((uint64) INT64_AL32(tmp)) << 32);
228
229 /* the fourth term: always unsigned */
230 int128_add_uint64(i128, x_l32 * y_l32);
231 }
232}
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:893
#define INT64_AU32(i64)
Definition: int128.h:170
static void int128_add_uint64(INT128 *i128, uint64 v)
Definition: int128.h:122
#define INT64_AL32(i64)
Definition: int128.h:171
int y
Definition: isn.c:71
int x
Definition: isn.c:70

References INT128::hi, int128_add_uint64(), INT64_AL32, INT64_AU32, StaticAssertDecl, x, and y.

Referenced by interval_cmp_value(), and main().

◆ int128_add_uint64()

static void int128_add_uint64 ( INT128 i128,
uint64  v 
)
inlinestatic

Definition at line 122 of file int128.h.

123{
124 /*
125 * First add the value to the .lo part, then check to see if a carry needs
126 * to be propagated into the .hi part. A carry is needed if both inputs
127 * have high bits set, or if just one input has high bit set while the new
128 * .lo part doesn't. Remember that .lo part is unsigned; we cast to
129 * signed here just as a cheap way to check the high bit.
130 */
131 uint64 oldlo = i128->lo;
132
133 i128->lo += v;
134 if (((int64) v < 0 && (int64) oldlo < 0) ||
135 (((int64) v < 0 || (int64) oldlo < 0) && (int64) i128->lo >= 0))
136 i128->hi++;
137}

References INT128::hi, and INT128::lo.

Referenced by int128_add_int64_mul_int64(), and main().

◆ int128_compare()

static int int128_compare ( INT128  x,
INT128  y 
)
inlinestatic

Definition at line 238 of file int128.h.

239{
240 if (x.hi < y.hi)
241 return -1;
242 if (x.hi > y.hi)
243 return 1;
244 if (x.lo < y.lo)
245 return -1;
246 if (x.lo > y.lo)
247 return 1;
248 return 0;
249}

References x, and y.

Referenced by interval_cmp_internal(), interval_sign(), and main().

◆ int128_to_int64()

static int64 int128_to_int64 ( INT128  val)
inlinestatic

Definition at line 269 of file int128.h.

270{
271 return (int64) val.lo;
272}
long val
Definition: informix.c:689

References val.

Referenced by interval_hash(), and interval_hash_extended().

◆ int64_to_int128()

static INT128 int64_to_int128 ( int64  v)
inlinestatic

Definition at line 255 of file int128.h.

256{
257 INT128 val;
258
259 val.lo = (uint64) v;
260 val.hi = (v < 0) ? -INT64CONST(1) : INT64CONST(0);
261 return val;
262}
#define INT64CONST(x)
Definition: c.h:502
Definition: int128.h:108

References INT64CONST, and val.

Referenced by interval_cmp_value(), and interval_sign().