MobilityDB 1.1
int.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * int.h
4 * Routines to perform integer math, while checking for overflows.
5 *
6 * The routines in this file are intended to be well defined C, without
7 * relying on compiler flags like -fwrapv.
8 *
9 * To reduce the overhead of these routines try to use compiler intrinsics
10 * where available. That's not that important for the 16, 32 bit cases, but
11 * the 64 bit cases can be considerably faster with intrinsics. In case no
12 * intrinsics are available 128 bit math is used where available.
13 *
14 * Copyright (c) 2017-2021, PostgreSQL Global Development Group
15 *
16 * src/include/common/int.h
17 *
18 *-------------------------------------------------------------------------
19 */
20#ifndef COMMON_INT_H
21#define COMMON_INT_H
22
23
24/*---------
25 * The following guidelines apply to all the routines:
26 * - If a + b overflows, return true, otherwise store the result of a + b
27 * into *result. The content of *result is implementation defined in case of
28 * overflow.
29 * - If a - b overflows, return true, otherwise store the result of a - b
30 * into *result. The content of *result is implementation defined in case of
31 * overflow.
32 * - If a * b overflows, return true, otherwise store the result of a * b
33 * into *result. The content of *result is implementation defined in case of
34 * overflow.
35 *---------
36 */
37
38/*------------------------------------------------------------------------
39 * Overflow routines for signed integers
40 *------------------------------------------------------------------------
41 */
42
43/*
44 * INT16
45 */
46static inline bool
48{
49#if defined(HAVE__BUILTIN_OP_OVERFLOW)
50 return __builtin_add_overflow(a, b, result);
51#else
52 int32 res = (int32) a + (int32) b;
53
54 if (res > PG_INT16_MAX || res < PG_INT16_MIN)
55 {
56 *result = 0x5EED; /* to avoid spurious warnings */
57 return true;
58 }
59 *result = (int16) res;
60 return false;
61#endif
62}
63
64static inline bool
66{
67#if defined(HAVE__BUILTIN_OP_OVERFLOW)
68 return __builtin_sub_overflow(a, b, result);
69#else
70 int32 res = (int32) a - (int32) b;
71
72 if (res > PG_INT16_MAX || res < PG_INT16_MIN)
73 {
74 *result = 0x5EED; /* to avoid spurious warnings */
75 return true;
76 }
77 *result = (int16) res;
78 return false;
79#endif
80}
81
82static inline bool
84{
85#if defined(HAVE__BUILTIN_OP_OVERFLOW)
86 return __builtin_mul_overflow(a, b, result);
87#else
88 int32 res = (int32) a * (int32) b;
89
90 if (res > PG_INT16_MAX || res < PG_INT16_MIN)
91 {
92 *result = 0x5EED; /* to avoid spurious warnings */
93 return true;
94 }
95 *result = (int16) res;
96 return false;
97#endif
98}
99
100/*
101 * INT32
102 */
103static inline bool
105{
106#if defined(HAVE__BUILTIN_OP_OVERFLOW)
107 return __builtin_add_overflow(a, b, result);
108#else
109 int64 res = (int64) a + (int64) b;
110
111 if (res > PG_INT32_MAX || res < PG_INT32_MIN)
112 {
113 *result = 0x5EED; /* to avoid spurious warnings */
114 return true;
115 }
116 *result = (int32) res;
117 return false;
118#endif
119}
120
121static inline bool
123{
124#if defined(HAVE__BUILTIN_OP_OVERFLOW)
125 return __builtin_sub_overflow(a, b, result);
126#else
127 int64 res = (int64) a - (int64) b;
128
129 if (res > PG_INT32_MAX || res < PG_INT32_MIN)
130 {
131 *result = 0x5EED; /* to avoid spurious warnings */
132 return true;
133 }
134 *result = (int32) res;
135 return false;
136#endif
137}
138
139static inline bool
141{
142#if defined(HAVE__BUILTIN_OP_OVERFLOW)
143 return __builtin_mul_overflow(a, b, result);
144#else
145 int64 res = (int64) a * (int64) b;
146
147 if (res > PG_INT32_MAX || res < PG_INT32_MIN)
148 {
149 *result = 0x5EED; /* to avoid spurious warnings */
150 return true;
151 }
152 *result = (int32) res;
153 return false;
154#endif
155}
156
157/*
158 * INT64
159 */
160static inline bool
162{
163#if defined(HAVE__BUILTIN_OP_OVERFLOW)
164 return __builtin_add_overflow(a, b, result);
165#elif defined(HAVE_INT128)
166 int128 res = (int128) a + (int128) b;
167
168 if (res > PG_INT64_MAX || res < PG_INT64_MIN)
169 {
170 *result = 0x5EED; /* to avoid spurious warnings */
171 return true;
172 }
173 *result = (int64) res;
174 return false;
175#else
176 if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
177 (a < 0 && b < 0 && a < PG_INT64_MIN - b))
178 {
179 *result = 0x5EED; /* to avoid spurious warnings */
180 return true;
181 }
182 *result = a + b;
183 return false;
184#endif
185}
186
187static inline bool
189{
190#if defined(HAVE__BUILTIN_OP_OVERFLOW)
191 return __builtin_sub_overflow(a, b, result);
192#elif defined(HAVE_INT128)
193 int128 res = (int128) a - (int128) b;
194
195 if (res > PG_INT64_MAX || res < PG_INT64_MIN)
196 {
197 *result = 0x5EED; /* to avoid spurious warnings */
198 return true;
199 }
200 *result = (int64) res;
201 return false;
202#else
203 if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
204 (a > 0 && b < 0 && a > PG_INT64_MAX + b))
205 {
206 *result = 0x5EED; /* to avoid spurious warnings */
207 return true;
208 }
209 *result = a - b;
210 return false;
211#endif
212}
213
214static inline bool
216{
217#if defined(HAVE__BUILTIN_OP_OVERFLOW)
218 return __builtin_mul_overflow(a, b, result);
219#elif defined(HAVE_INT128)
220 int128 res = (int128) a * (int128) b;
221
222 if (res > PG_INT64_MAX || res < PG_INT64_MIN)
223 {
224 *result = 0x5EED; /* to avoid spurious warnings */
225 return true;
226 }
227 *result = (int64) res;
228 return false;
229#else
230 /*
231 * Overflow can only happen if at least one value is outside the range
232 * sqrt(min)..sqrt(max) so check that first as the division can be quite a
233 * bit more expensive than the multiplication.
234 *
235 * Multiplying by 0 or 1 can't overflow of course and checking for 0
236 * separately avoids any risk of dividing by 0. Be careful about dividing
237 * INT_MIN by -1 also, note reversing the a and b to ensure we're always
238 * dividing it by a positive value.
239 *
240 */
241 if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
242 b > PG_INT32_MAX || b < PG_INT32_MIN) &&
243 a != 0 && a != 1 && b != 0 && b != 1 &&
244 ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
245 (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
246 (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
247 (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
248 {
249 *result = 0x5EED; /* to avoid spurious warnings */
250 return true;
251 }
252 *result = a * b;
253 return false;
254#endif
255}
256
257/*------------------------------------------------------------------------
258 * Overflow routines for unsigned integers
259 *------------------------------------------------------------------------
260 */
261
262/*
263 * UINT16
264 */
265static inline bool
267{
268#if defined(HAVE__BUILTIN_OP_OVERFLOW)
269 return __builtin_add_overflow(a, b, result);
270#else
271 uint16 res = a + b;
272
273 if (res < a)
274 {
275 *result = 0x5EED; /* to avoid spurious warnings */
276 return true;
277 }
278 *result = res;
279 return false;
280#endif
281}
282
283static inline bool
285{
286#if defined(HAVE__BUILTIN_OP_OVERFLOW)
287 return __builtin_sub_overflow(a, b, result);
288#else
289 if (b > a)
290 {
291 *result = 0x5EED; /* to avoid spurious warnings */
292 return true;
293 }
294 *result = a - b;
295 return false;
296#endif
297}
298
299static inline bool
301{
302#if defined(HAVE__BUILTIN_OP_OVERFLOW)
303 return __builtin_mul_overflow(a, b, result);
304#else
305 uint32 res = (uint32) a * (uint32) b;
306
307 if (res > PG_UINT16_MAX)
308 {
309 *result = 0x5EED; /* to avoid spurious warnings */
310 return true;
311 }
312 *result = (uint16) res;
313 return false;
314#endif
315}
316
317/*
318 * INT32
319 */
320static inline bool
322{
323#if defined(HAVE__BUILTIN_OP_OVERFLOW)
324 return __builtin_add_overflow(a, b, result);
325#else
326 uint32 res = a + b;
327
328 if (res < a)
329 {
330 *result = 0x5EED; /* to avoid spurious warnings */
331 return true;
332 }
333 *result = res;
334 return false;
335#endif
336}
337
338static inline bool
340{
341#if defined(HAVE__BUILTIN_OP_OVERFLOW)
342 return __builtin_sub_overflow(a, b, result);
343#else
344 if (b > a)
345 {
346 *result = 0x5EED; /* to avoid spurious warnings */
347 return true;
348 }
349 *result = a - b;
350 return false;
351#endif
352}
353
354static inline bool
356{
357#if defined(HAVE__BUILTIN_OP_OVERFLOW)
358 return __builtin_mul_overflow(a, b, result);
359#else
360 uint64 res = (uint64) a * (uint64) b;
361
362 if (res > PG_UINT32_MAX)
363 {
364 *result = 0x5EED; /* to avoid spurious warnings */
365 return true;
366 }
367 *result = (uint32) res;
368 return false;
369#endif
370}
371
372/*
373 * UINT64
374 */
375static inline bool
377{
378#if defined(HAVE__BUILTIN_OP_OVERFLOW)
379 return __builtin_add_overflow(a, b, result);
380#else
381 uint64 res = a + b;
382
383 if (res < a)
384 {
385 *result = 0x5EED; /* to avoid spurious warnings */
386 return true;
387 }
388 *result = res;
389 return false;
390#endif
391}
392
393static inline bool
395{
396#if defined(HAVE__BUILTIN_OP_OVERFLOW)
397 return __builtin_sub_overflow(a, b, result);
398#else
399 if (b > a)
400 {
401 *result = 0x5EED; /* to avoid spurious warnings */
402 return true;
403 }
404 *result = a - b;
405 return false;
406#endif
407}
408
409static inline bool
411{
412#if defined(HAVE__BUILTIN_OP_OVERFLOW)
413 return __builtin_mul_overflow(a, b, result);
414#elif defined(HAVE_INT128)
415 uint128 res = (uint128) a * (uint128) b;
416
417 if (res > PG_UINT64_MAX)
418 {
419 *result = 0x5EED; /* to avoid spurious warnings */
420 return true;
421 }
422 *result = (uint64) res;
423 return false;
424#else
425 uint64 res = a * b;
426
427 if (a != 0 && b != res / a)
428 {
429 *result = 0x5EED; /* to avoid spurious warnings */
430 return true;
431 }
432 *result = res;
433 return false;
434#endif
435}
436
437#endif /* COMMON_INT_H */
#define PG_INT32_MAX
Definition: c.h:529
#define PG_UINT32_MAX
Definition: c.h:530
#define PG_INT16_MIN
Definition: c.h:525
#define PG_INT64_MAX
Definition: c.h:532
#define PG_INT64_MIN
Definition: c.h:531
#define PG_UINT16_MAX
Definition: c.h:527
#define PG_UINT64_MAX
Definition: c.h:533
#define PG_INT32_MIN
Definition: c.h:528
#define PG_INT16_MAX
Definition: c.h:526
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
static bool pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:339
static bool pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:321
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:376
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:65
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:140
static bool pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:300
static bool pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:355
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:83
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:410
static bool pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:284
static bool pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:266
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:47
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:122
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:161
static bool pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:394
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:104
signed short int16
Functions for building a cache of temporal types and operators.
Definition: meos_catalog.h:41
unsigned short uint16
Definition: pg_ext_defs.in.h:12
unsigned int uint32
Definition: pg_ext_defs.in.h:13
signed int int32
Definition: pg_ext_defs.in.h:8
unsigned long int uint64
Definition: pg_ext_defs.in.h:14
long int int64
Definition: pg_ext_defs.in.h:9