LCOV - code coverage report
Current view: top level - src/port - pg_bitutils.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 0.0 % 23 0
Test Date: 2026-03-03 13:15:30 Functions: 0.0 % 2 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * pg_bitutils.c
       4              :  *    Miscellaneous functions for bit-wise operations.
       5              :  *
       6              :  * Copyright (c) 2019-2026, PostgreSQL Global Development Group
       7              :  *
       8              :  * IDENTIFICATION
       9              :  *    src/port/pg_bitutils.c
      10              :  *
      11              :  *-------------------------------------------------------------------------
      12              :  */
      13              : #include "c.h"
      14              : 
      15              : #include "port/pg_bitutils.h"
      16              : 
      17              : 
      18              : /*
      19              :  * Array giving the position of the left-most set bit for each possible
      20              :  * byte value.  We count the right-most position as the 0th bit, and the
      21              :  * left-most the 7th bit.  The 0th entry of the array should not be used.
      22              :  *
      23              :  * Note: this is not used by the functions in pg_bitutils.h when
      24              :  * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that
      25              :  * extensions possibly compiled with a different compiler can use it.
      26              :  */
      27              : const uint8 pg_leftmost_one_pos[256] = {
      28              :     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
      29              :     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
      30              :     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
      31              :     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
      32              :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      33              :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      34              :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      35              :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      36              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      37              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      38              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      39              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      40              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      41              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      42              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      43              :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
      44              : };
      45              : 
      46              : /*
      47              :  * Array giving the position of the right-most set bit for each possible
      48              :  * byte value.  We count the right-most position as the 0th bit, and the
      49              :  * left-most the 7th bit.  The 0th entry of the array should not be used.
      50              :  *
      51              :  * Note: this is not used by the functions in pg_bitutils.h when
      52              :  * HAVE__BUILTIN_CTZ is defined, but we provide it anyway, so that
      53              :  * extensions possibly compiled with a different compiler can use it.
      54              :  */
      55              : const uint8 pg_rightmost_one_pos[256] = {
      56              :     0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      57              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      58              :     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      59              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      60              :     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      61              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      62              :     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      63              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      64              :     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      65              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      66              :     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      67              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      68              :     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      69              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      70              :     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
      71              :     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
      72              : };
      73              : 
      74              : /*
      75              :  * Array giving the number of 1-bits in each possible byte value.
      76              :  *
      77              :  * Note: we export this for use by functions in which explicit use
      78              :  * of the popcount functions seems unlikely to be a win.
      79              :  */
      80              : const uint8 pg_number_of_ones[256] = {
      81              :     0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
      82              :     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
      83              :     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
      84              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      85              :     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
      86              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      87              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      88              :     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
      89              :     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
      90              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      91              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      92              :     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
      93              :     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
      94              :     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
      95              :     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
      96              :     4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
      97              : };
      98              : 
      99              : /*
     100              :  * pg_popcount_portable
     101              :  *      Returns the number of 1-bits in buf
     102              :  */
     103              : uint64
     104            0 : pg_popcount_portable(const char *buf, int bytes)
     105              : {
     106            0 :     uint64      popcnt = 0;
     107              : 
     108              : #if SIZEOF_VOID_P >= 8
     109              :     /* Process in 64-bit chunks if the buffer is aligned. */
     110            0 :     if (buf == (const char *) TYPEALIGN(8, buf))
     111              :     {
     112            0 :         const uint64 *words = (const uint64 *) buf;
     113              : 
     114            0 :         while (bytes >= 8)
     115              :         {
     116            0 :             popcnt += pg_popcount64(*words++);
     117            0 :             bytes -= 8;
     118              :         }
     119              : 
     120            0 :         buf = (const char *) words;
     121              :     }
     122              : #endif
     123              : 
     124              :     /* Process any remaining bytes */
     125            0 :     while (bytes--)
     126            0 :         popcnt += pg_number_of_ones[(unsigned char) *buf++];
     127              : 
     128            0 :     return popcnt;
     129              : }
     130              : 
     131              : /*
     132              :  * pg_popcount_masked_portable
     133              :  *      Returns the number of 1-bits in buf after applying the mask to each byte
     134              :  */
     135              : uint64
     136            0 : pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask)
     137              : {
     138            0 :     uint64      popcnt = 0;
     139              : 
     140              : #if SIZEOF_VOID_P >= 8
     141              :     /* Process in 64-bit chunks if the buffer is aligned */
     142            0 :     uint64      maskv = ~UINT64CONST(0) / 0xFF * mask;
     143              : 
     144            0 :     if (buf == (const char *) TYPEALIGN(8, buf))
     145              :     {
     146            0 :         const uint64 *words = (const uint64 *) buf;
     147              : 
     148            0 :         while (bytes >= 8)
     149              :         {
     150            0 :             popcnt += pg_popcount64(*words++ & maskv);
     151            0 :             bytes -= 8;
     152              :         }
     153              : 
     154            0 :         buf = (const char *) words;
     155              :     }
     156              : #endif
     157              : 
     158              :     /* Process any remaining bytes */
     159            0 :     while (bytes--)
     160            0 :         popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
     161              : 
     162            0 :     return popcnt;
     163              : }
     164              : 
     165              : #if !defined(HAVE_X86_64_POPCNTQ) && !defined(USE_NEON)
     166              : 
     167              : /*
     168              :  * When special CPU instructions are not available, there's no point in using
     169              :  * function pointers to vary the implementation.  We instead just make these
     170              :  * actual external functions.  The compiler should be able to inline the
     171              :  * portable versions here.
     172              :  */
     173              : 
     174              : /*
     175              :  * pg_popcount_optimized
     176              :  *      Returns the number of 1-bits in buf
     177              :  */
     178              : uint64
     179              : pg_popcount_optimized(const char *buf, int bytes)
     180              : {
     181              :     return pg_popcount_portable(buf, bytes);
     182              : }
     183              : 
     184              : /*
     185              :  * pg_popcount_masked_optimized
     186              :  *      Returns the number of 1-bits in buf after applying the mask to each byte
     187              :  */
     188              : uint64
     189              : pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask)
     190              : {
     191              :     return pg_popcount_masked_portable(buf, bytes, mask);
     192              : }
     193              : 
     194              : #endif                          /* ! HAVE_X86_64_POPCNTQ && ! USE_NEON */
        

Generated by: LCOV version 2.0-1