LCOV - code coverage report
Current view: top level - util/bits - fd_sat.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 43 55 78.2 %
Date: 2024-11-13 11:58:15 Functions: 65 7476 0.9 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_bits_fd_sat_h
       2             : #define HEADER_fd_src_util_bits_fd_sat_h
       3             : 
       4             : #include "fd_bits.h"
       5             : 
       6             : /* Set of primitives for saturating math operations, mimicking the behaviour
       7             :    of Rust's primitive `saturating_add`, `saturating_sub`, `saturating_mul` operations.
       8             :    These saturate at the boundaries of the integer representation, instead of overflowing
       9             :    or underflowing.
      10             : 
      11             :    Note that this is a placeholder API, and the implementations will be optimised and
      12             :    hardened in the future.  The intent of this is to provide an abstraction for saturating
      13             :    operations which can be used throughout the codebase, providing a single place to optimize
      14             :    these. */
      15             : 
      16             : FD_PROTOTYPES_BEGIN
      17             : 
      18             : #if FD_HAS_INT128
      19             : 
      20             : FD_FN_CONST static inline __uint128_t
      21   300000009 : fd_uint128_sat_add( __uint128_t x, __uint128_t y ) {
      22   300000009 :   __uint128_t res = x + y;
      23   300000009 :   return fd_uint128_if( res < x, UINT128_MAX, res );
      24   300000009 : }
      25             : 
      26             : FD_FN_CONST static inline __uint128_t
      27   300000009 : fd_uint128_sat_mul( __uint128_t x, __uint128_t y ) {
      28   300000009 :   __uint128_t res = x * y;
      29   300000009 :   uchar overflow = ( x != 0 ) && ( y != 0 ) && ( ( res < x ) || ( res < y ) || ( ( res / x ) != y ) );
      30   300000009 :   return fd_uint128_if( overflow, UINT128_MAX, res );
      31   300000009 : }
      32             : 
      33             : FD_FN_CONST static inline __uint128_t
      34   300000006 : fd_uint128_sat_sub( __uint128_t x, __uint128_t y ) {
      35   300000006 :   __uint128_t res = x - y;
      36   300000006 :   return fd_uint128_if( res > x, 0, res );
      37   300000006 : }
      38             : 
      39             : #endif /* FD_HAS_INT128 */
      40             : 
      41             : FD_FN_CONST static inline ulong
      42   300864948 : fd_ulong_sat_add( ulong x, ulong y ) {
      43   300864948 :   ulong res;
      44   300864948 :   int cf = __builtin_uaddl_overflow ( x, y, &res );
      45   300864948 :   return fd_ulong_if( cf, ULONG_MAX, res );
      46   300864948 : }
      47             : 
      48             : FD_FN_CONST static inline ulong
      49   300022611 : fd_ulong_sat_mul( ulong x, ulong y ) {
      50   300022611 :   ulong res;
      51   300022611 :   int cf = __builtin_umull_overflow ( x, y, &res );
      52   300022611 :   return fd_ulong_if( cf, ULONG_MAX, res );
      53   300022611 : }
      54             : 
      55             : FD_FN_CONST static inline ulong
      56   388086104 : fd_ulong_sat_sub( ulong x, ulong y ) {
      57   388086104 :   ulong res;
      58   388086104 :   int cf = __builtin_usubl_overflow ( x, y, &res );
      59   388086104 :   return fd_ulong_if( cf, 0UL, res );
      60   388086104 : }
      61             : 
      62             : FD_FN_CONST static inline uint
      63   300000027 : fd_uint_sat_add( uint x, uint y ) {
      64   300000027 :   uint res;
      65   300000027 :   int cf = __builtin_uadd_overflow ( x, y, &res );
      66   300000027 :   return fd_uint_if( cf, UINT_MAX, res );
      67   300000027 : }
      68             : 
      69             : FD_FN_CONST static inline uint
      70   300006057 : fd_uint_sat_mul( uint x, uint y ) {
      71   300006057 :   uint res;
      72   300006057 :   int cf = __builtin_umul_overflow ( x, y, &res );
      73   300006057 :   return fd_uint_if( cf, UINT_MAX, res );
      74   300006057 : }
      75             : 
      76             : FD_FN_CONST static inline uint
      77   300000060 : fd_uint_sat_sub( uint x, uint y ) {
      78   300000060 :   uint res;
      79   300000060 :   int cf = __builtin_usub_overflow ( x, y, &res );
      80   300000060 :   return fd_uint_if( cf, 0U, res );
      81   300000060 : }
      82             : 
      83             : FD_FN_CONST static inline double
      84           0 : fd_double_sat_add( double x, double y ) {
      85           0 :   // What does rust do here?
      86           0 :   return x + y;
      87           0 : }
      88             : 
      89             : FD_FN_CONST static inline double
      90           0 : fd_double_sat_mul( double x, double y ) {
      91           0 :   // What does rust do here?
      92           0 :   return x * y;
      93           0 : }
      94             : 
      95             : FD_FN_CONST static inline double
      96           0 : fd_double_sat_sub( double x, double y ) {
      97           0 :   // What does rust do here?
      98           0 :   return x - y;
      99           0 : }
     100             : 
     101             : FD_PROTOTYPES_END
     102             : 
     103             : #endif /* HEADER_fd_src_util_bits_fd_sat_h */

Generated by: LCOV version 1.14