PostgreSQL Source Code git master
testint128.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * testint128.c
4 * Testbed for roll-our-own 128-bit integer arithmetic.
5 *
6 * This is a standalone test program that compares the behavior of an
7 * implementation in int128.h to an (assumed correct) int128 native type.
8 *
9 * Copyright (c) 2017-2025, PostgreSQL Global Development Group
10 *
11 *
12 * IDENTIFICATION
13 * src/tools/testint128.c
14 *
15 *-------------------------------------------------------------------------
16 */
17
18#include "postgres_fe.h"
19
20/*
21 * By default, we test the non-native implementation in int128.h; but
22 * by predefining USE_NATIVE_INT128 to 1, you can test the native
23 * implementation, just to be sure.
24 */
25#ifndef USE_NATIVE_INT128
26#define USE_NATIVE_INT128 0
27#endif
28
29#include "common/int128.h"
30#include "common/pg_prng.h"
31
32/*
33 * We assume the parts of this union are laid out compatibly.
34 */
35typedef union
36{
37 int128 i128;
39 union
40 {
41#ifdef WORDS_BIGENDIAN
42 int64 hi;
43 uint64 lo;
44#else
47#endif
48 } hl;
49} test128;
50
51
52/*
53 * Control version of comparator.
54 */
55static inline int
56my_int128_compare(int128 x, int128 y)
57{
58 if (x < y)
59 return -1;
60 if (x > y)
61 return 1;
62 return 0;
63}
64
65/*
66 * Main program.
67 *
68 * Generates a lot of random numbers and tests the implementation for each.
69 * The results should be reproducible, since we use a fixed PRNG seed.
70 *
71 * You can give a loop count if you don't like the default 1B iterations.
72 */
73int
74main(int argc, char **argv)
75{
76 long count;
77
79
80 if (argc >= 2)
81 count = strtol(argv[1], NULL, 0);
82 else
83 count = 1000000000;
84
85 while (count-- > 0)
86 {
90 test128 t1;
91 test128 t2;
92
93 /* check unsigned addition */
94 t1.hl.hi = x;
95 t1.hl.lo = y;
96 t2 = t1;
97 t1.i128 += (int128) (uint64) z;
99
100 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
101 {
102 printf("%016lX%016lX + unsigned %lX\n", x, y, z);
103 printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
104 printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
105 return 1;
106 }
107
108 /* check signed addition */
109 t1.hl.hi = x;
110 t1.hl.lo = y;
111 t2 = t1;
112 t1.i128 += (int128) z;
113 int128_add_int64(&t2.I128, z);
114
115 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
116 {
117 printf("%016lX%016lX + signed %lX\n", x, y, z);
118 printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
119 printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
120 return 1;
121 }
122
123 /* check multiplication */
124 t1.i128 = (int128) x * (int128) y;
125
126 t2.hl.hi = t2.hl.lo = 0;
128
129 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
130 {
131 printf("%lX * %lX\n", x, y);
132 printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
133 printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
134 return 1;
135 }
136
137 /* check comparison */
138 t1.hl.hi = x;
139 t1.hl.lo = y;
140 t2.hl.hi = z;
142
143 if (my_int128_compare(t1.i128, t2.i128) !=
144 int128_compare(t1.I128, t2.I128))
145 {
146 printf("comparison failure: %d vs %d\n",
148 int128_compare(t1.I128, t2.I128));
149 printf("arg1 = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
150 printf("arg2 = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
151 return 1;
152 }
153
154 /* check case with identical hi parts; above will hardly ever hit it */
155 t2.hl.hi = x;
156
157 if (my_int128_compare(t1.i128, t2.i128) !=
158 int128_compare(t1.I128, t2.I128))
159 {
160 printf("comparison failure: %d vs %d\n",
162 int128_compare(t1.I128, t2.I128));
163 printf("arg1 = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
164 printf("arg2 = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
165 return 1;
166 }
167 }
168
169 return 0;
170}
int64_t int64
Definition: c.h:482
uint64_t uint64
Definition: c.h:486
static void int128_add_uint64(INT128 *i128, uint64 v)
Definition: int128.h:122
static int int128_compare(INT128 x, INT128 y)
Definition: int128.h:238
static void int128_add_int64(INT128 *i128, int64 v)
Definition: int128.h:143
static void int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:177
int y
Definition: isn.c:71
int x
Definition: isn.c:70
uint64 pg_prng_uint64(pg_prng_state *state)
Definition: pg_prng.c:134
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
#define printf(...)
Definition: port.h:244
Definition: int128.h:108
int main(int argc, char **argv)
Definition: testint128.c:74
static int my_int128_compare(int128 x, int128 y)
Definition: testint128.c:56
union test128::@191 hl
int128 i128
Definition: testint128.c:37
INT128 I128
Definition: testint128.c:38
int64 hi
Definition: testint128.c:46
uint64 lo
Definition: testint128.c:45