// Fractal Chaos Bands // // fractal_chaos_bands // // Elder's Fractal Chaos Bands using fractal channels // // Upper/Lower: fractal-based channel boundaries // // Inputs: 4 // Outputs: 2 // Constants: 1 #include "ts.h" typedef struct { uint_t k; } ts_fractal_chaos_bands_params_t; ts_parameter_t const ts_fractal_chaos_bands_p = { .n_inputs = 4, .n_outputs = 2, .n_constants = 1, .params_size = sizeof(ts_fractal_chaos_bands_params_t) }; uint_t ts_fractal_chaos_bands_offset( ts_constant_t const *c ) { ( void )c; return ( c ? ((ts_fractal_chaos_bands_params_t *)c)->k / 2 : 0 ); } int ts_fractal_chaos_bands( 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_fractal_chaos_bands_p ); if ( !c ) return -1; uint_t k = ((ts_fractal_chaos_bands_params_t *)c)->k; if (k == 0 || n < k) return -1; fp_t alpha = 2.0 / (k + 1.0); uint_t half_k = k / 2; fp_t ema_upper = 0; fp_t ema_lower = 0; uint_t ema_count = 0; for (uint_t i = half_k; i < n - half_k; ++i) { fp_t fh = x[1][i]; fp_t fl = x[2][i]; for (int_t j = -(int_t)half_k; j <= (int_t)half_k; ++j) { uint_t idx = (uint_t)((int_t)i + j); if (x[1][idx] > fh) fh = x[1][idx]; if (x[2][idx] < fl) fl = x[2][idx]; } if (ema_count == 0) { ema_upper = fh; ema_lower = fl; } else { ema_upper = ema_upper + alpha * (fh - ema_upper); ema_lower = ema_lower + alpha * (fl - ema_lower); } ema_count++; y[0][i] = ema_upper; y[1][i] = ema_lower; } return 0; }