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 }
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:915
#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 }
Definition: int128.h:108

References val.

Referenced by interval_cmp_value(), and interval_sign().