diff options
Diffstat (limited to 'lib/ulcer_index.c')
| -rw-r--r-- | lib/ulcer_index.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/ulcer_index.c b/lib/ulcer_index.c new file mode 100644 index 0000000..ca70734 --- /dev/null +++ b/lib/ulcer_index.c @@ -0,0 +1,76 @@ +// Ulcer Index +// +// ulcer_index +// +// Ulcer Index +// +// +// +// Inputs: 1 +// Outputs: 1 +// Constants: 1 + + +#include <math.h> +#include <stdlib.h> +#include "ts.h" + +typedef struct { + uint_t k; +} ts_ulcer_index_params_t; + +ts_parameter_t const ts_ulcer_index_p = { .n_inputs = 1, .n_outputs = 1, .n_constants = 1, .params_size = sizeof(ts_ulcer_index_params_t) }; + +uint_t ts_ulcer_index_offset( ts_constant_t const *c ) +{ + ( void )c; + return ( c ? ((ts_ulcer_index_params_t *)c)->k > 0 ? ((ts_ulcer_index_params_t *)c)->k - 1 : 0 : 0 ); +} + +int ts_ulcer_index( + fp_t * const *y, uint_t y_n, + fp_t const * const *x, uint_t x_n, + uint_t n, ts_constant_t const *c +) +{ + TS_PROLOGUE( ts_ulcer_index_p ); + if ( !c ) return -1; + uint_t k = ((ts_ulcer_index_params_t *)c)->k; + if (k == 0 || n < k) return -1; + + /* Precompute cumulative highest-high for each index: O(n) */ + fp_t *cum_hhv = calloc( n, sizeof( fp_t ) ); + if ( !cum_hhv ) return -1; + { + fp_t hh = x[0][0]; + for ( uint_t i = 0; i < n; ++i ) + { + if ( x[0][i] > hh ) hh = x[0][i]; + cum_hhv[i] = hh; + } + } + + for( uint_t i = k - 1; i < n; ++i ) + { + fp_t hhv = x[0][i - k + 1]; + for( uint_t j = 1; j < k; ++j ) + { + fp_t v = x[0][i - k + 1 + j]; + if (v > hhv) hhv = v; + } + + fp_t d_sq_sum = 0; + for( uint_t j = 0; j < k; ++j ) + { + uint_t idx = i - k + 1 + j; + fp_t ch = cum_hhv[idx]; + fp_t d = ch > 0 ? ( ch - x[0][idx] ) / ch * 100.0 : 0; + d_sq_sum += d * d; + } + y[0][i] = sqrt( d_sq_sum / (fp_t)k ); + } + + free( cum_hhv ); + return 0; +} + |