LCOV - code coverage report
Current view: top level - src/test/modules/test_int128 - test_int128.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 134 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 2 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * test_int128.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-2026, PostgreSQL Global Development Group
      10              :  *
      11              :  *
      12              :  * IDENTIFICATION
      13              :  *        src/test/modules/test_int128/test_int128.c
      14              :  *
      15              :  *-------------------------------------------------------------------------
      16              :  */
      17              : 
      18              : #include "postgres_fe.h"
      19              : 
      20              : #include <time.h>
      21              : 
      22              : /* Require a native int128 type */
      23              : #ifdef HAVE_INT128
      24              : 
      25              : /*
      26              :  * By default, we test the non-native implementation in int128.h; but
      27              :  * by predefining USE_NATIVE_INT128 to 1, you can test the native
      28              :  * implementation, just to be sure.
      29              :  */
      30              : #ifndef USE_NATIVE_INT128
      31              : #define USE_NATIVE_INT128 0
      32              : #endif
      33              : 
      34              : #include "common/int128.h"
      35              : #include "common/pg_prng.h"
      36              : 
      37              : /*
      38              :  * We assume the parts of this union are laid out compatibly.
      39              :  */
      40              : typedef union
      41              : {
      42              :         int128          i128;
      43              :         INT128          I128;
      44              :         struct
      45              :         {
      46              : #ifdef WORDS_BIGENDIAN
      47              :                 int64           hi;
      48              :                 uint64          lo;
      49              : #else
      50              :                 uint64          lo;
      51              :                 int64           hi;
      52              : #endif
      53              :         }                       hl;
      54              : } test128;
      55              : 
      56              : #define INT128_HEX_FORMAT       "%016" PRIx64 "%016" PRIx64
      57              : 
      58              : /*
      59              :  * Control version of comparator.
      60              :  */
      61              : static inline int
      62            0 : my_int128_compare(int128 x, int128 y)
      63              : {
      64            0 :         if (x < y)
      65            0 :                 return -1;
      66            0 :         if (x > y)
      67            0 :                 return 1;
      68            0 :         return 0;
      69            0 : }
      70              : 
      71              : /*
      72              :  * Main program.
      73              :  *
      74              :  * Generates a lot of random numbers and tests the implementation for each.
      75              :  * The results should be reproducible, since we use a fixed PRNG seed.
      76              :  *
      77              :  * You can give a loop count if you don't like the default 1B iterations.
      78              :  */
      79              : int
      80            0 : main(int argc, char **argv)
      81              : {
      82            0 :         long            count;
      83              : 
      84            0 :         pg_prng_seed(&pg_global_prng_state, (uint64) time(NULL));
      85              : 
      86            0 :         if (argc >= 2)
      87            0 :                 count = strtol(argv[1], NULL, 0);
      88              :         else
      89            0 :                 count = 1000000000;
      90              : 
      91            0 :         while (count-- > 0)
      92              :         {
      93            0 :                 int64           x = pg_prng_int64(&pg_global_prng_state);
      94            0 :                 int64           y = pg_prng_int64(&pg_global_prng_state);
      95            0 :                 int64           z = pg_prng_int64(&pg_global_prng_state);
      96            0 :                 int64           w = pg_prng_int64(&pg_global_prng_state);
      97            0 :                 int32           z32 = pg_prng_int32(&pg_global_prng_state);
      98            0 :                 test128         t1;
      99            0 :                 test128         t2;
     100            0 :                 test128         t3;
     101            0 :                 int32           r1;
     102            0 :                 int32           r2;
     103              : 
     104              :                 /* prevent division by zero in the 128/32-bit division test */
     105            0 :                 while (z32 == 0)
     106            0 :                         z32 = pg_prng_int32(&pg_global_prng_state);
     107              : 
     108              :                 /* check unsigned addition */
     109            0 :                 t1.hl.hi = x;
     110            0 :                 t1.hl.lo = y;
     111            0 :                 t2 = t1;
     112            0 :                 t1.i128 += (int128) (uint64) z;
     113            0 :                 int128_add_uint64(&t2.I128, (uint64) z);
     114              : 
     115            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     116              :                 {
     117            0 :                         printf(INT128_HEX_FORMAT " + unsigned %016" PRIx64 "\n", x, y, z);
     118            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     119            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     120            0 :                         return 1;
     121              :                 }
     122              : 
     123              :                 /* check signed addition */
     124            0 :                 t1.hl.hi = x;
     125            0 :                 t1.hl.lo = y;
     126            0 :                 t2 = t1;
     127            0 :                 t1.i128 += (int128) z;
     128            0 :                 int128_add_int64(&t2.I128, z);
     129              : 
     130            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     131              :                 {
     132            0 :                         printf(INT128_HEX_FORMAT " + signed %016" PRIx64 "\n", x, y, z);
     133            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     134            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     135            0 :                         return 1;
     136              :                 }
     137              : 
     138              :                 /* check 128-bit signed addition */
     139            0 :                 t1.hl.hi = x;
     140            0 :                 t1.hl.lo = y;
     141            0 :                 t2 = t1;
     142            0 :                 t3.hl.hi = z;
     143            0 :                 t3.hl.lo = w;
     144            0 :                 t1.i128 += t3.i128;
     145            0 :                 int128_add_int128(&t2.I128, t3.I128);
     146              : 
     147            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     148              :                 {
     149            0 :                         printf(INT128_HEX_FORMAT " + " INT128_HEX_FORMAT "\n", x, y, z, w);
     150            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     151            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     152            0 :                         return 1;
     153              :                 }
     154              : 
     155              :                 /* check unsigned subtraction */
     156            0 :                 t1.hl.hi = x;
     157            0 :                 t1.hl.lo = y;
     158            0 :                 t2 = t1;
     159            0 :                 t1.i128 -= (int128) (uint64) z;
     160            0 :                 int128_sub_uint64(&t2.I128, (uint64) z);
     161              : 
     162            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     163              :                 {
     164            0 :                         printf(INT128_HEX_FORMAT " - unsigned %016" PRIx64 "\n", x, y, z);
     165            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     166            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     167            0 :                         return 1;
     168              :                 }
     169              : 
     170              :                 /* check signed subtraction */
     171            0 :                 t1.hl.hi = x;
     172            0 :                 t1.hl.lo = y;
     173            0 :                 t2 = t1;
     174            0 :                 t1.i128 -= (int128) z;
     175            0 :                 int128_sub_int64(&t2.I128, z);
     176              : 
     177            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     178              :                 {
     179            0 :                         printf(INT128_HEX_FORMAT " - signed %016" PRIx64 "\n", x, y, z);
     180            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     181            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     182            0 :                         return 1;
     183              :                 }
     184              : 
     185              :                 /* check 64x64-bit multiply-add */
     186            0 :                 t1.hl.hi = x;
     187            0 :                 t1.hl.lo = y;
     188            0 :                 t2 = t1;
     189            0 :                 t1.i128 += (int128) z * (int128) w;
     190            0 :                 int128_add_int64_mul_int64(&t2.I128, z, w);
     191              : 
     192            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     193              :                 {
     194            0 :                         printf(INT128_HEX_FORMAT " + %016" PRIx64 " * %016" PRIx64 "\n", x, y, z, w);
     195            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     196            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     197            0 :                         return 1;
     198              :                 }
     199              : 
     200              :                 /* check 64x64-bit multiply-subtract */
     201            0 :                 t1.hl.hi = x;
     202            0 :                 t1.hl.lo = y;
     203            0 :                 t2 = t1;
     204            0 :                 t1.i128 -= (int128) z * (int128) w;
     205            0 :                 int128_sub_int64_mul_int64(&t2.I128, z, w);
     206              : 
     207            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     208              :                 {
     209            0 :                         printf(INT128_HEX_FORMAT " - %016" PRIx64 " * %016" PRIx64 "\n", x, y, z, w);
     210            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     211            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     212            0 :                         return 1;
     213              :                 }
     214              : 
     215              :                 /* check 128/32-bit division */
     216            0 :                 t3.hl.hi = x;
     217            0 :                 t3.hl.lo = y;
     218            0 :                 t1.i128 = t3.i128 / z32;
     219            0 :                 r1 = (int32) (t3.i128 % z32);
     220            0 :                 t2 = t3;
     221            0 :                 int128_div_mod_int32(&t2.I128, z32, &r2);
     222              : 
     223            0 :                 if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
     224              :                 {
     225            0 :                         printf(INT128_HEX_FORMAT " / signed %08X\n", t3.hl.hi, t3.hl.lo, z32);
     226            0 :                         printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     227            0 :                         printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     228            0 :                         return 1;
     229              :                 }
     230            0 :                 if (r1 != r2)
     231              :                 {
     232            0 :                         printf(INT128_HEX_FORMAT " %% signed %08X\n", t3.hl.hi, t3.hl.lo, z32);
     233            0 :                         printf("native = %08X\n", r1);
     234            0 :                         printf("result = %08X\n", r2);
     235            0 :                         return 1;
     236              :                 }
     237              : 
     238              :                 /* check comparison */
     239            0 :                 t1.hl.hi = x;
     240            0 :                 t1.hl.lo = y;
     241            0 :                 t2.hl.hi = z;
     242            0 :                 t2.hl.lo = w;
     243              : 
     244            0 :                 if (my_int128_compare(t1.i128, t2.i128) !=
     245            0 :                         int128_compare(t1.I128, t2.I128))
     246              :                 {
     247            0 :                         printf("comparison failure: %d vs %d\n",
     248              :                                    my_int128_compare(t1.i128, t2.i128),
     249              :                                    int128_compare(t1.I128, t2.I128));
     250            0 :                         printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     251            0 :                         printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     252            0 :                         return 1;
     253              :                 }
     254              : 
     255              :                 /* check case with identical hi parts; above will hardly ever hit it */
     256            0 :                 t2.hl.hi = x;
     257              : 
     258            0 :                 if (my_int128_compare(t1.i128, t2.i128) !=
     259            0 :                         int128_compare(t1.I128, t2.I128))
     260              :                 {
     261            0 :                         printf("comparison failure: %d vs %d\n",
     262              :                                    my_int128_compare(t1.i128, t2.i128),
     263              :                                    int128_compare(t1.I128, t2.I128));
     264            0 :                         printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
     265            0 :                         printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
     266            0 :                         return 1;
     267              :                 }
     268            0 :         }
     269              : 
     270            0 :         return 0;
     271            0 : }
     272              : 
     273              : #else                                                   /* ! HAVE_INT128 */
     274              : 
     275              : /*
     276              :  * For now, do nothing if we don't have a native int128 type.
     277              :  */
     278              : int
     279              : main(int argc, char **argv)
     280              : {
     281              :         printf("skipping tests: no native int128 type\n");
     282              :         return 0;
     283              : }
     284              : 
     285              : #endif
        

Generated by: LCOV version 2.3.2-1