Line data Source code
1 : #ifndef HEADER_fd_src_disco_gui_fd_gui_ema_h 2 : #define HEADER_fd_src_disco_gui_fd_gui_ema_h 3 : 4 : #include "../../util/fd_util_base.h" 5 : 6 : #include <float.h> 7 : #include <math.h> 8 : 9 : struct fd_gui_ema { 10 : double value; /* filtered value */ 11 : double weight; /* used for Adam-style startup debiasing */ 12 : long last_update_nanos; /* last recorded sample timestamp */ 13 : long half_life_nanos; /* Time horizon for the filter */ 14 : }; 15 : 16 : typedef struct fd_gui_ema fd_gui_ema_t; 17 : 18 : static inline void 19 : fd_gui_ema_init( fd_gui_ema_t * ema, 20 : long now_nanos, 21 0 : long half_life_nanos ) { 22 0 : ema->value = 0.0; 23 0 : ema->weight = 0.0; 24 0 : ema->last_update_nanos = now_nanos; 25 0 : ema->half_life_nanos = half_life_nanos; 26 0 : } 27 : 28 : static inline double 29 : fd_gui_ema_alpha( long dt_nanos, 30 0 : long half_life_nanos ) { 31 0 : return 1.0 - exp( -0.69314718055994 * (double)dt_nanos / (double)half_life_nanos ); 32 0 : } 33 : 34 : static inline double 35 : fd_gui_ema_advance_alpha( fd_gui_ema_t * ema, 36 : long now_nanos, 37 : double sample, 38 0 : double alpha ) { 39 0 : double new_weight = fmax( alpha + (1.0 - alpha) * ema->weight, DBL_EPSILON ); 40 0 : ema->value = (alpha * sample + (1.0 - alpha) * ema->weight * ema->value) / new_weight; 41 0 : ema->weight = new_weight; 42 0 : ema->last_update_nanos = now_nanos; 43 0 : return ema->value; 44 0 : } 45 : 46 : static inline double 47 : fd_gui_ema_advance( fd_gui_ema_t * ema, 48 : long now_nanos, 49 0 : double sample ) { 50 0 : long dt = now_nanos - ema->last_update_nanos; 51 0 : if( FD_UNLIKELY( dt<=0L ) ) return ema->value; 52 0 : return fd_gui_ema_advance_alpha( ema, now_nanos, sample, fd_gui_ema_alpha( dt, ema->half_life_nanos ) ); 53 0 : } 54 : 55 : static inline double 56 : fd_gui_ema_value( fd_gui_ema_t const * ema, 57 : long now_nanos, 58 0 : double sample ) { 59 0 : fd_gui_ema_t cpy = *ema; 60 0 : return fd_gui_ema_advance( &cpy, now_nanos, sample ); 61 0 : } 62 : 63 : #endif /* HEADER_fd_src_disco_gui_fd_gui_ema_h */