1 /*-------------------------------------------------------------------------
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
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
29 #include "common/int128.h"
30 #include "common/pg_prng.h"
33 * We assume the parts of this union are laid out compatibly.
41 #ifdef WORDS_BIGENDIAN
53 * Control version of comparator.
56 my_int128_compare(int128 x
, int128 y
)
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.
74 main(int argc
, char **argv
)
78 pg_prng_seed(&pg_global_prng_state
, 0);
81 count
= strtol(argv
[1], NULL
, 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
);
93 /* check unsigned addition */
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
);
108 /* check signed addition */
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
);
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
);
137 /* check comparison */
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
);
154 /* check case with identical hi parts; above will hardly ever hit it */
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
);