LCOV - code coverage report
Current view: top level - util/tmpl - fd_smallset.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 33 36 91.7 %
Date: 2024-11-13 11:58:15 Functions: 39 120 32.5 %

          Line data    Source code
       1             : /* Declare a header-only API for fast manipulation of index sets where
       2             :    the set itself is represented in a primitive unsigned integer type.
       3             :    Example:
       4             : 
       5             :      #define SET_NAME myset
       6             :      #include "util/tmpl/fd_smallset.c"
       7             : 
       8             :    will declare the following in the compile unit:
       9             : 
      10             :      enum { myset_MAX = 64 }; // maximum number of elements in set (for use in compile time constructors)
      11             : 
      12             :      // Set constructors
      13             :      myset_t myset_null   ( void           ); // return {}
      14             :      myset_t myset_full   ( void           ); // return ~{}
      15             :      myset_t myset_full_if( int c          ); // return c ? ~{} : {}
      16             :      myset_t myset_ele    ( ulong i        ); // return { i }
      17             :      myset_t myset_ele_if ( int c, ulong i ); // return c ? { i } : {}
      18             :      
      19             :      // Index operations
      20             :      ulong myset_max  ( void      ); // return the maximum number of elements that can be held by the set,
      21             :                                      // will be in (0,8*sizeof(myset_t)]
      22             :      ulong myset_cnt  ( myset_t x ); // return the current number of elements in the set, will be in [0,myset_max()]
      23             :      ulong myset_first( myset_t x ); // return the index of the first element in the set, will be in [0,myset_max()),
      24             :                                      // U.B. if set is null
      25             :      
      26             :      // Boolean operations
      27             :      int myset_valid_idx( ulong i              ); // returns 1 if i is a valid set index (i.e. idx < myset_max())
      28             :      int myset_valid    ( myset_t x            ); // returns 1 if x a valid set (i.e. no bits idx >= myset_max() are set)
      29             :      int myset_is_null  ( myset_t x            ); // returns 1 if x is the null set
      30             :      int myset_is_full  ( myset_t x            ); // returns 1 if x is the full set
      31             :      int myset_test     ( myset_t x, ulong i   ); // returns 1 if element i is in set x
      32             :      int myset_eq       ( myset_t x, myset_t y ); // returns 1 if x and y are the same sets
      33             :      int myset_subset   ( myset_t x, myset_t y ); // returns 1 if x is a subset of y
      34             :      
      35             :      // Unary operations
      36             :      myset_t myset_copy      ( myset_t x ); // returns x
      37             :      myset_t myset_complement( myset_t x ); // returns ~x
      38             :      
      39             :      // Binary operations
      40             :      myset_t myset_union    ( myset_t x, myset_t y ); // returns x u y
      41             :      myset_t myset_intersect( myset_t x, myset_t y ); // returns x n y 
      42             :      myset_t myset_subtract ( myset_t x, myset_t y ); // returns x - y
      43             :      myset_t myset_xor      ( myset_t x, myset_t y ); // returns (x u y) - (x n y)
      44             :      
      45             :      // Trinary operations
      46             :      myset_t myset_if( int c, myset_t t, myset_t f ); // returns c ? t : f
      47             : 
      48             :      // Iteration
      49             :      //
      50             :      // for( myset_iter_t iter=myset_iter_init(set); !myset_iter_done(iter); iter=myset_iter_next(iter) ) {
      51             :      //   ulong idx = myset_iter_idx(iter);
      52             :      //   ... process element idx of set here
      53             :      //   ... do not touch iter
      54             :      // }
      55             :      //
      56             :      // will efficiently iterate over the elements of set in ascending
      57             :      // order.
      58             : 
      59             :      myset_iter_t myset_iter_init( myset_t      set  );
      60             :      myset_iter_t myset_iter_done( myset_iter_t iter );
      61             :      myset_iter_t myset_iter_next( myset_iter_t iter );
      62             :      ulong        myset_iter_idx ( myset_iter_t iter );
      63             :      
      64             :      // Misc
      65             :      myset_t myset_insert( myset_t x, ulong i ); // short for myset_union   ( x, myset_ele( i ) )
      66             :      myset_t myset_remove( myset_t x, ulong i ); // short for myset_subtract( x, myset_ele( i ) )
      67             : 
      68             :      myset_t myset_insert_if( int c, myset_t x, ulong i ); // Fast implementation of "c ? myset_insert( x, i ) : x;"
      69             :      myset_t myset_remove_if( int c, myset_t x, ulong i ); // Fast implementation of "c ? myset_remove( x, i ) : y;"
      70             : 
      71             :      // With the exceptions of myidx_valid_idx and myset_valid, all
      72             :      // these assume their inputs are valid and produce valid well
      73             :      // defined outputs unless explicitly noted otherwise
      74             : 
      75             :    This is safe for multiple inclusion and other options exist for fine
      76             :    tuning described below. */
      77             : 
      78             : #include "../bits/fd_bits.h"
      79             : 
      80             : #ifndef SET_NAME
      81             : #error "Define SET_NAME"
      82             : #endif
      83             : 
      84             : /* SET_TYPE is a type that behaves like a primitive integral type and
      85             :    is efficient to pass around by value.  Defaults to ulong. */
      86             : 
      87             : #ifndef SET_TYPE
      88             : #define SET_TYPE ulong
      89             : #endif
      90             : 
      91             : /* SET_MAX is an integer expression that gives the maximum number of
      92             :    elements this set can hold.  Should be [1,WIDTH_SET_TYPE].  Defaults
      93             :    to the number of bits in SET_TYPE. */
      94             : 
      95             : #ifndef SET_MAX
      96             : #define SET_MAX (8*(int)sizeof(SET_TYPE))
      97             : #endif
      98             : 
      99             : /* SET_IDX_T is the integral type used to index set elements.  Defaults
     100             :    to ulong. */
     101             : 
     102             : #ifndef SET_IDX_T
     103             : #define SET_IDX_T ulong
     104             : #endif
     105             : 
     106             : /* Define SET_POPCNT, SET_FIND_LSB AND SET_POP_LSB to the most efficient
     107             :    way to compute the population count of a small set.  Defaults to
     108             :    corresponding APIs for the SET_TYPE in fd_bits. */
     109             : 
     110             : #ifndef SET_POPCNT
     111   170948049 : #define SET_POPCNT FD_EXPAND_THEN_CONCAT3(fd_,SET_TYPE,_popcnt)
     112             : #endif
     113             : 
     114             : #ifndef SET_FIND_LSB
     115   170971095 : #define SET_FIND_LSB FD_EXPAND_THEN_CONCAT3(fd_,SET_TYPE,_find_lsb)
     116             : #endif
     117             : 
     118             : #ifndef SET_POP_LSB
     119       23814 : #define SET_POP_LSB FD_EXPAND_THEN_CONCAT3(fd_,SET_TYPE,_pop_lsb)
     120             : #endif
     121             : 
     122             : /* Implementation *****************************************************/
     123             : 
     124      113754 : #define SET_(x)FD_EXPAND_THEN_CONCAT3(SET_NAME,_,x)
     125             : 
     126             : enum {
     127             :   SET_(MAX)             = (SET_MAX),
     128             :   SET_(PRIVATE_BIT_CNT) = 8*(int)sizeof(SET_TYPE),
     129             :   SET_(PRIVATE_ZP_CNT)  = SET_(PRIVATE_BIT_CNT) - SET_(MAX)
     130             : }; 
     131             : 
     132             : FD_STATIC_ASSERT( 0<SET_(MAX) && SET_(MAX)<=SET_(PRIVATE_BIT_CNT),              range );
     133             : FD_STATIC_ASSERT( (ulong)SET_(PRIVATE_BIT_CNT)<=(1UL<<(8*sizeof(SET_IDX_T)-1)), range );
     134             : 
     135             : typedef SET_TYPE SET_(t);
     136             : typedef SET_TYPE SET_(iter_t);
     137             : 
     138             : FD_PROTOTYPES_BEGIN
     139             : 
     140           0 : FD_FN_CONST static inline SET_(t) SET_(null)( void ) { return (SET_(t))0; }
     141             : 
     142           0 : FD_FN_CONST static inline SET_(t) SET_(full)( void ) { return (SET_(t))((((SET_(t))~((SET_(t))0))) >> SET_(PRIVATE_ZP_CNT)); }
     143             : 
     144             : FD_FN_CONST static inline SET_(t)
     145           6 : SET_(full_if)( int c ) {
     146           6 :   return (SET_(t))(((SET_(t))(((SET_(t))!c)-((SET_(t))1))) & SET_(full)());
     147           6 : }
     148             : 
     149   349479024 : FD_FN_CONST static inline SET_(t) SET_(ele)   (        SET_IDX_T i ) { return (SET_(t))(((SET_(t))  1) << i);   }
     150        3402 : FD_FN_CONST static inline SET_(t) SET_(ele_if)( int c, SET_IDX_T i ) { return (SET_(t))(((SET_(t))!!c) << i);   }
     151             : 
     152           0 : FD_FN_CONST static inline SET_IDX_T SET_(max)  ( void      ) { return (SET_IDX_T)SET_(MAX);       }
     153   170948049 : FD_FN_CONST static inline SET_IDX_T SET_(cnt)  ( SET_(t) x ) { return (SET_IDX_T)SET_POPCNT(x);   }
     154   170947281 : FD_FN_CONST static inline SET_IDX_T SET_(first)( SET_(t) x ) { return (SET_IDX_T)SET_FIND_LSB(x); }
     155             : 
     156             : /* Handles >=0 for negative types too */
     157         378 : FD_FN_CONST static inline int SET_(valid_idx)( SET_IDX_T i              ) { return ((ulong)(long)i)<((ulong)SET_(MAX)); }
     158             : 
     159        1512 : FD_FN_CONST static inline int SET_(valid)    ( SET_(t)   x              ) { return !(x & ~SET_(full)());                }
     160      744828 : FD_FN_CONST static inline int SET_(is_null)  ( SET_(t)   x              ) { return !x;                                  }
     161       51837 : FD_FN_CONST static inline int SET_(is_full)  ( SET_(t)   x              ) { return x==SET_(full)();                     }
     162    21570693 : FD_FN_CONST static inline int SET_(test)     ( SET_(t)   x, SET_IDX_T i ) { return (int)((x>>i) & ((SET_(t))1));        }
     163       27411 : FD_FN_CONST static inline int SET_(eq)       ( SET_(t)   x, SET_(t)   y ) { return x==y;                                }
     164        3024 : FD_FN_CONST static inline int SET_(subset)   ( SET_(t)   x, SET_(t)   y ) { return x==(x & y);                          }
     165             : 
     166         756 : FD_FN_CONST static inline SET_(t) SET_(copy)      ( SET_(t) x ) { return x;                }
     167         756 : FD_FN_CONST static inline SET_(t) SET_(complement)( SET_(t) x ) { return x ^ SET_(full)(); }
     168             : 
     169        3213 : FD_FN_CONST static inline SET_(t) SET_(union)    ( SET_(t) x, SET_(t) y ) { return x | y;  }
     170      747276 : FD_FN_CONST static inline SET_(t) SET_(intersect)( SET_(t) x, SET_(t) y ) { return x & y;  }
     171        3213 : FD_FN_CONST static inline SET_(t) SET_(subtract) ( SET_(t) x, SET_(t) y ) { return (SET_(t))(x & ~y); }
     172        3024 : FD_FN_CONST static inline SET_(t) SET_(xor)      ( SET_(t) x, SET_(t) y ) { return x ^  y;  }
     173             : 
     174        6048 : FD_FN_CONST static inline SET_(t) SET_(if)( int c, SET_(t) t, SET_(t) f ) { return c ? t : f; }
     175             : 
     176         756 : FD_FN_CONST static inline SET_(iter_t) SET_(iter_init)( SET_(t)      set  ) { return set;                             }
     177       24570 : FD_FN_CONST static inline SET_(iter_t) SET_(iter_done)( SET_(iter_t) iter ) { return !iter;                           }
     178       23814 : FD_FN_CONST static inline SET_(iter_t) SET_(iter_next)( SET_(iter_t) iter ) { return SET_POP_LSB(  iter );            }
     179       23814 : FD_FN_CONST static inline SET_IDX_T    SET_(iter_idx) ( SET_(iter_t) iter ) { return (SET_IDX_T)SET_FIND_LSB( iter ); }
     180             : 
     181       55296 : FD_FN_CONST static inline SET_(t) SET_(insert)( SET_(t) x, SET_IDX_T i ) { return x | SET_(ele)(i); }
     182         945 : FD_FN_CONST static inline SET_(t) SET_(remove)( SET_(t) x, SET_IDX_T i ) { return (SET_(t))(x & ~SET_(ele)(i)); }
     183             : 
     184        1512 : FD_FN_CONST static inline SET_(t) SET_(insert_if)( int c, SET_(t) x, SET_IDX_T i ) { return x | SET_(ele_if)(c,i); }
     185        1512 : FD_FN_CONST static inline SET_(t) SET_(remove_if)( int c, SET_(t) x, SET_IDX_T i ) { return (SET_(t))(x & ~SET_(ele_if)(c,i)); }
     186             : 
     187             : FD_PROTOTYPES_END
     188             : 
     189             : #undef SET_
     190             : 
     191             : #undef SET_POP_LSB
     192             : #undef SET_FIND_LSB
     193             : #undef SET_POPCNT
     194             : #undef SET_MAX
     195             : #undef SET_TYPE
     196             : #undef SET_NAME
     197             : 

Generated by: LCOV version 1.14