Mark hash_corrupted() as pg_attribute_noreturn.
[pgsql.git] / src / tools / testint128.c
blob4613ef0a50d451ed0cc53c0a8ec37dac8d038173
1 /*-------------------------------------------------------------------------
3 * testint128.c
4 * Testbed for roll-our-own 128-bit integer arithmetic.
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.
9 * Copyright (c) 2017-2024, PostgreSQL Global Development Group
12 * IDENTIFICATION
13 * src/tools/testint128.c
15 *-------------------------------------------------------------------------
18 #include "postgres_fe.h"
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.
25 #ifndef USE_NATIVE_INT128
26 #define USE_NATIVE_INT128 0
27 #endif
29 #include "common/int128.h"
30 #include "common/pg_prng.h"
33 * We assume the parts of this union are laid out compatibly.
35 typedef union
37 int128 i128;
38 INT128 I128;
39 union
41 #ifdef WORDS_BIGENDIAN
42 int64 hi;
43 uint64 lo;
44 #else
45 uint64 lo;
46 int64 hi;
47 #endif
48 } hl;
49 } test128;
53 * Control version of comparator.
55 static inline int
56 my_int128_compare(int128 x, int128 y)
58 if (x < y)
59 return -1;
60 if (x > y)
61 return 1;
62 return 0;
66 * Main program.
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.
71 * You can give a loop count if you don't like the default 1B iterations.
73 int
74 main(int argc, char **argv)
76 long count;
78 pg_prng_seed(&pg_global_prng_state, 0);
80 if (argc >= 2)
81 count = strtol(argv[1], NULL, 0);
82 else
83 count = 1000000000;
85 while (count-- > 0)
87 int64 x = pg_prng_uint64(&pg_global_prng_state);
88 int64 y = pg_prng_uint64(&pg_global_prng_state);
89 int64 z = pg_prng_uint64(&pg_global_prng_state);
90 test128 t1;
91 test128 t2;
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);
100 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
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;
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);
115 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
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;
123 /* check multiplication */
124 t1.i128 = (int128) x * (int128) y;
126 t2.hl.hi = t2.hl.lo = 0;
127 int128_add_int64_mul_int64(&t2.I128, x, y);
129 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
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;
137 /* check comparison */
138 t1.hl.hi = x;
139 t1.hl.lo = y;
140 t2.hl.hi = z;
141 t2.hl.lo = pg_prng_uint64(&pg_global_prng_state);
143 if (my_int128_compare(t1.i128, t2.i128) !=
144 int128_compare(t1.I128, t2.I128))
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;
154 /* check case with identical hi parts; above will hardly ever hit it */
155 t2.hl.hi = x;
157 if (my_int128_compare(t1.i128, t2.i128) !=
158 int128_compare(t1.I128, t2.I128))
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;
169 return 0;