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-2024, 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  */
35 typedef union
36 {
37  int128 i128;
39  union
40  {
41 #ifdef WORDS_BIGENDIAN
42  int64 hi;
43  uint64 lo;
44 #else
45  uint64 lo;
46  int64 hi;
47 #endif
48  } hl;
49 } test128;
50 
51 
52 /*
53  * Control version of comparator.
54  */
55 static inline int
56 my_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  */
73 int
74 main(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;
98  int128_add_uint64(&t2.I128, (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",
147  my_int128_compare(t1.i128, t2.i128),
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",
161  my_int128_compare(t1.i128, t2.i128),
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 }
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:72
int x
Definition: isn.c:71
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
int128 i128
Definition: testint128.c:37
INT128 I128
Definition: testint128.c:38
int64 hi
Definition: testint128.c:46
uint64 lo
Definition: testint128.c:45
union test128::@185 hl