summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile37
-rw-r--r--README.md4
-rw-r--r--lib/acceleration_bands.c6
-rw-r--r--lib/ad.c1
-rw-r--r--lib/ad_oscillator.c5
-rw-r--r--lib/adx.c4
-rw-r--r--lib/alligator.c1
-rw-r--r--lib/annualized_historical_volatility.c8
-rw-r--r--lib/apo.c7
-rw-r--r--lib/aroon.c4
-rw-r--r--lib/aroon_oscillator.c4
-rw-r--r--lib/asi.c1
-rw-r--r--lib/atr.c4
-rw-r--r--lib/atr_bands.c15
-rw-r--r--lib/atr_trailing_stops.c14
-rw-r--r--lib/average.c4
-rw-r--r--lib/average_exponential.c2
-rw-r--r--lib/average_exponential_double.c4
-rw-r--r--lib/average_exponential_triple.c4
-rw-r--r--lib/average_triangle.c4
-rw-r--r--lib/average_weighted.c4
-rw-r--r--lib/average_weighted_series.c4
-rw-r--r--lib/band_width.c8
-rw-r--r--lib/beta_pdf.c4
-rw-r--r--lib/binomial_pdf.c4
-rw-r--r--lib/bollinger_bands.c23
-rw-r--r--lib/bollinger_lower.c6
-rw-r--r--lib/bollinger_pctb.c9
-rw-r--r--lib/bollinger_upper.c9
-rw-r--r--lib/bollinger_width.c9
-rw-r--r--lib/cci.c4
-rw-r--r--lib/center_of_gravity.c4
-rw-r--r--lib/chande_forecast_oscillator.c4
-rw-r--r--lib/change.c4
-rw-r--r--lib/channel.c4
-rw-r--r--lib/chebyshev_t.c52
-rw-r--r--lib/chi_squared_pdf.c2
-rw-r--r--lib/choppiness_index.c4
-rw-r--r--lib/close_to_high.c1
-rw-r--r--lib/close_to_open_ratio.c1
-rw-r--r--lib/cmf.c4
-rw-r--r--lib/cmo.c4
-rw-r--r--lib/coppock_curve.c6
-rw-r--r--lib/correlation_coefficient.c4
-rw-r--r--lib/cv.c10
-rw-r--r--lib/darvas_box.c4
-rw-r--r--lib/decay_exponential.c7
-rw-r--r--lib/decay_linear.c56
-rw-r--r--lib/delta.c4
-rw-r--r--lib/deviation_average.c4
-rw-r--r--lib/deviation_standard.c4
-rw-r--r--lib/deviation_standard_average_exponential.c3
-rw-r--r--lib/deviation_vector.c4
-rw-r--r--lib/di_minus.c4
-rw-r--r--lib/di_plus.c4
-rw-r--r--lib/disparity_index.c4
-rw-r--r--lib/donchian_channel.c4
-rw-r--r--lib/donchian_width.c4
-rw-r--r--lib/dpo.c4
-rw-r--r--lib/dx.c4
-rw-r--r--lib/ease_of_movement.c2
-rw-r--r--lib/elder_force_index.c2
-rw-r--r--lib/elder_impulse.c4
-rw-r--r--lib/elder_ray.c2
-rw-r--r--lib/ema_variable.c3
-rw-r--r--lib/envelope.c6
-rw-r--r--lib/exponential.c2
-rw-r--r--lib/factorial.c3
-rw-r--r--lib/fill_indicator.c4
-rw-r--r--lib/fisher_transform.c4
-rw-r--r--lib/fractal_chaos_bands.c12
-rw-r--r--lib/fractal_chaos_oscillator.c4
-rw-r--r--lib/gamma_pdf.c2
-rw-r--r--lib/gcd.c31
-rw-r--r--lib/gopalakrishnan_range_index.c4
-rw-r--r--lib/harmonic.c6
-rw-r--r--lib/high_low_bands.c4
-rw-r--r--lib/highest_high.c4
-rw-r--r--lib/historical_volatility.c4
-rw-r--r--lib/hull_ma.c4
-rw-r--r--lib/hurst_exponent.c2
-rw-r--r--lib/ichimoku.c2
-rw-r--r--lib/kalman_filter.c5
-rw-r--r--lib/kaufman_adaptive_ma.c4
-rw-r--r--lib/keltner_channel.c4
-rw-r--r--lib/kvo.c6
-rw-r--r--lib/lag.c6
-rw-r--r--lib/lcm.c52
-rw-r--r--lib/linear_regression.c4
-rw-r--r--lib/linear_regression_angle.c4
-rw-r--r--lib/linear_regression_forecast.c4
-rw-r--r--lib/linear_regression_intercept.c4
-rw-r--r--lib/linear_regression_r2.c4
-rw-r--r--lib/linear_regression_slope.c4
-rw-r--r--lib/linear_weighted_ma.c4
-rwxr-xr-xlib/logarithm.c4
-rw-r--r--lib/lowest_low.c4
-rw-r--r--lib/macd.c18
-rwxr-xr-xlib/maximum.c4
-rw-r--r--lib/mesa_sine_wave.c50
-rw-r--r--lib/mfi.c4
-rw-r--r--lib/midpoint.c4
-rw-r--r--lib/midprice.c4
-rwxr-xr-xlib/minimum.c4
-rw-r--r--lib/minmax.c4
-rw-r--r--lib/missing_bar_count.c3
-rw-r--r--lib/momentum.c4
-rw-r--r--lib/moving_linear_regression.c4
-rw-r--r--lib/moving_linear_regression_r2.c4
-rw-r--r--lib/natr.c8
-rw-r--r--lib/nvi.c1
-rw-r--r--lib/obv.c1
-rw-r--r--lib/on_balance_volume_rate.c4
-rw-r--r--lib/oscillator_cross.c7
-rw-r--r--lib/osma.c9
-rw-r--r--lib/parabolic_sar.c5
-rw-r--r--lib/performance_ratio.c6
-rw-r--r--lib/poisson_pdf.c2
-rw-r--r--lib/polynomial.c2
-rwxr-xr-xlib/power.c2
-rw-r--r--lib/ppo.c9
-rw-r--r--lib/pretty_good_oscillator.c2
-rw-r--r--lib/price_channel.c4
-rw-r--r--lib/price_momentum_oscillator.c4
-rw-r--r--lib/price_rate_of_change.c4
-rw-r--r--lib/prime_number_bands.c4
-rw-r--r--lib/prings_special_k.c6
-rw-r--r--lib/psychological_line.c4
-rw-r--r--lib/pvi.c3
-rw-r--r--lib/qstick.c4
-rw-r--r--lib/rainbow_oscillator.c2
-rw-r--r--lib/random_walk_index.c4
-rw-r--r--lib/rank.c4
-rwxr-xr-xlib/ratio.c4
-rw-r--r--lib/ravi.c18
-rwxr-xr-xlib/regression_linear_least_squares.c4
-rw-r--r--lib/relative_volatility.c4
-rw-r--r--lib/roc.c4
-rw-r--r--lib/rocp.c4
-rw-r--r--lib/rocr.c4
-rw-r--r--lib/rocr100.c4
-rwxr-xr-xlib/root.c2
-rw-r--r--lib/rsi.c4
-rw-r--r--lib/schaff_trend_cycle.c3
-rw-r--r--lib/shinohara_intensity_ratio.c4
-rw-r--r--lib/sigmoid.c7
-rwxr-xr-xlib/slope.c4
-rw-r--r--lib/softplus.c7
-rw-r--r--lib/standard_error.c4
-rw-r--r--lib/starc_bands.c15
-rw-r--r--lib/starc_lower.c8
-rw-r--r--lib/starc_upper.c6
-rw-r--r--lib/std_error.c4
-rw-r--r--lib/stoch_rsi.c6
-rw-r--r--lib/stochastic_fast.c4
-rw-r--r--lib/stochastic_momentum_index.c8
-rw-r--r--lib/stochastic_slow.c4
-rw-r--r--lib/student_t_pdf.c2
-rwxr-xr-xlib/summation.c4
-rw-r--r--lib/supertrend.c6
-rw-r--r--lib/swish.c7
-rw-r--r--lib/synthetic_yield.c5
-rw-r--r--lib/t3.c1
-rwxr-xr-xlib/test.c51
-rw-r--r--lib/trade_volume_index.c26
-rw-r--r--lib/trend_intensity_index.c4
-rwxr-xr-xlib/trix.c3
-rwxr-xr-xlib/ts.c91
-rw-r--r--lib/ulcer_index.c10
-rw-r--r--lib/valuation_lines.c4
-rw-r--r--lib/variable_index_dynamic_average.c4
-rwxr-xr-xlib/variance.c4
-rwxr-xr-xlib/variance_exponential.c3
-rw-r--r--lib/vertical_horizontal_filter.c4
-rw-r--r--lib/volatility_stop.c14
-rw-r--r--lib/volatility_system.c8
-rw-r--r--lib/volume_moving_average.c4
-rw-r--r--lib/volume_oscillator.c7
-rw-r--r--lib/volume_rate_of_change.c4
-rw-r--r--lib/volume_weighted_moving_average.c4
-rw-r--r--lib/vortex_indicator.c4
-rw-r--r--lib/vwap_period.c4
-rw-r--r--lib/weibull_pdf.c2
-rw-r--r--lib/wilders_smoothing.c3
-rw-r--r--lib/williams_r.c4
-rw-r--r--lib/zero_lag_ema.c4
-rw-r--r--lib/zigzag.c3
-rwxr-xr-xmain.c19
-rw-r--r--scripts/gen_bindings.py21
-rw-r--r--scripts/gen_registry.py13
-rw-r--r--scripts/ts_parser.py35
-rw-r--r--test/adx.c14
-rw-r--r--test/awesome_oscillator.c5
-rw-r--r--test/bench.c1
-rw-r--r--test/bollinger_bands.c2
-rw-r--r--test/cv.c3
-rw-r--r--test/edge_cases.c1
-rw-r--r--test/fuzz.c6
-rw-r--r--test/gen_test_data.c7
-rw-r--r--test/hurst_exponent.c14
-rw-r--r--test/main.c4
-rw-r--r--test/nextafter.c6
-rw-r--r--test/nexttoward.c6
-rw-r--r--test/nvi.c2
-rw-r--r--test/test_python.py52
-rw-r--r--ts.c45
-rw-r--r--ts.h53
207 files changed, 881 insertions, 725 deletions
diff --git a/Makefile b/Makefile
index 572e23b..7a8753c 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ ifeq ($(PYTHON3),)
endif
# Base flags
-CFLAGS_BASE = -std=c11 -Wall -Wextra -Wshadow -Wdouble-promotion -Wnull-dereference -Wimplicit-fallthrough -Wmisleading-indentation -pedantic -O2 -I. -Ilib -MMD -MP
+CFLAGS_BASE = -std=c11 -Wall -Wextra -Wshadow -Wdouble-promotion -Wnull-dereference -Wimplicit-fallthrough -Wmisleading-indentation -Wstrict-aliasing=2 -pedantic -O2 -I. -Ilib -MMD -MP
# Platform-specific
UNAME_S := $(shell uname -s)
@@ -18,13 +18,14 @@ else ifeq ($(UNAME_S),Darwin)
CFLAGS_BASE += -D_DARWIN_C_SOURCE
else
# BSD and others
- CFLAGS_BASE += -D_BSD_SOURCE
+ CFLAGS_BASE += -D_DEFAULT_SOURCE
endif
# Security hardening (optimized builds only)
CFLAGS_HARDENING = -D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wformat-security -fno-common
CFLAGS := $(CFLAGS_BASE) $(CFLAGS_HARDENING)
+LDFLAGS ?=
LDLIBS = -lm
SRCDIR = lib
@@ -72,7 +73,7 @@ else
endif
$(SHLIB): $(SHARED_OBJS) $(SHARED_TS_OBJ) $(FLAT_OBJ) $(REG_OBJ) | $(BUILDDIR)
- $(CC) -shared $(SHLIB_SONAME) -Wl,-rpath,'$$ORIGIN' -o $@ $^ $(LDLIBS)
+ $(CC) $(LDFLAGS) -shared $(SHLIB_SONAME) -Wl,-rpath,'$$ORIGIN' -o $@ $^ $(LDLIBS)
$(BUILDDIR):
@mkdir -p $@
@@ -90,25 +91,25 @@ $(BUILDDIR)/ts.so.o: ts.c | $(BUILDDIR)
$(CC) $(CFLAGS) -fPIC -c ts.c -o $@
ts_generated.h: $(SCRIPTDIR)/gen_all.py $(filter-out $(SRCDIR)/ts_flat_generated.c $(SRCDIR)/ts_registry_generated.c,$(wildcard $(SRCDIR)/*.c))
- python3 $< || (echo "ERROR: gen_all.py failed" && exit 1)
+ $(PYTHON3) $< || (echo "ERROR: gen_all.py failed" && exit 1)
test/main_generated.c: ts_generated.h
- @touch $@
+ $(PYTHON3) $(SCRIPTDIR)/gen_all.py || (echo "ERROR: gen_all.py failed" && exit 1)
$(SRCDIR)/ts_flat_generated.c: $(SCRIPTDIR)/gen_flat.py $(filter-out $(SRCDIR)/ts_flat_generated.c $(SRCDIR)/ts_registry_generated.c,$(wildcard $(SRCDIR)/*.c))
- python3 $< || (echo "ERROR: gen_flat.py failed" && exit 1)
+ $(PYTHON3) $< || (echo "ERROR: gen_flat.py failed" && exit 1)
$(FLAT_OBJ): $(SRCDIR)/ts_flat_generated.c ts.h | $(BUILDDIR)
$(CC) $(CFLAGS) -fPIC -c $< -o $@
$(SRCDIR)/ts_registry_generated.c: $(SCRIPTDIR)/gen_registry.py $(filter-out $(SRCDIR)/ts_registry_generated.c $(SRCDIR)/ts_flat_generated.c,$(wildcard $(SRCDIR)/*.c))
- python3 $< || (echo "ERROR: gen_registry.py failed" && exit 1)
+ $(PYTHON3) $< || (echo "ERROR: gen_registry.py failed" && exit 1)
$(REG_OBJ): $(SRCDIR)/ts_registry_generated.c ts.h | $(BUILDDIR)
$(CC) $(CFLAGS) -fPIC -c $< -o $@
$(TESTDIR)/fuzz_table_generated.c: $(SCRIPTDIR)/gen_fuzz.py $(filter-out $(SRCDIR)/ts_flat_generated.c $(SRCDIR)/ts_registry_generated.c,$(wildcard $(SRCDIR)/*.c))
- python3 $< || (echo "ERROR: gen_fuzz.py failed" && exit 1)
+ $(PYTHON3) $< || (echo "ERROR: gen_fuzz.py failed" && exit 1)
$(BUILDDIR)/test/fuzz.o: $(TESTDIR)/fuzz.c $(TESTDIR)/fuzz_table_generated.c ts.h | $(TEST_BUILDDIR)
$(CC) $(CFLAGS) -DTS_IMPLEMENTATION -c $< -o $@
@@ -117,34 +118,34 @@ $(TEST_BUILDDIR):
@mkdir -p $@
$(BUILDDIR)/test/%.o: $(TESTDIR)/%.c ts.h | $(TEST_BUILDDIR)
- $(CC) $(CFLAGS) -DTS_IMPLEMENTATION -c $< -o $@
+ $(CC) $(CFLAGS) -DTS_IMPLEMENTATION -Wno-strict-aliasing -c $< -o $@
$(MAIN): $(OBJS) $(TS_OBJ) main.c | $(BUILDDIR)
- $(CC) $(CFLAGS) main.c $(OBJS) $(TS_OBJ) -o $@ $(LDLIBS)
+ $(CC) $(CFLAGS) main.c $(OBJS) $(TS_OBJ) $(LDFLAGS) -o $@ $(LDLIBS)
$(TEST_BIN): $(OBJS) $(TEST_OBJS) $(TS_OBJ) | $(BUILDDIR)
- $(CC) $(CFLAGS) $(TEST_OBJS) $(OBJS) $(TS_OBJ) -o $@ $(LDLIBS)
+ $(CC) $(CFLAGS) $(TEST_OBJS) $(OBJS) $(TS_OBJ) $(LDFLAGS) -o $@ $(LDLIBS)
test: $(TEST_BIN)
./$(TEST_BIN)
$(BENCH_BIN): $(OBJS) $(TS_OBJ) test/bench.c | $(BUILDDIR)
- $(CC) $(CFLAGS) test/bench.c $(OBJS) $(TS_OBJ) -o $@ $(LDLIBS)
+ $(CC) $(CFLAGS) test/bench.c $(OBJS) $(TS_OBJ) $(LDFLAGS) -o $@ $(LDLIBS)
bench: $(BENCH_BIN)
./$(BENCH_BIN)
python/ts/__init__.py: $(SCRIPTDIR)/gen_bindings.py $(SCRIPTDIR)/ts_parser.py $(filter-out $(SRCDIR)/ts_flat_generated.c $(SRCDIR)/ts_registry_generated.c,$(wildcard $(SRCDIR)/*.c))
- python3 $(SCRIPTDIR)/gen_bindings.py || (echo "ERROR: gen_bindings.py failed" && exit 1)
+ $(PYTHON3) $(SCRIPTDIR)/gen_bindings.py || (echo "ERROR: gen_bindings.py failed" && exit 1)
gen-bindings: python/ts/__init__.py
test-python: shared gen-bindings
- LD_LIBRARY_PATH=$(BUILDDIR):$$LD_LIBRARY_PATH python3 $(TESTDIR)/test_python.py
+ LD_LIBRARY_PATH=$(BUILDDIR):$$LD_LIBRARY_PATH $(PYTHON3) $(TESTDIR)/test_python.py
check:
$(MAKE) clean
- $(MAKE) test CFLAGS="$(CFLAGS_BASE) $(CFLAGS_HARDENING) -Werror"
+ $(MAKE) test CFLAGS="$(CFLAGS_BASE) $(CFLAGS_HARDENING) -Werror -Wno-error=strict-aliasing"
test-one: $(OBJS) $(TS_OBJ)
ifndef TEST
@@ -153,8 +154,8 @@ endif
@echo "$(TEST)" | grep -qE '^[a-z0-9_]+$$' || { echo "ERROR: TEST must match [a-z0-9_]+"; exit 1; }
@mkdir -p $(BUILDDIR)
@printf '#include <stdbool.h>\nextern bool ts_test_$(TEST)(void);\nint main(void){return ts_test_$(TEST)() ? 0 : 1;}\n' > $(BUILDDIR)/stub.c
- $(CC) $(CFLAGS) -DTS_IMPLEMENTATION $(BUILDDIR)/stub.c $(TESTDIR)/$(TEST).c $(OBJS) $(TS_OBJ) -o $(BUILDDIR)/test_$(TEST) $(LDLIBS)
- ./$(BUILDDIR)/test_$(TEST)
+ $(CC) $(CFLAGS) -DTS_IMPLEMENTATION $(BUILDDIR)/stub.c $(TESTDIR)/$(TEST).c $(OBJS) $(TS_OBJ) $(LDFLAGS) -o $(BUILDDIR)/test_$(TEST) $(LDLIBS)
+ @RET=0; ./$(BUILDDIR)/test_$(TEST) || RET=$$?; rm -f $(BUILDDIR)/stub.c $(BUILDDIR)/test_$(TEST); exit $$RET
valgrind: $(TEST_BIN)
valgrind --leak-check=full --error-exitcode=1 ./$(TEST_BIN)
@@ -196,7 +197,9 @@ clean:
distclean: clean
rm -f $(SRCDIR)/ts_flat_generated.c
+ rm -f $(SRCDIR)/ts_registry_generated.c
rm -f $(TESTDIR)/fuzz_table_generated.c
+ rm -f $(TESTDIR)/main_generated.c
rm -f ts_generated.h
rm -f python/ts/__init__.py
diff --git a/README.md b/README.md
index fe8a3e2..98f3f90 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# ts — Time Series Analysis Library
-C11 library of 354 financial and mathematical time-series indicators.
+C11 library of 349 financial and mathematical time-series indicators.
-The library provides 354 indicators covering moving averages, oscillators,
+The library provides 349 indicators covering moving averages, oscillators,
volatility measures, statistical functions, and more. See the source files
in `lib/` for the complete list.
diff --git a/lib/acceleration_bands.c b/lib/acceleration_bands.c
index 776b990..19c174a 100644
--- a/lib/acceleration_bands.c
+++ b/lib/acceleration_bands.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_acceleration_bands_p = { .n_inputs = 4, .n_outputs = 3,
uint_t ts_acceleration_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_acceleration_bands_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_acceleration_bands_params_t const *)c)->k - 1 : 0 );
}
int ts_acceleration_bands(
@@ -33,9 +33,11 @@ int ts_acceleration_bands(
{
TS_PROLOGUE( ts_acceleration_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_acceleration_bands_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_acceleration_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
+ if (n > SIZE_MAX / sizeof( fp_t )) return -1;
fp_t *hh_r = malloc( n * sizeof( fp_t ) );
fp_t *ll_r = malloc( n * sizeof( fp_t ) );
fp_t *tp = malloc( n * sizeof( fp_t ) );
diff --git a/lib/ad.c b/lib/ad.c
index fd0e40e..875f827 100644
--- a/lib/ad.c
+++ b/lib/ad.c
@@ -27,7 +27,6 @@ int ts_ad(
{
TS_PROLOGUE( ts_ad_p );
(void)c;
- if( n == 0 ) return -1;
fp_t hl0 = ts_h( x, 0 ) - ts_l( x, 0 );
y[0][0] = hl0 != 0
diff --git a/lib/ad_oscillator.c b/lib/ad_oscillator.c
index 5021140..66ca3cf 100644
--- a/lib/ad_oscillator.c
+++ b/lib/ad_oscillator.c
@@ -31,10 +31,9 @@ int ts_ad_oscillator(
{
TS_PROLOGUE( ts_ad_oscillator_p );
if ( !c ) return -1;
- if( n == 0 ) return -1;
- fp_t fast = ((ts_ad_oscillator_params_t *)c)->fast;
- fp_t slow = ((ts_ad_oscillator_params_t *)c)->slow;
+ fp_t fast = ((ts_ad_oscillator_params_t const *)c)->fast;
+ fp_t slow = ((ts_ad_oscillator_params_t const *)c)->slow;
if (fast == 0 || slow == 0) return -1;
fp_t a_fast = 1.0 / fast;
fp_t a_slow = 1.0 / slow;
diff --git a/lib/adx.c b/lib/adx.c
index 505732b..a6700cf 100644
--- a/lib/adx.c
+++ b/lib/adx.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_adx_p = { .n_inputs = 4, .n_outputs = 4, .n_constants =
uint_t ts_adx_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_adx_params_t *)c)->k + 1 : 0 );
+ return ( c ? ((ts_adx_params_t const *)c)->k + 1 : 0 );
}
int ts_adx(
@@ -36,7 +36,7 @@ int ts_adx(
TS_PROLOGUE( ts_adx_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_adx_params_t *)c)->k;
+ uint_t k = ((ts_adx_params_t const *)c)->k;
if (k == 0) return -1;
fp_t ema_plus = 0, ema_minus = 0, ema_tr = 0;
diff --git a/lib/alligator.c b/lib/alligator.c
index 81450b0..a74602c 100644
--- a/lib/alligator.c
+++ b/lib/alligator.c
@@ -28,7 +28,6 @@ int ts_alligator(
{
TS_PROLOGUE( ts_alligator_p );
(void)c;
- if( n == 0 ) return -1;
/* Jaw: SMA(13) shifted 8 positions */
/* Teeth: SMA(8) shifted 5 positions */
/* Lips: SMA(5) shifted 3 positions */
diff --git a/lib/annualized_historical_volatility.c b/lib/annualized_historical_volatility.c
index c0c88cf..27ed0f0 100644
--- a/lib/annualized_historical_volatility.c
+++ b/lib/annualized_historical_volatility.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_annualized_historical_volatility_p = { .n_inputs = 1, .n
uint_t ts_annualized_historical_volatility_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_annualized_historical_volatility_params_t *)c)->k : 0 );
+ return ( c ? ((ts_annualized_historical_volatility_params_t const *)c)->k : 0 );
}
int ts_annualized_historical_volatility(
@@ -31,9 +31,13 @@ int ts_annualized_historical_volatility(
{
TS_PROLOGUE( ts_annualized_historical_volatility_p );
if ( !c ) return -1;
- uint_t k = ((ts_annualized_historical_volatility_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_annualized_historical_volatility_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
+ for ( uint_t i = 0; i < k; ++i )
+ y[0][i] = NAN;
+
/* Compute log returns, then stddev, then annualize */
for (uint_t i = k; i < n; ++i)
{
diff --git a/lib/apo.c b/lib/apo.c
index f888162..fa720a7 100644
--- a/lib/apo.c
+++ b/lib/apo.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_apo_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_apo_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)((ts_apo_params_t *)c)->slow_k - 1 : 0 );
+ return ( c ? (uint_t)((ts_apo_params_t const *)c)->slow_k - 1 : 0 );
}
int ts_apo(
@@ -31,10 +31,9 @@ int ts_apo(
{
TS_PROLOGUE( ts_apo_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t fast_k = ((ts_apo_params_t *)c)->fast_k;
- fp_t slow_k = ((ts_apo_params_t *)c)->slow_k;
+ fp_t fast_k = ((ts_apo_params_t const *)c)->fast_k;
+ fp_t slow_k = ((ts_apo_params_t const *)c)->slow_k;
if (fast_k == 0 || slow_k == 0) return -1;
fp_t fast_a = 1.0 / fast_k;
diff --git a/lib/aroon.c b/lib/aroon.c
index 539e97b..1bf824b 100644
--- a/lib/aroon.c
+++ b/lib/aroon.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_aroon_p = { .n_inputs = 4, .n_outputs = 2, .n_constants
uint_t ts_aroon_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_aroon_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_aroon_params_t const *)c)->k - 1 : 0 );
}
int ts_aroon(
@@ -32,7 +32,7 @@ int ts_aroon(
{
TS_PROLOGUE( ts_aroon_p );
if ( !c ) return -1;
- uint_t k = ((ts_aroon_params_t *)c)->k;
+ uint_t k = ((ts_aroon_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for ( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/aroon_oscillator.c b/lib/aroon_oscillator.c
index db9fe9d..2152655 100644
--- a/lib/aroon_oscillator.c
+++ b/lib/aroon_oscillator.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_aroon_oscillator_p = { .n_inputs = 4, .n_outputs = 1, .n
uint_t ts_aroon_oscillator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_aroon_oscillator_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_aroon_oscillator_params_t const *)c)->k - 1 : 0 );
}
int ts_aroon_oscillator(
@@ -32,7 +32,7 @@ int ts_aroon_oscillator(
{
TS_PROLOGUE( ts_aroon_oscillator_p );
if ( !c ) return -1;
- uint_t k = ((ts_aroon_oscillator_params_t *)c)->k;
+ uint_t k = ((ts_aroon_oscillator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for ( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/asi.c b/lib/asi.c
index ac4225b..e0132e8 100644
--- a/lib/asi.c
+++ b/lib/asi.c
@@ -28,7 +28,6 @@ int ts_asi(
{
TS_PROLOGUE( ts_asi_p );
(void)c;
- if( n == 0 ) return -1;
y[0][0] = 0;
diff --git a/lib/atr.c b/lib/atr.c
index 7c9f06f..7444531 100644
--- a/lib/atr.c
+++ b/lib/atr.c
@@ -26,7 +26,7 @@ ts_parameter_t const ts_atr_p = { .n_inputs = 4, .n_outputs = 1, .n_constants =
uint_t ts_atr_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_atr_params_t *)c)->k : 0 );
+ return ( c ? ((ts_atr_params_t const *)c)->k : 0 );
}
int ts_atr(
@@ -38,7 +38,7 @@ int ts_atr(
TS_PROLOGUE( ts_atr_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_atr_params_t *)c)->k;
+ uint_t k = ((ts_atr_params_t const *)c)->k;
if (k == 0) return -1;
if (n < 2) return -1;
diff --git a/lib/atr_bands.c b/lib/atr_bands.c
index 73b7d44..1aa7464 100644
--- a/lib/atr_bands.c
+++ b/lib/atr_bands.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_atr_bands_p = { .n_inputs = 4, .n_outputs = 3, .n_consta
uint_t ts_atr_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_atr_bands_params_t *)c)->k : 0 );
+ return ( c ? ((ts_atr_bands_params_t const *)c)->k : 0 );
}
int ts_atr_bands(
@@ -36,11 +36,20 @@ int ts_atr_bands(
{
TS_PROLOGUE( ts_atr_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_atr_bands_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_atr_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
if (n < 2) return -1;
- fp_t mult = ((ts_atr_bands_params_t *)c)->mult;
+ fp_t mult = ((ts_atr_bands_params_t const *)c)->mult;
+ if (mult < 0 || isnan(mult) || isinf(mult)) return -1;
+
+ for ( uint_t i = 0; i < k - 1; ++i )
+ {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ y[2][i] = NAN;
+ }
fp_t tr_sum = 0;
fp_t atr = 0;
diff --git a/lib/atr_trailing_stops.c b/lib/atr_trailing_stops.c
index 2c7cd73..46628a2 100644
--- a/lib/atr_trailing_stops.c
+++ b/lib/atr_trailing_stops.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_atr_trailing_stops_p = { .n_inputs = 4, .n_outputs = 2,
uint_t ts_atr_trailing_stops_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_atr_trailing_stops_params_t *)c)->k : 0 );
+ return ( c ? ((ts_atr_trailing_stops_params_t const *)c)->k : 0 );
}
int ts_atr_trailing_stops(
@@ -35,11 +35,19 @@ int ts_atr_trailing_stops(
{
TS_PROLOGUE( ts_atr_trailing_stops_p );
if ( !c ) return -1;
- uint_t k = ((ts_atr_trailing_stops_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_atr_trailing_stops_params_t const *)c)->k;
if (k == 0) return -1;
if (n < k + 1) return -1;
- fp_t mult = ((ts_atr_trailing_stops_params_t *)c)->mult;
+ fp_t mult = ((ts_atr_trailing_stops_params_t const *)c)->mult;
+ if (mult < 0 || isnan(mult) || isinf(mult)) return -1;
+
+ for ( uint_t i = 0; i < k; ++i )
+ {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ }
fp_t tr_sum = 0;
fp_t atr = 0;
diff --git a/lib/average.c b/lib/average.c
index 391de93..ece89ca 100644
--- a/lib/average.c
+++ b/lib/average.c
@@ -33,7 +33,7 @@ ts_parameter_t const ts_average_p = { .n_inputs = 1, .n_outputs = 1, .n_constant
uint_t ts_average_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_average_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_average_params_t const *)c)->k - 1 : 0 );
}
int ts_average(
@@ -45,7 +45,7 @@ int ts_average(
TS_PROLOGUE( ts_average_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_average_params_t *)c)->k;
+ uint_t k = ((ts_average_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/average_exponential.c b/lib/average_exponential.c
index bae9d5f..1875bc3 100644
--- a/lib/average_exponential.c
+++ b/lib/average_exponential.c
@@ -40,7 +40,7 @@ int ts_average_exponential(
TS_PROLOGUE( ts_average_exponential_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- fp_t k = ((ts_average_exponential_params_t *)c)->k;
+ fp_t k = ((ts_average_exponential_params_t const *)c)->k;
if (k <= 0 || isnan(k)) return -1;
fp_t a = 1.0 / k;
diff --git a/lib/average_exponential_double.c b/lib/average_exponential_double.c
index eeb890f..5c3dcb4 100644
--- a/lib/average_exponential_double.c
+++ b/lib/average_exponential_double.c
@@ -35,8 +35,8 @@ int ts_average_exponential_double(
TS_PROLOGUE( ts_average_exponential_double_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- fp_t a = ((ts_average_exponential_double_params_t *)c)->a;
- if (a == 0 || n == 0) return -1;
+ fp_t a = ((ts_average_exponential_double_params_t const *)c)->a;
+ if (a == 0) return -1;
fp_t ema1 = x[0][0];
fp_t ema2 = x[0][0];
diff --git a/lib/average_exponential_triple.c b/lib/average_exponential_triple.c
index 467d87f..793d048 100644
--- a/lib/average_exponential_triple.c
+++ b/lib/average_exponential_triple.c
@@ -33,8 +33,8 @@ int ts_average_exponential_triple(
TS_PROLOGUE( ts_average_exponential_triple_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- fp_t a = ((ts_average_exponential_triple_params_t *)c)->a;
- if (a == 0 || n == 0) return -1;
+ fp_t a = ((ts_average_exponential_triple_params_t const *)c)->a;
+ if (a == 0) return -1;
fp_t ema1 = x[0][0];
fp_t ema2 = x[0][0];
diff --git a/lib/average_triangle.c b/lib/average_triangle.c
index 9ac952d..fd1c037 100644
--- a/lib/average_triangle.c
+++ b/lib/average_triangle.c
@@ -29,7 +29,7 @@ ts_parameter_t const ts_average_triangle_p = { .n_inputs = 1, .n_outputs = 1, .n
uint_t ts_average_triangle_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? 2 * ( ((ts_average_triangle_params_t *)c)->k - 1 ) : 0 );
+ return ( c ? 2 * ( ((ts_average_triangle_params_t const *)c)->k - 1 ) : 0 );
}
int ts_average_triangle(
@@ -40,7 +40,7 @@ int ts_average_triangle(
{
TS_PROLOGUE( ts_average_triangle_p );
if ( !c ) return -1;
- uint_t k = ((ts_average_triangle_params_t *)c)->k;
+ uint_t k = ((ts_average_triangle_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t rk2 = _ts_reciprocal( _ts_square( k ) );
diff --git a/lib/average_weighted.c b/lib/average_weighted.c
index eb99a17..632de8b 100644
--- a/lib/average_weighted.c
+++ b/lib/average_weighted.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_average_weighted_p = { .n_inputs = 1, .n_outputs = 1, .n
uint_t ts_average_weighted_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_average_weighted_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_average_weighted_params_t const *)c)->k - 1 : 0 );
}
int ts_average_weighted(
@@ -35,7 +35,7 @@ int ts_average_weighted(
{
TS_PROLOGUE( ts_average_weighted_p );
if ( !c ) return -1;
- uint_t k = ((ts_average_weighted_params_t *)c)->k;
+ uint_t k = ((ts_average_weighted_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/average_weighted_series.c b/lib/average_weighted_series.c
index d7e2ccb..d388651 100644
--- a/lib/average_weighted_series.c
+++ b/lib/average_weighted_series.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_average_weighted_series_p = { .n_inputs = 2, .n_outputs
uint_t ts_average_weighted_series_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_average_weighted_series_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_average_weighted_series_params_t const *)c)->k - 1 : 0 );
}
int ts_average_weighted_series(
@@ -34,7 +34,7 @@ int ts_average_weighted_series(
{
TS_PROLOGUE( ts_average_weighted_series_p );
if ( !c ) return -1;
- uint_t k = ((ts_average_weighted_series_params_t *)c)->k;
+ uint_t k = ((ts_average_weighted_series_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/band_width.c b/lib/band_width.c
index 822d835..4a4d6cb 100644
--- a/lib/band_width.c
+++ b/lib/band_width.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_band_width_p = { .n_inputs = 1, .n_outputs = 1, .n_const
uint_t ts_band_width_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_band_width_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_band_width_params_t const *)c)->k > 0 ? ((ts_band_width_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_band_width(
@@ -32,9 +32,11 @@ int ts_band_width(
{
TS_PROLOGUE( ts_band_width_p );
if ( !c ) return -1;
- uint_t k = ((ts_band_width_params_t *)c)->k;
- fp_t std_mult = ((ts_band_width_params_t *)c)->std_mult;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_band_width_params_t const *)c)->k;
+ fp_t std_mult = ((ts_band_width_params_t const *)c)->std_mult;
if (k == 0 || n < k) return -1;
+ if (std_mult < 0 || isnan(std_mult) || isinf(std_mult)) return -1;
for (uint_t i = k - 1; i < n; ++i)
{
diff --git a/lib/beta_pdf.c b/lib/beta_pdf.c
index a23ed68..1366665 100644
--- a/lib/beta_pdf.c
+++ b/lib/beta_pdf.c
@@ -32,8 +32,8 @@ int ts_beta_pdf(
{
TS_PROLOGUE( ts_beta_pdf_p );
if ( !c ) return -1;
- fp_t alpha = ((ts_beta_pdf_params_t *)c)->alpha;
- fp_t beta = ((ts_beta_pdf_params_t *)c)->beta;
+ fp_t alpha = ((ts_beta_pdf_params_t const *)c)->alpha;
+ fp_t beta = ((ts_beta_pdf_params_t const *)c)->beta;
if (isnan(alpha) || isnan(beta) || alpha <= 0 || beta <= 0)
{
for( uint_t i = 0; i < n; ++i ) y[0][i] = 0;
diff --git a/lib/binomial_pdf.c b/lib/binomial_pdf.c
index 8b3a442..f10663f 100644
--- a/lib/binomial_pdf.c
+++ b/lib/binomial_pdf.c
@@ -32,8 +32,8 @@ int ts_binomial_pdf(
{
TS_PROLOGUE( ts_binomial_pdf_p );
if ( !c ) return -1;
- uint_t n_trials = ((ts_binomial_pdf_params_t *)c)->n_trials;
- fp_t p = ((ts_binomial_pdf_params_t *)c)->p;
+ uint_t n_trials = ((ts_binomial_pdf_params_t const *)c)->n_trials;
+ fp_t p = ((ts_binomial_pdf_params_t const *)c)->p;
if (p < 0.0 || p > 1.0 || isnan(p) || isinf(p)) return -1;
for( uint_t i = 0; i < n; ++i )
{
diff --git a/lib/bollinger_bands.c b/lib/bollinger_bands.c
index 55da054..56ce8f9 100644
--- a/lib/bollinger_bands.c
+++ b/lib/bollinger_bands.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_bollinger_bands_p = { .n_inputs = 1, .n_outputs = 3, .n_
uint_t ts_bollinger_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_bollinger_bands_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_bollinger_bands_params_t const *)c)->k > 0 ? ((ts_bollinger_bands_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_bollinger_bands(
@@ -37,10 +37,17 @@ int ts_bollinger_bands(
TS_PROLOGUE( ts_bollinger_bands_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_bollinger_bands_params_t *)c)->k;
+ uint_t k = ((ts_bollinger_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- fp_t std_mult = ((ts_bollinger_bands_params_t *)c)->std_mult;
- if (std_mult < 0 || isnan(std_mult)) return -1;
+ fp_t std_mult = ((ts_bollinger_bands_params_t const *)c)->std_mult;
+ if (std_mult < 0 || isnan(std_mult) || isinf(std_mult)) return -1;
+
+ for( uint_t i = 0; i < k - 1; ++i )
+ {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ y[2][i] = NAN;
+ }
// Two-pass initial window for numerical stability
{
@@ -56,8 +63,8 @@ int ts_bollinger_bands(
}
variance /= (fp_t)k;
fp_t stddev = sqrt( variance );
- y[1][k - 1] = mean + std_mult * stddev;
- y[0][k - 1] = mean;
+ y[0][k - 1] = mean + std_mult * stddev;
+ y[1][k - 1] = mean;
y[2][k - 1] = mean - std_mult * stddev;
}
@@ -79,8 +86,8 @@ int ts_bollinger_bands(
}
variance *= rk;
fp_t stddev = sqrt( variance );
- y[1][i] = mean + std_mult * stddev;
- y[0][i] = mean;
+ y[0][i] = mean + std_mult * stddev;
+ y[1][i] = mean;
y[2][i] = mean - std_mult * stddev;
}
return 0;
diff --git a/lib/bollinger_lower.c b/lib/bollinger_lower.c
index 05a0883..3eac1f0 100644
--- a/lib/bollinger_lower.c
+++ b/lib/bollinger_lower.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_bollinger_lower_p = { .n_inputs = 1, .n_outputs = 1, .n_
uint_t ts_bollinger_lower_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_bollinger_lower_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_bollinger_lower_params_t const *)c)->k - 1 : 0 );
}
int ts_bollinger_lower(
@@ -34,9 +34,9 @@ int ts_bollinger_lower(
{
TS_PROLOGUE( ts_bollinger_lower_p );
if ( !c ) return -1;
- uint_t k = ((ts_bollinger_lower_params_t *)c)->k;
+ uint_t k = ((ts_bollinger_lower_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- fp_t std_mult = ((ts_bollinger_lower_params_t *)c)->std_mult;
+ fp_t std_mult = ((ts_bollinger_lower_params_t const *)c)->std_mult;
if (isnan(std_mult) || isinf(std_mult)) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/bollinger_pctb.c b/lib/bollinger_pctb.c
index a3425cd..6387f16 100644
--- a/lib/bollinger_pctb.c
+++ b/lib/bollinger_pctb.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_bollinger_pctb_p = { .n_inputs = 1, .n_outputs = 1, .n_c
uint_t ts_bollinger_pctb_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_bollinger_pctb_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_bollinger_pctb_params_t const *)c)->k > 0 ? ((ts_bollinger_pctb_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_bollinger_pctb(
@@ -34,10 +34,11 @@ int ts_bollinger_pctb(
{
TS_PROLOGUE( ts_bollinger_pctb_p );
if ( !c ) return -1;
- uint_t k = ((ts_bollinger_pctb_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_bollinger_pctb_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- fp_t std_mult = ((ts_bollinger_pctb_params_t *)c)->std_mult;
- if (isnan(std_mult) || isinf(std_mult)) return -1;
+ fp_t std_mult = ((ts_bollinger_pctb_params_t const *)c)->std_mult;
+ if (std_mult < 0 || isnan(std_mult) || isinf(std_mult)) return -1;
for( uint_t i = k - 1; i < n; ++i )
{
diff --git a/lib/bollinger_upper.c b/lib/bollinger_upper.c
index 9294cfb..51ced24 100644
--- a/lib/bollinger_upper.c
+++ b/lib/bollinger_upper.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_bollinger_upper_p = { .n_inputs = 1, .n_outputs = 1, .n_
uint_t ts_bollinger_upper_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_bollinger_upper_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_bollinger_upper_params_t const *)c)->k > 0 ? ((ts_bollinger_upper_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_bollinger_upper(
@@ -34,10 +34,11 @@ int ts_bollinger_upper(
{
TS_PROLOGUE( ts_bollinger_upper_p );
if ( !c ) return -1;
- uint_t k = ((ts_bollinger_upper_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_bollinger_upper_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- fp_t std_mult = ((ts_bollinger_upper_params_t *)c)->std_mult;
- if (isnan(std_mult) || isinf(std_mult)) return -1;
+ fp_t std_mult = ((ts_bollinger_upper_params_t const *)c)->std_mult;
+ if (std_mult < 0 || isnan(std_mult) || isinf(std_mult)) return -1;
for( uint_t i = k - 1; i < n; ++i )
{
diff --git a/lib/bollinger_width.c b/lib/bollinger_width.c
index d9bca25..00891ce 100644
--- a/lib/bollinger_width.c
+++ b/lib/bollinger_width.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_bollinger_width_p = { .n_inputs = 1, .n_outputs = 1, .n_
uint_t ts_bollinger_width_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_bollinger_width_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_bollinger_width_params_t const *)c)->k > 0 ? ((ts_bollinger_width_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_bollinger_width(
@@ -34,10 +34,11 @@ int ts_bollinger_width(
{
TS_PROLOGUE( ts_bollinger_width_p );
if ( !c ) return -1;
- uint_t k = ((ts_bollinger_width_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_bollinger_width_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- fp_t std_mult = ((ts_bollinger_width_params_t *)c)->std_mult;
- if (isnan(std_mult) || isinf(std_mult)) return -1;
+ fp_t std_mult = ((ts_bollinger_width_params_t const *)c)->std_mult;
+ if (std_mult < 0 || isnan(std_mult) || isinf(std_mult)) return -1;
for( uint_t i = k - 1; i < n; ++i )
{
diff --git a/lib/cci.c b/lib/cci.c
index 956f619..5345ac8 100644
--- a/lib/cci.c
+++ b/lib/cci.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_cci_p = { .n_inputs = 4, .n_outputs = 1, .n_constants =
uint_t ts_cci_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_cci_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_cci_params_t const *)c)->k - 1 : 0 );
}
int ts_cci(
@@ -32,7 +32,7 @@ int ts_cci(
TS_PROLOGUE( ts_cci_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_cci_params_t *)c)->k;
+ uint_t k = ((ts_cci_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
// Compute initial typical prices
diff --git a/lib/center_of_gravity.c b/lib/center_of_gravity.c
index 3186c44..ae78bdc 100644
--- a/lib/center_of_gravity.c
+++ b/lib/center_of_gravity.c
@@ -19,7 +19,7 @@ ts_parameter_t const ts_center_of_gravity_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_center_of_gravity_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_center_of_gravity_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_center_of_gravity_params_t const *)c)->k - 1 : 0 );
}
int ts_center_of_gravity(
@@ -30,7 +30,7 @@ int ts_center_of_gravity(
{
TS_PROLOGUE( ts_center_of_gravity_p );
if ( !c ) return -1;
- uint_t k = ((ts_center_of_gravity_params_t *)c)->k;
+ uint_t k = ((ts_center_of_gravity_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/chande_forecast_oscillator.c b/lib/chande_forecast_oscillator.c
index 6e65bbe..c3b2c8c 100644
--- a/lib/chande_forecast_oscillator.c
+++ b/lib/chande_forecast_oscillator.c
@@ -19,7 +19,7 @@ ts_parameter_t const ts_chande_forecast_oscillator_p = { .n_inputs = 1, .n_outpu
uint_t ts_chande_forecast_oscillator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_chande_forecast_oscillator_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_chande_forecast_oscillator_params_t const *)c)->k - 1 : 0 );
}
int ts_chande_forecast_oscillator(
@@ -30,7 +30,7 @@ int ts_chande_forecast_oscillator(
{
TS_PROLOGUE( ts_chande_forecast_oscillator_p );
if ( !c ) return -1;
- uint_t k = ((ts_chande_forecast_oscillator_params_t *)c)->k;
+ uint_t k = ((ts_chande_forecast_oscillator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/change.c b/lib/change.c
index 84815a5..8e4c1b2 100644
--- a/lib/change.c
+++ b/lib/change.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_change_p = { .n_inputs = 1, .n_outputs = 1, .n_constants
uint_t ts_change_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_change_params_t *)c)->k : 0 );
+ return ( c ? ((ts_change_params_t const *)c)->k : 0 );
}
int ts_change(
@@ -31,7 +31,7 @@ int ts_change(
{
TS_PROLOGUE( ts_change_p );
if ( !c ) return -1;
- uint_t k = ((ts_change_params_t *)c)->k;
+ uint_t k = ((ts_change_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/channel.c b/lib/channel.c
index a2d8bd9..9fbd0e3 100644
--- a/lib/channel.c
+++ b/lib/channel.c
@@ -19,7 +19,7 @@ ts_parameter_t const ts_channel_p = { .n_inputs = 4, .n_outputs = 2, .n_constant
uint_t ts_channel_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_channel_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_channel_params_t const *)c)->k - 1 : 0 );
}
int ts_channel(
@@ -30,7 +30,7 @@ int ts_channel(
{
TS_PROLOGUE( ts_channel_p );
if ( !c ) return -1;
- uint_t k = ((ts_channel_params_t *)c)->k;
+ uint_t k = ((ts_channel_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k - 1;
diff --git a/lib/chebyshev_t.c b/lib/chebyshev_t.c
index a0230b8..5428fa4 100644
--- a/lib/chebyshev_t.c
+++ b/lib/chebyshev_t.c
@@ -28,32 +28,32 @@ int ts_chebyshev_t(
{
TS_PROLOGUE( ts_chebyshev_t_p );
(void)c;
- for( uint_t i = 0; i < n; ++i )
- {
- fp_t xv = x[0][i];
- uint_t n_val = (uint_t)x[1][i];
- if (x[1][i] < 0 || x[1][i] > 10000) { y[0][i] = 0; continue; }
- if( n_val == 0 )
- {
- y[0][i] = 1.0;
- }
- else if( n_val == 1 )
- {
- y[0][i] = xv;
- }
- else
- {
- fp_t t0 = 1.0;
- fp_t t1 = xv;
- for( uint_t k = 2; k <= n_val; ++k )
- {
- fp_t t2 = 2.0 * xv * t1 - t0;
- t0 = t1;
- t1 = t2;
- }
- y[0][i] = t1;
- }
- }
+ for( uint_t i = 0; i < n; ++i )
+ {
+ fp_t xv = x[0][i];
+ uint_t n_val = (uint_t)x[1][i];
+ if (x[1][i] < 0 || x[1][i] > 10000) { y[0][i] = 0; continue; }
+ if( n_val == 0 )
+ {
+ y[0][i] = 1.0;
+ }
+ else if( n_val == 1 )
+ {
+ y[0][i] = xv;
+ }
+ else
+ {
+ fp_t t0 = 1.0;
+ fp_t t1 = xv;
+ for( uint_t k = 2; k <= n_val; ++k )
+ {
+ fp_t t2 = 2.0 * xv * t1 - t0;
+ t0 = t1;
+ t1 = t2;
+ }
+ y[0][i] = t1;
+ }
+ }
return 0;
}
diff --git a/lib/chi_squared_pdf.c b/lib/chi_squared_pdf.c
index 7f2ba09..7a3c7df 100644
--- a/lib/chi_squared_pdf.c
+++ b/lib/chi_squared_pdf.c
@@ -31,7 +31,7 @@ int ts_chi_squared_pdf(
{
TS_PROLOGUE( ts_chi_squared_pdf_p );
if ( !c ) return -1;
- fp_t k = ((ts_chi_squared_pdf_params_t *)c)->k;
+ fp_t k = ((ts_chi_squared_pdf_params_t const *)c)->k;
if ( k <= 0 )
{
for( uint_t i = 0; i < n; ++i ) y[0][i] = 0;
diff --git a/lib/choppiness_index.c b/lib/choppiness_index.c
index 55ecb46..332e8b3 100644
--- a/lib/choppiness_index.c
+++ b/lib/choppiness_index.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_choppiness_index_p = { .n_inputs = 3, .n_outputs = 1, .n
uint_t ts_choppiness_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? 2 * ((ts_choppiness_index_params_t *)c)->k : 0 );
+ return ( c ? 2 * ((ts_choppiness_index_params_t const *)c)->k : 0 );
}
int ts_choppiness_index(
@@ -31,7 +31,7 @@ int ts_choppiness_index(
{
TS_PROLOGUE( ts_choppiness_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_choppiness_index_params_t *)c)->k;
+ uint_t k = ((ts_choppiness_index_params_t const *)c)->k;
uint_t range_period = 2 * k;
if (k == 0 || n < range_period) return -1;
diff --git a/lib/close_to_high.c b/lib/close_to_high.c
index dc7cf7b..a4c15f4 100644
--- a/lib/close_to_high.c
+++ b/lib/close_to_high.c
@@ -8,7 +8,6 @@
// Outputs: 1 (ratio)
// Constants: 0
-#include <math.h>
#include "ts.h"
diff --git a/lib/close_to_open_ratio.c b/lib/close_to_open_ratio.c
index d857dd2..466b5e1 100644
--- a/lib/close_to_open_ratio.c
+++ b/lib/close_to_open_ratio.c
@@ -8,7 +8,6 @@
// Outputs: 1 (ratio)
// Constants: 0
-#include <math.h>
#include "ts.h"
diff --git a/lib/cmf.c b/lib/cmf.c
index 7ac0402..52fa7c6 100644
--- a/lib/cmf.c
+++ b/lib/cmf.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_cmf_p = { .n_inputs = 5, .n_outputs = 1, .n_constants =
uint_t ts_cmf_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_cmf_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_cmf_params_t const *)c)->k - 1 : 0 );
}
int ts_cmf(
@@ -31,7 +31,7 @@ int ts_cmf(
{
TS_PROLOGUE( ts_cmf_p );
if ( !c ) return -1;
- uint_t k = ((ts_cmf_params_t *)c)->k;
+ uint_t k = ((ts_cmf_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_mf = 0;
diff --git a/lib/cmo.c b/lib/cmo.c
index 9db5622..4c7598c 100644
--- a/lib/cmo.c
+++ b/lib/cmo.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_cmo_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_cmo_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_cmo_params_t *)c)->k : 0 );
+ return ( c ? ((ts_cmo_params_t const *)c)->k : 0 );
}
int ts_cmo(
@@ -31,7 +31,7 @@ int ts_cmo(
{
TS_PROLOGUE( ts_cmo_p );
if ( !c ) return -1;
- uint_t k = ((ts_cmo_params_t *)c)->k;
+ uint_t k = ((ts_cmo_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
for (uint_t j = 0; j < k; ++j) y[0][j] = 0;
diff --git a/lib/coppock_curve.c b/lib/coppock_curve.c
index dfa1ad2..e192bd1 100644
--- a/lib/coppock_curve.c
+++ b/lib/coppock_curve.c
@@ -33,9 +33,9 @@ int ts_coppock_curve(
uint_t roc_short = 11;
uint_t wma_period = 10;
- if (n == 0 || n < roc_long) return -1;
+ if (n < roc_long) return -1;
- fp_t *combined = calloc( n, sizeof( fp_t ) );
+ fp_t *combined = calloc( n, sizeof( fp_t ) );
if ( !combined ) return -1;
for ( uint_t i = roc_long; i < n; ++i )
@@ -50,7 +50,7 @@ int ts_coppock_curve(
combined[i - roc_long] = roc14 + roc11;
}
- for (uint_t j = 0; j < n && j < roc_long; ++j) y[0][j] = 0;
+ for ( uint_t j = 0; j < n && j < roc_long; ++j ) y[0][j] = 0;
for ( uint_t i = roc_long; i < n; ++i )
{
diff --git a/lib/correlation_coefficient.c b/lib/correlation_coefficient.c
index d20d1ea..a806daf 100644
--- a/lib/correlation_coefficient.c
+++ b/lib/correlation_coefficient.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_correlation_coefficient_p = { .n_inputs = 2, .n_outputs
uint_t ts_correlation_coefficient_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_correlation_coefficient_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_correlation_coefficient_params_t const *)c)->k - 1 : 0 );
}
int ts_correlation_coefficient(
@@ -31,7 +31,7 @@ int ts_correlation_coefficient(
{
TS_PROLOGUE( ts_correlation_coefficient_p );
if ( !c ) return -1;
- uint_t k = ((ts_correlation_coefficient_params_t *)c)->k;
+ uint_t k = ((ts_correlation_coefficient_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_y = 0, sum_xy = 0, sum_x2 = 0, sum_y2 = 0;
diff --git a/lib/cv.c b/lib/cv.c
index 0c06250..356716a 100644
--- a/lib/cv.c
+++ b/lib/cv.c
@@ -4,7 +4,7 @@
//
// EMA_fast(H-L) - EMA_slow(H-L), volatility measure
//
-// Inputs: 5 (OHLCV)
+// Inputs: 4 (OHLC)
// Outputs: 1 (CV)
// Constants: 2 (fast, slow periods)
@@ -21,7 +21,7 @@ ts_parameter_t const ts_cv_p = { .n_inputs = 4, .n_outputs = 1, .n_constants = 2
uint_t ts_cv_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)((ts_cv_params_t *)c)->slow : 0 );
+ return ( c ? (uint_t)((ts_cv_params_t const *)c)->slow : 0 );
}
int ts_cv(
@@ -32,9 +32,9 @@ int ts_cv(
{
TS_PROLOGUE( ts_cv_p );
if ( !c ) return -1;
- fp_t fast = ((ts_cv_params_t *)c)->fast;
- fp_t slow = ((ts_cv_params_t *)c)->slow;
- if (fast == 0 || slow == 0 || n == 0) return -1;
+ fp_t fast = ((ts_cv_params_t const *)c)->fast;
+ fp_t slow = ((ts_cv_params_t const *)c)->slow;
+ if (fast == 0 || slow == 0) return -1;
fp_t a_fast = 1.0 / fast;
fp_t a_slow = 1.0 / slow;
diff --git a/lib/darvas_box.c b/lib/darvas_box.c
index 573ed1e..a3bb5c1 100644
--- a/lib/darvas_box.c
+++ b/lib/darvas_box.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_darvas_box_p = { .n_inputs = 4, .n_outputs = 2, .n_const
uint_t ts_darvas_box_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_darvas_box_params_t *)c)->k > 0 ? ((ts_darvas_box_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_darvas_box_params_t const *)c)->k > 0 ? ((ts_darvas_box_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_darvas_box(
@@ -32,7 +32,7 @@ int ts_darvas_box(
{
TS_PROLOGUE( ts_darvas_box_p );
if ( !c ) return -1;
- uint_t k = ((ts_darvas_box_params_t *)c)->k;
+ uint_t k = ((ts_darvas_box_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/decay_exponential.c b/lib/decay_exponential.c
index 97afe36..506d225 100644
--- a/lib/decay_exponential.c
+++ b/lib/decay_exponential.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_decay_exponential_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_decay_exponential_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_decay_exponential_params_t *)c)->k : 0 );
+ return ( c ? ((ts_decay_exponential_params_t const *)c)->k : 0 );
}
int ts_decay_exponential(
@@ -34,8 +34,9 @@ int ts_decay_exponential(
{
TS_PROLOGUE( ts_decay_exponential_p );
if ( !c ) return -1;
- uint_t k = ((ts_decay_exponential_params_t *)c)->k;
- if (k == 0 || n <= k) return -1;
+ uint_t k = ((ts_decay_exponential_params_t const *)c)->k;
+ if (k == 0) return -1;
+ if (n <= k) return -1;
fp_t a = ( fp_t ) 1.0 - _ts_reciprocal( k );
diff --git a/lib/decay_linear.c b/lib/decay_linear.c
index 8519d13..9d92b49 100644
--- a/lib/decay_linear.c
+++ b/lib/decay_linear.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_decay_linear_p = { .n_inputs = 1, .n_outputs = 1, .n_con
uint_t ts_decay_linear_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_decay_linear_params_t *)c)->k : 0 );
+ return ( c ? ((ts_decay_linear_params_t const *)c)->k : 0 );
}
int ts_decay_linear(
@@ -36,47 +36,47 @@ int ts_decay_linear(
{
TS_PROLOGUE( ts_decay_linear_p );
if ( !c ) return -1;
- uint_t k = ((ts_decay_linear_params_t *)c)->k;
+ uint_t k = ((ts_decay_linear_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
- for (uint_t zi = 0; zi < k; ++zi) y[0][zi] = 0;
+ for (uint_t zi = 0; zi < k; ++zi) y[0][zi] = 0;
- uint_t xi = 1;
+ uint_t xi = 1;
- fp_t prev = x[0][0];
- fp_t r = prev / k;
+ fp_t prev = x[0][0];
+ fp_t r = prev / (fp_t)k;
for( ; xi < k; xi++ )
{
- prev -= r;
+ prev -= r;
- if( x[0][xi] > prev )
- {
- prev = x[0][xi];
- r = x[0][xi] / k;
- }
- else
- {
- prev = fmax( prev, 0 );
- }
+ if( x[0][xi] > prev )
+ {
+ prev = x[0][xi];
+ r = x[0][xi] / (fp_t)k;
+ }
+ else
+ {
+ prev = fmax( prev, 0 );
+ }
}
for( uint_t yi = k; xi < n; xi++, yi++ )
{
- fp_t curr = prev - r;
+ fp_t curr = prev - r;
- if( x[0][xi] > curr )
- {
- curr = x[0][xi];
- r = x[0][xi] / k;
- }
- else
- {
- curr = fmax( curr, 0 );
- }
+ if( x[0][xi] > curr )
+ {
+ curr = x[0][xi];
+ r = x[0][xi] / (fp_t)k;
+ }
+ else
+ {
+ curr = fmax( curr, 0 );
+ }
- y[0][yi] = curr;
- prev = curr;
+ y[0][yi] = curr;
+ prev = curr;
}
return 0;
}
diff --git a/lib/delta.c b/lib/delta.c
index 02ccb66..2ee037a 100644
--- a/lib/delta.c
+++ b/lib/delta.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_delta_p = { .n_inputs = 1, .n_outputs = 1, .n_constants
uint_t ts_delta_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_delta_params_t *)c)->k : 0 );
+ return ( c ? ((ts_delta_params_t const *)c)->k : 0 );
}
int ts_delta(
@@ -35,7 +35,7 @@ int ts_delta(
{
TS_PROLOGUE( ts_delta_p );
if ( !c ) return -1;
- uint_t k = ((ts_delta_params_t *)c)->k;
+ uint_t k = ((ts_delta_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k;
diff --git a/lib/deviation_average.c b/lib/deviation_average.c
index 5ac7109..552d226 100644
--- a/lib/deviation_average.c
+++ b/lib/deviation_average.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_deviation_average_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_deviation_average_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_deviation_average_params_t *)c)->k > 0 ? ((ts_deviation_average_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_deviation_average_params_t const *)c)->k > 0 ? ((ts_deviation_average_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_deviation_average(
@@ -32,7 +32,7 @@ int ts_deviation_average(
{
TS_PROLOGUE( ts_deviation_average_p );
if ( !c ) return -1;
- uint_t k = ((ts_deviation_average_params_t *)c)->k;
+ uint_t k = ((ts_deviation_average_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/deviation_standard.c b/lib/deviation_standard.c
index a2a0a76..f843224 100644
--- a/lib/deviation_standard.c
+++ b/lib/deviation_standard.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_deviation_standard_p = { .n_inputs = 1, .n_outputs = 1,
uint_t ts_deviation_standard_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_deviation_standard_params_t *)c)->k > 0 ? ((ts_deviation_standard_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_deviation_standard_params_t const *)c)->k > 0 ? ((ts_deviation_standard_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_deviation_standard(
@@ -32,7 +32,7 @@ int ts_deviation_standard(
TS_PROLOGUE( ts_deviation_standard_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_deviation_standard_params_t *)c)->k;
+ uint_t k = ((ts_deviation_standard_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/deviation_standard_average_exponential.c b/lib/deviation_standard_average_exponential.c
index 8c484f5..a27cc6a 100644
--- a/lib/deviation_standard_average_exponential.c
+++ b/lib/deviation_standard_average_exponential.c
@@ -32,9 +32,8 @@ int ts_deviation_standard_average_exponential(
{
TS_PROLOGUE( ts_deviation_standard_average_exponential_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t a = ((ts_deviation_standard_average_exponential_params_t *)c)->a;
+ fp_t a = ((ts_deviation_standard_average_exponential_params_t const *)c)->a;
if (a == 0) return -1;
y[0][0] = x[0][0];
diff --git a/lib/deviation_vector.c b/lib/deviation_vector.c
index 4f10037..02d9f72 100644
--- a/lib/deviation_vector.c
+++ b/lib/deviation_vector.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_deviation_vector_p = { .n_inputs = 1, .n_outputs = 1, .n
uint_t ts_deviation_vector_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_deviation_vector_params_t *)c)->k > 0 ? ((ts_deviation_vector_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_deviation_vector_params_t const *)c)->k > 0 ? ((ts_deviation_vector_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_deviation_vector(
@@ -31,7 +31,7 @@ int ts_deviation_vector(
{
TS_PROLOGUE( ts_deviation_vector_p );
if ( !c ) return -1;
- uint_t k = ((ts_deviation_vector_params_t *)c)->k;
+ uint_t k = ((ts_deviation_vector_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = 0; i < n; ++i)
diff --git a/lib/di_minus.c b/lib/di_minus.c
index 95b0559..7fe0115 100644
--- a/lib/di_minus.c
+++ b/lib/di_minus.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_di_minus_p = { .n_inputs = 4, .n_outputs = 1, .n_constan
uint_t ts_di_minus_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_di_minus_params_t *)c)->k : 0 );
+ return ( c ? ((ts_di_minus_params_t const *)c)->k : 0 );
}
int ts_di_minus(
@@ -32,7 +32,7 @@ int ts_di_minus(
{
TS_PROLOGUE( ts_di_minus_p );
if ( !c ) return -1;
- uint_t k = ((ts_di_minus_params_t *)c)->k;
+ uint_t k = ((ts_di_minus_params_t const *)c)->k;
if (k == 0 || n < 2) return -1;
fp_t *ema_minus = calloc( n, sizeof( fp_t ) );
fp_t *ema_plus = calloc( n, sizeof( fp_t ) );
diff --git a/lib/di_plus.c b/lib/di_plus.c
index fb3c076..2939fc5 100644
--- a/lib/di_plus.c
+++ b/lib/di_plus.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_di_plus_p = { .n_inputs = 4, .n_outputs = 1, .n_constant
uint_t ts_di_plus_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_di_plus_params_t *)c)->k : 0 );
+ return ( c ? ((ts_di_plus_params_t const *)c)->k : 0 );
}
int ts_di_plus(
@@ -32,7 +32,7 @@ int ts_di_plus(
{
TS_PROLOGUE( ts_di_plus_p );
if ( !c ) return -1;
- uint_t k = ((ts_di_plus_params_t *)c)->k;
+ uint_t k = ((ts_di_plus_params_t const *)c)->k;
if (k == 0 || n < 2) return -1;
fp_t *ema_plus = calloc( n, sizeof( fp_t ) );
fp_t *ema_minus = calloc( n, sizeof( fp_t ) );
diff --git a/lib/disparity_index.c b/lib/disparity_index.c
index ebf5e0d..2909033 100644
--- a/lib/disparity_index.c
+++ b/lib/disparity_index.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_disparity_index_p = { .n_inputs = 1, .n_outputs = 1, .n_
uint_t ts_disparity_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_disparity_index_params_t *)c)->k > 0 ? ((ts_disparity_index_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_disparity_index_params_t const *)c)->k > 0 ? ((ts_disparity_index_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_disparity_index(
@@ -31,7 +31,7 @@ int ts_disparity_index(
{
TS_PROLOGUE( ts_disparity_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_disparity_index_params_t *)c)->k;
+ uint_t k = ((ts_disparity_index_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum = 0;
diff --git a/lib/donchian_channel.c b/lib/donchian_channel.c
index 760c396..93ae589 100644
--- a/lib/donchian_channel.c
+++ b/lib/donchian_channel.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_donchian_channel_p = { .n_inputs = 4, .n_outputs = 3, .n
uint_t ts_donchian_channel_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_donchian_channel_params_t *)c)->k > 0 ? ((ts_donchian_channel_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_donchian_channel_params_t const *)c)->k > 0 ? ((ts_donchian_channel_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_donchian_channel(
@@ -33,7 +33,7 @@ int ts_donchian_channel(
{
TS_PROLOGUE( ts_donchian_channel_p );
if ( !c ) return -1;
- uint_t k = ((ts_donchian_channel_params_t *)c)->k;
+ uint_t k = ((ts_donchian_channel_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for ( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/donchian_width.c b/lib/donchian_width.c
index c69936f..f6eb42c 100644
--- a/lib/donchian_width.c
+++ b/lib/donchian_width.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_donchian_width_p = { .n_inputs = 4, .n_outputs = 1, .n_c
uint_t ts_donchian_width_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_donchian_width_params_t *)c)->k > 0 ? ((ts_donchian_width_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_donchian_width_params_t const *)c)->k > 0 ? ((ts_donchian_width_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_donchian_width(
@@ -31,7 +31,7 @@ int ts_donchian_width(
{
TS_PROLOGUE( ts_donchian_width_p );
if ( !c ) return -1;
- uint_t k = ((ts_donchian_width_params_t *)c)->k;
+ uint_t k = ((ts_donchian_width_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for ( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/dpo.c b/lib/dpo.c
index 5bf069b..5d481a7 100644
--- a/lib/dpo.c
+++ b/lib/dpo.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_dpo_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_dpo_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_dpo_params_t *)c)->k / 2 + 1 : 0 );
+ return ( c ? ((ts_dpo_params_t const *)c)->k / 2 + 1 : 0 );
}
int ts_dpo(
@@ -32,7 +32,7 @@ int ts_dpo(
{
TS_PROLOGUE( ts_dpo_p );
if ( !c ) return -1;
- uint_t k = ((ts_dpo_params_t *)c)->k;
+ uint_t k = ((ts_dpo_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t sma_period = k;
diff --git a/lib/dx.c b/lib/dx.c
index b4552fa..8ae355f 100644
--- a/lib/dx.c
+++ b/lib/dx.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_dx_p = { .n_inputs = 4, .n_outputs = 1, .n_constants = 1
uint_t ts_dx_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_dx_params_t *)c)->k : 0 );
+ return ( c ? ((ts_dx_params_t const *)c)->k : 0 );
}
int ts_dx(
@@ -32,7 +32,7 @@ int ts_dx(
{
TS_PROLOGUE( ts_dx_p );
if ( !c ) return -1;
- uint_t k = ((ts_dx_params_t *)c)->k;
+ uint_t k = ((ts_dx_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t *plus_dm_arr = calloc( n, sizeof( fp_t ) );
diff --git a/lib/ease_of_movement.c b/lib/ease_of_movement.c
index d16f32c..f6f1f46 100644
--- a/lib/ease_of_movement.c
+++ b/lib/ease_of_movement.c
@@ -31,7 +31,7 @@ int ts_ease_of_movement(
{
TS_PROLOGUE( ts_ease_of_movement_p );
if ( !c ) return -1;
- uint_t k = ((ts_ease_of_movement_params_t *)c)->k;
+ uint_t k = ((ts_ease_of_movement_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
fp_t *eom = calloc( n, sizeof( fp_t ) );
diff --git a/lib/elder_force_index.c b/lib/elder_force_index.c
index 23cce66..c2b367c 100644
--- a/lib/elder_force_index.c
+++ b/lib/elder_force_index.c
@@ -31,7 +31,7 @@ int ts_elder_force_index(
{
TS_PROLOGUE( ts_elder_force_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_elder_force_index_params_t *)c)->k;
+ uint_t k = ((ts_elder_force_index_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t a = 1.0 / k;
diff --git a/lib/elder_impulse.c b/lib/elder_impulse.c
index d629e7c..b86514d 100644
--- a/lib/elder_impulse.c
+++ b/lib/elder_impulse.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_elder_impulse_p = { .n_inputs = 1, .n_outputs = 2, .n_co
uint_t ts_elder_impulse_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? 2 * ((ts_elder_impulse_params_t *)c)->k - 1 : 0 );
+ return ( c ? 2 * ((ts_elder_impulse_params_t const *)c)->k - 1 : 0 );
}
int ts_elder_impulse(
@@ -31,7 +31,7 @@ int ts_elder_impulse(
{
TS_PROLOGUE( ts_elder_impulse_p );
if ( !c ) return -1;
- uint_t k = ((ts_elder_impulse_params_t *)c)->k;
+ uint_t k = ((ts_elder_impulse_params_t const *)c)->k;
if (k == 0 || n < 2 * k - 1) return -1;
fp_t *sma = malloc( n * sizeof( fp_t ) );
diff --git a/lib/elder_ray.c b/lib/elder_ray.c
index a0f330f..730810b 100644
--- a/lib/elder_ray.c
+++ b/lib/elder_ray.c
@@ -33,7 +33,7 @@ int ts_elder_ray(
{
TS_PROLOGUE( ts_elder_ray_p );
if ( !c ) return -1;
- fp_t k = ((ts_elder_ray_params_t *)c)->k;
+ fp_t k = ((ts_elder_ray_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t a = 1.0 / k;
fp_t *ema = calloc( n, sizeof( fp_t ) );
diff --git a/lib/ema_variable.c b/lib/ema_variable.c
index c20fee2..38f505e 100644
--- a/lib/ema_variable.c
+++ b/lib/ema_variable.c
@@ -31,9 +31,8 @@ int ts_ema_variable(
{
TS_PROLOGUE( ts_ema_variable_p );
if ( !c ) return -1;
- fp_t k = ((ts_ema_variable_params_t *)c)->k;
+ fp_t k = ((ts_ema_variable_params_t const *)c)->k;
if (k <= 0) return -1;
- if (n == 0) return -1;
fp_t alpha = 2.0 / (k + 1.0);
y[0][0] = x[0][0];
diff --git a/lib/envelope.c b/lib/envelope.c
index 1ddda0c..0813ee5 100644
--- a/lib/envelope.c
+++ b/lib/envelope.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_envelope_p = { .n_inputs = 1, .n_outputs = 2, .n_constan
uint_t ts_envelope_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_envelope_params_t *)c)->k > 0 ? ((ts_envelope_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_envelope_params_t const *)c)->k > 0 ? ((ts_envelope_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_envelope(
@@ -32,8 +32,8 @@ int ts_envelope(
{
TS_PROLOGUE( ts_envelope_p );
if ( !c ) return -1;
- uint_t k = ((ts_envelope_params_t *)c)->k;
- fp_t pct = ((ts_envelope_params_t *)c)->pct;
+ uint_t k = ((ts_envelope_params_t const *)c)->k;
+ fp_t pct = ((ts_envelope_params_t const *)c)->pct;
if (k == 0 || n < k) return -1;
fp_t sum = 0;
diff --git a/lib/exponential.c b/lib/exponential.c
index b3a6205..a4e19c9 100644
--- a/lib/exponential.c
+++ b/lib/exponential.c
@@ -36,7 +36,7 @@ int ts_exponential(
{
TS_PROLOGUE( ts_exponential_p );
if ( !c ) return -1;
- fp_t b = ((ts_exponential_params_t *)c)->b;
+ fp_t b = ((ts_exponential_params_t const *)c)->b;
if (b <= 0) return -1;
for( uint_t i = 0; i < n; ++i )
diff --git a/lib/factorial.c b/lib/factorial.c
index 8e64fa3..7e82ffb 100644
--- a/lib/factorial.c
+++ b/lib/factorial.c
@@ -8,6 +8,7 @@
// Outputs: 1 (n!)
// Constants: 0
+#include <math.h>
#include "ts.h"
@@ -31,7 +32,7 @@ int ts_factorial(
(void)c;
for( uint_t i = 0; i < n; ++i )
{
- if (x[0][i] < 0) { y[0][i] = NAN; continue; }
+ if (isnan(x[0][i]) || isinf(x[0][i]) || x[0][i] < 0) { y[0][i] = NAN; continue; }
fp_t result = 1.0;
uint_t k = (uint_t)x[0][i];
if (k > 170) k = 170;
diff --git a/lib/fill_indicator.c b/lib/fill_indicator.c
index 9cb9cbc..448c32d 100644
--- a/lib/fill_indicator.c
+++ b/lib/fill_indicator.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_fill_indicator_p = { .n_inputs = 4, .n_outputs = 1, .n_c
uint_t ts_fill_indicator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_fill_indicator_params_t *)c)->k > 0 ? ((ts_fill_indicator_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_fill_indicator_params_t const *)c)->k > 0 ? ((ts_fill_indicator_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_fill_indicator(
@@ -31,7 +31,7 @@ int ts_fill_indicator(
{
TS_PROLOGUE( ts_fill_indicator_p );
if ( !c ) return -1;
- uint_t k = ((ts_fill_indicator_params_t *)c)->k;
+ uint_t k = ((ts_fill_indicator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/fisher_transform.c b/lib/fisher_transform.c
index 2b416ba..1bf8c51 100644
--- a/lib/fisher_transform.c
+++ b/lib/fisher_transform.c
@@ -20,7 +20,7 @@ ts_parameter_t const ts_fisher_transform_p = { .n_inputs = 4, .n_outputs = 2, .n
uint_t ts_fisher_transform_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_fisher_transform_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_fisher_transform_params_t const *)c)->k - 1 : 0 );
}
int ts_fisher_transform(
@@ -31,7 +31,7 @@ int ts_fisher_transform(
{
TS_PROLOGUE( ts_fisher_transform_p );
if ( !c ) return -1;
- uint_t k = ((ts_fisher_transform_params_t *)c)->k;
+ uint_t k = ((ts_fisher_transform_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = k - 1; i < n; ++i)
diff --git a/lib/fractal_chaos_bands.c b/lib/fractal_chaos_bands.c
index 57bbf00..1cbef90 100644
--- a/lib/fractal_chaos_bands.c
+++ b/lib/fractal_chaos_bands.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_fractal_chaos_bands_p = { .n_inputs = 4, .n_outputs = 2,
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 );
+ return ( c ? ((ts_fractal_chaos_bands_params_t const *)c)->k / 2 : 0 );
}
int ts_fractal_chaos_bands(
@@ -33,7 +33,8 @@ int ts_fractal_chaos_bands(
{
TS_PROLOGUE( ts_fractal_chaos_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_fractal_chaos_bands_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_fractal_chaos_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t alpha = 2.0 / (k + 1.0);
@@ -69,6 +70,13 @@ int ts_fractal_chaos_bands(
y[0][i] = ema_upper;
y[1][i] = ema_lower;
}
+
+ for ( uint_t i = n - half_k; i < n; ++i )
+ {
+ y[0][i] = 0;
+ y[1][i] = 0;
+ }
+
return 0;
}
diff --git a/lib/fractal_chaos_oscillator.c b/lib/fractal_chaos_oscillator.c
index 5c845d3..835bb05 100644
--- a/lib/fractal_chaos_oscillator.c
+++ b/lib/fractal_chaos_oscillator.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_fractal_chaos_oscillator_p = { .n_inputs = 4, .n_outputs
uint_t ts_fractal_chaos_oscillator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_fractal_chaos_oscillator_params_t *)c)->k / 2 : 0 );
+ return ( c ? ((ts_fractal_chaos_oscillator_params_t const *)c)->k / 2 : 0 );
}
int ts_fractal_chaos_oscillator(
@@ -33,7 +33,7 @@ int ts_fractal_chaos_oscillator(
{
TS_PROLOGUE( ts_fractal_chaos_oscillator_p );
if ( !c ) return -1;
- uint_t k = ((ts_fractal_chaos_oscillator_params_t *)c)->k;
+ uint_t k = ((ts_fractal_chaos_oscillator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t alpha = 2.0 / (k + 1.0);
diff --git a/lib/gamma_pdf.c b/lib/gamma_pdf.c
index 977f8b7..7a8370c 100644
--- a/lib/gamma_pdf.c
+++ b/lib/gamma_pdf.c
@@ -34,7 +34,7 @@ int ts_gamma_pdf(
{
TS_PROLOGUE( ts_gamma_pdf_p );
if ( !c ) return -1;
- fp_t shape = ((ts_gamma_pdf_params_t *)c)->shape;
+ fp_t shape = ((ts_gamma_pdf_params_t const *)c)->shape;
if (shape <= 0.0) return -1;
for( uint_t i = 0; i < n; ++i )
diff --git a/lib/gcd.c b/lib/gcd.c
index 44068cf..8ca3861 100644
--- a/lib/gcd.c
+++ b/lib/gcd.c
@@ -31,18 +31,25 @@ int ts_gcd(
{
TS_PROLOGUE( ts_gcd_p );
(void)c;
- for( uint_t i = 0; i < n; ++i )
- {
- long a = (long)fabs(x[0][i]);
- long b = (long)fabs(x[1][i]);
- while( b )
- {
- long t = b;
- b = a % b;
- a = t;
- }
- y[0][i] = (fp_t)a;
- }
+ for( uint_t i = 0; i < n; ++i )
+ {
+ fp_t ax = fabs(x[0][i]);
+ fp_t bx = fabs(x[1][i]);
+ if (ax > 9223372036854775807.0 || bx > 9223372036854775807.0)
+ {
+ y[0][i] = 0;
+ continue;
+ }
+ long a = (long)ax;
+ long b = (long)bx;
+ while( b )
+ {
+ long t = b;
+ b = a % b;
+ a = t;
+ }
+ y[0][i] = (fp_t)fabs((fp_t)a);
+ }
return 0;
}
diff --git a/lib/gopalakrishnan_range_index.c b/lib/gopalakrishnan_range_index.c
index 80da0b4..17e3d66 100644
--- a/lib/gopalakrishnan_range_index.c
+++ b/lib/gopalakrishnan_range_index.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_gopalakrishnan_range_index_p = { .n_inputs = 4, .n_outpu
uint_t ts_gopalakrishnan_range_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_gopalakrishnan_range_index_params_t *)c)->k : 0 );
+ return ( c ? ((ts_gopalakrishnan_range_index_params_t const *)c)->k : 0 );
}
int ts_gopalakrishnan_range_index(
@@ -34,7 +34,7 @@ int ts_gopalakrishnan_range_index(
{
TS_PROLOGUE( ts_gopalakrishnan_range_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_gopalakrishnan_range_index_params_t *)c)->k;
+ uint_t k = ((ts_gopalakrishnan_range_index_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
fp_t sum_abs = 0;
diff --git a/lib/harmonic.c b/lib/harmonic.c
index 2c69ee8..c9920c9 100644
--- a/lib/harmonic.c
+++ b/lib/harmonic.c
@@ -1,10 +1,10 @@
-// Harmonic
+// Harmonic Number
//
// harmonic
//
-// Harmonic mean
+// Harmonic number H(n) = Σ(1/k) for k=1..n
//
-// H = n / Σ(1/x_i)
+// H(n) = 1 + 1/2 + 1/3 + ... + 1/n
//
// Inputs: 1
// Outputs: 1
diff --git a/lib/high_low_bands.c b/lib/high_low_bands.c
index 544796f..cc05feb 100644
--- a/lib/high_low_bands.c
+++ b/lib/high_low_bands.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_high_low_bands_p = { .n_inputs = 4, .n_outputs = 2, .n_c
uint_t ts_high_low_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? 2 * ((ts_high_low_bands_params_t *)c)->k - 2 : 0 );
+ return ( c ? 2 * ((ts_high_low_bands_params_t const *)c)->k - 2 : 0 );
}
int ts_high_low_bands(
@@ -34,7 +34,7 @@ int ts_high_low_bands(
{
TS_PROLOGUE( ts_high_low_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_high_low_bands_params_t *)c)->k;
+ uint_t k = ((ts_high_low_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = 2 * k - 2; i < n; ++i )
diff --git a/lib/highest_high.c b/lib/highest_high.c
index d3ac753..22bd845 100644
--- a/lib/highest_high.c
+++ b/lib/highest_high.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_highest_high_p = { .n_inputs = 4, .n_outputs = 1, .n_con
uint_t ts_highest_high_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_highest_high_params_t *)c)->k > 0 ? ((ts_highest_high_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_highest_high_params_t const *)c)->k > 0 ? ((ts_highest_high_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_highest_high(
@@ -34,7 +34,7 @@ int ts_highest_high(
{
TS_PROLOGUE( ts_highest_high_p );
if ( !c ) return -1;
- uint_t k = ((ts_highest_high_params_t *)c)->k;
+ uint_t k = ((ts_highest_high_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t max_val = ts_h( x, 0 );
diff --git a/lib/historical_volatility.c b/lib/historical_volatility.c
index cde0d91..5848d1c 100644
--- a/lib/historical_volatility.c
+++ b/lib/historical_volatility.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_historical_volatility_p = { .n_inputs = 1, .n_outputs =
uint_t ts_historical_volatility_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_historical_volatility_params_t *)c)->k > 0 ? ((ts_historical_volatility_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_historical_volatility_params_t const *)c)->k > 0 ? ((ts_historical_volatility_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_historical_volatility(
@@ -34,7 +34,7 @@ int ts_historical_volatility(
{
TS_PROLOGUE( ts_historical_volatility_p );
if ( !c ) return -1;
- uint_t k = ((ts_historical_volatility_params_t *)c)->k;
+ uint_t k = ((ts_historical_volatility_params_t const *)c)->k;
if (k == 0 || n < k + 1) return -1;
for ( uint_t d = k - 1; d < n - 1; ++d )
diff --git a/lib/hull_ma.c b/lib/hull_ma.c
index e412a6f..1870397 100644
--- a/lib/hull_ma.c
+++ b/lib/hull_ma.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_hull_ma_p = { .n_inputs = 1, .n_outputs = 1, .n_constant
uint_t ts_hull_ma_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_hull_ma_params_t *)c)->k + (uint_t)sqrt((fp_t)((ts_hull_ma_params_t *)c)->k) - 2 : 0 );
+ return ( c ? ((ts_hull_ma_params_t const *)c)->k + (uint_t)sqrt((fp_t)((ts_hull_ma_params_t const *)c)->k) - 2 : 0 );
}
int ts_hull_ma(
@@ -36,7 +36,7 @@ int ts_hull_ma(
TS_PROLOGUE( ts_hull_ma_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_hull_ma_params_t *)c)->k;
+ uint_t k = ((ts_hull_ma_params_t const *)c)->k;
if (k < 2) return -1;
uint_t half_k = k / 2;
diff --git a/lib/hurst_exponent.c b/lib/hurst_exponent.c
index aa58036..3eea141 100644
--- a/lib/hurst_exponent.c
+++ b/lib/hurst_exponent.c
@@ -34,7 +34,7 @@ int ts_hurst_exponent(
{
TS_PROLOGUE( ts_hurst_exponent_p );
if ( !c ) return -1;
- uint_t k = ((ts_hurst_exponent_params_t *)c)->k;
+ uint_t k = ((ts_hurst_exponent_params_t const *)c)->k;
if (k == 0 || k > n) return -1;
for ( uint_t i = 0; i < n; ++i )
diff --git a/lib/ichimoku.c b/lib/ichimoku.c
index 76f85e6..da63626 100644
--- a/lib/ichimoku.c
+++ b/lib/ichimoku.c
@@ -42,7 +42,7 @@ int ts_ichimoku(
if ( c )
{
- ts_ichimoku_params_t *p = (ts_ichimoku_params_t *)c;
+ ts_ichimoku_params_t const *p = (ts_ichimoku_params_t const *)c;
if ( p->tenkan > 0 ) tenkan = p->tenkan;
if ( p->kijun > 0 ) kijun = p->kijun;
if ( p->senkou > 0 ) senkou = p->senkou;
diff --git a/lib/kalman_filter.c b/lib/kalman_filter.c
index f7adf6f..a5ac5bf 100644
--- a/lib/kalman_filter.c
+++ b/lib/kalman_filter.c
@@ -36,12 +36,11 @@ int ts_kalman_filter(
TS_PROLOGUE( ts_kalman_filter_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- fp_t Q = ((ts_kalman_filter_params_t *)c)->Q;
- fp_t R = ((ts_kalman_filter_params_t *)c)->R;
+ fp_t Q = ((ts_kalman_filter_params_t const *)c)->Q;
+ fp_t R = ((ts_kalman_filter_params_t const *)c)->R;
if (Q < 0 || R < 0) return -1;
if (isnan(Q) || isnan(R)) return -1;
- if (n == 0) return -1;
fp_t x_est = x[0][0];
/* NOTE: P=1.0 is a reasonable default for normalized data.
* For price data in the range of 100-3000, consider initializing
diff --git a/lib/kaufman_adaptive_ma.c b/lib/kaufman_adaptive_ma.c
index f56c6a1..8822344 100644
--- a/lib/kaufman_adaptive_ma.c
+++ b/lib/kaufman_adaptive_ma.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_kaufman_adaptive_ma_p = { .n_inputs = 1, .n_outputs = 1,
uint_t ts_kaufman_adaptive_ma_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_kaufman_adaptive_ma_params_t *)c)->k : 0 );
+ return ( c ? ((ts_kaufman_adaptive_ma_params_t const *)c)->k : 0 );
}
int ts_kaufman_adaptive_ma(
@@ -34,7 +34,7 @@ int ts_kaufman_adaptive_ma(
{
TS_PROLOGUE( ts_kaufman_adaptive_ma_p );
if ( !c ) return -1;
- uint_t k = ((ts_kaufman_adaptive_ma_params_t *)c)->k;
+ uint_t k = ((ts_kaufman_adaptive_ma_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t ama = x[0][0];
diff --git a/lib/keltner_channel.c b/lib/keltner_channel.c
index 259be03..c4bf3f6 100644
--- a/lib/keltner_channel.c
+++ b/lib/keltner_channel.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_keltner_channel_p = { .n_inputs = 4, .n_outputs = 3, .n_
uint_t ts_keltner_channel_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_keltner_channel_params_t *)c)->k : 0 );
+ return ( c ? ((ts_keltner_channel_params_t const *)c)->k : 0 );
}
int ts_keltner_channel(
@@ -34,7 +34,7 @@ int ts_keltner_channel(
{
TS_PROLOGUE( ts_keltner_channel_p );
if ( !c ) return -1;
- uint_t k = ((ts_keltner_channel_params_t *)c)->k;
+ uint_t k = ((ts_keltner_channel_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
fp_t a = 2.0 / ((fp_t)k + 1.0);
diff --git a/lib/kvo.c b/lib/kvo.c
index 229fad8..1e2a15b 100644
--- a/lib/kvo.c
+++ b/lib/kvo.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_kvo_p = { .n_inputs = 5, .n_outputs = 2, .n_constants =
uint_t ts_kvo_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_kvo_params_t *)c)->k1 > 10 ? ((ts_kvo_params_t *)c)->k1 : 10 : 0 );
+ return ( c ? ((ts_kvo_params_t const *)c)->k1 > 10 ? ((ts_kvo_params_t const *)c)->k1 : 10 : 0 );
}
int ts_kvo(
@@ -35,8 +35,8 @@ int ts_kvo(
{
TS_PROLOGUE( ts_kvo_p );
if ( !c ) return -1;
- uint_t k1 = ((ts_kvo_params_t *)c)->k1;
- fp_t f0_raw = ((ts_kvo_params_t *)c)->f0;
+ uint_t k1 = ((ts_kvo_params_t const *)c)->k1;
+ fp_t f0_raw = ((ts_kvo_params_t const *)c)->f0;
if (isnan(f0_raw) || isinf(f0_raw) || f0_raw < 0) return -1;
uint_t k10 = (uint_t)f0_raw;
if (k1 == 0) return -1;
diff --git a/lib/lag.c b/lib/lag.c
index 1e3f657..22d1146 100644
--- a/lib/lag.c
+++ b/lib/lag.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_lag_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_lag_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_lag_params_t *)c)->k : 0 );
+ return ( c ? ((ts_lag_params_t const *)c)->k : 0 );
}
int ts_lag(
@@ -35,10 +35,10 @@ int ts_lag(
{
TS_PROLOGUE( ts_lag_p );
if ( !c ) return -1;
- uint_t k = ((ts_lag_params_t *)c)->k;
+ uint_t k = ((ts_lag_params_t const *)c)->k;
if (k == 0) return -1;
- fp_t insert = ((ts_lag_params_t *)c)->insert;
+ fp_t insert = ((ts_lag_params_t const *)c)->insert;
if (n <= k) return -1;
diff --git a/lib/lcm.c b/lib/lcm.c
index c8b52ef..8fbbce5 100644
--- a/lib/lcm.c
+++ b/lib/lcm.c
@@ -31,30 +31,34 @@ int ts_lcm(
{
TS_PROLOGUE( ts_lcm_p );
(void)c;
- for( uint_t i = 0; i < n; ++i )
- {
- fp_t ax = fabs(x[0][i]);
- fp_t bx = fabs(x[1][i]);
- if (ax > 1e15 || bx > 1e15) { y[0][i] = 0.0; continue; }
- long a = (long)ax;
- long b = (long)bx;
- if( !a || !b )
- {
- y[0][i] = 0.0;
- }
- else
- {
- long ta = a;
- long tb = b;
- while( tb )
- {
- long t = tb;
- tb = ta % tb;
- ta = t;
- }
- y[0][i] = (fp_t)(a / ta) * (fp_t)b;
- }
- }
+ for( uint_t i = 0; i < n; ++i )
+ {
+ fp_t ax = fabs(x[0][i]);
+ fp_t bx = fabs(x[1][i]);
+ if (ax > 9223372036854775807.0 || bx > 9223372036854775807.0)
+ {
+ y[0][i] = 0.0;
+ continue;
+ }
+ long a = (long)ax;
+ long b = (long)bx;
+ if( !a || !b )
+ {
+ y[0][i] = 0.0;
+ }
+ else
+ {
+ long ta = a;
+ long tb = b;
+ while( tb )
+ {
+ long t = tb;
+ tb = ta % tb;
+ ta = t;
+ }
+ y[0][i] = (fp_t)(a / ta) * (fp_t)b;
+ }
+ }
return 0;
}
diff --git a/lib/linear_regression.c b/lib/linear_regression.c
index 5d595bc..842df1f 100644
--- a/lib/linear_regression.c
+++ b/lib/linear_regression.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_linear_regression_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_linear_regression_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression(
@@ -35,7 +35,7 @@ int ts_linear_regression(
TS_PROLOGUE( ts_linear_regression_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_linear_regression_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
// Precompute constant x sums (x values are always 0..k-1)
diff --git a/lib/linear_regression_angle.c b/lib/linear_regression_angle.c
index 22928bc..0f60024 100644
--- a/lib/linear_regression_angle.c
+++ b/lib/linear_regression_angle.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_linear_regression_angle_p = { .n_inputs = 1, .n_outputs
uint_t ts_linear_regression_angle_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_angle_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_angle_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression_angle(
@@ -34,7 +34,7 @@ int ts_linear_regression_angle(
{
TS_PROLOGUE( ts_linear_regression_angle_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_regression_angle_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_angle_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/linear_regression_forecast.c b/lib/linear_regression_forecast.c
index 02a78a8..73f974c 100644
--- a/lib/linear_regression_forecast.c
+++ b/lib/linear_regression_forecast.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_linear_regression_forecast_p = { .n_inputs = 1, .n_outpu
uint_t ts_linear_regression_forecast_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_forecast_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_forecast_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression_forecast(
@@ -34,7 +34,7 @@ int ts_linear_regression_forecast(
{
TS_PROLOGUE( ts_linear_regression_forecast_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_regression_forecast_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_forecast_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/linear_regression_intercept.c b/lib/linear_regression_intercept.c
index 2b26478..adb153c 100644
--- a/lib/linear_regression_intercept.c
+++ b/lib/linear_regression_intercept.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_linear_regression_intercept_p = { .n_inputs = 1, .n_outp
uint_t ts_linear_regression_intercept_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_intercept_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_intercept_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression_intercept(
@@ -33,7 +33,7 @@ int ts_linear_regression_intercept(
{
TS_PROLOGUE( ts_linear_regression_intercept_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_regression_intercept_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_intercept_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/linear_regression_r2.c b/lib/linear_regression_r2.c
index 5cec662..c15ee67 100644
--- a/lib/linear_regression_r2.c
+++ b/lib/linear_regression_r2.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_linear_regression_r2_p = { .n_inputs = 1, .n_outputs = 1
uint_t ts_linear_regression_r2_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_r2_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_r2_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression_r2(
@@ -34,7 +34,7 @@ int ts_linear_regression_r2(
{
TS_PROLOGUE( ts_linear_regression_r2_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_regression_r2_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_r2_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/linear_regression_slope.c b/lib/linear_regression_slope.c
index d20ca8e..5bdc01f 100644
--- a/lib/linear_regression_slope.c
+++ b/lib/linear_regression_slope.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_linear_regression_slope_p = { .n_inputs = 1, .n_outputs
uint_t ts_linear_regression_slope_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_regression_slope_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_regression_slope_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_regression_slope(
@@ -33,7 +33,7 @@ int ts_linear_regression_slope(
{
TS_PROLOGUE( ts_linear_regression_slope_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_regression_slope_params_t *)c)->k;
+ uint_t k = ((ts_linear_regression_slope_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/linear_weighted_ma.c b/lib/linear_weighted_ma.c
index 70f660e..e11bf54 100644
--- a/lib/linear_weighted_ma.c
+++ b/lib/linear_weighted_ma.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_linear_weighted_ma_p = { .n_inputs = 1, .n_outputs = 1,
uint_t ts_linear_weighted_ma_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_linear_weighted_ma_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_linear_weighted_ma_params_t const *)c)->k - 1 : 0 );
}
int ts_linear_weighted_ma(
@@ -33,7 +33,7 @@ int ts_linear_weighted_ma(
{
TS_PROLOGUE( ts_linear_weighted_ma_p );
if ( !c ) return -1;
- uint_t k = ((ts_linear_weighted_ma_params_t *)c)->k;
+ uint_t k = ((ts_linear_weighted_ma_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t w_sum = 0;
diff --git a/lib/logarithm.c b/lib/logarithm.c
index 7451976..9ca98a6 100755
--- a/lib/logarithm.c
+++ b/lib/logarithm.c
@@ -36,8 +36,8 @@ int ts_logarithm(
{
TS_PROLOGUE( ts_logarithm_p );
if ( !c ) return -1;
- fp_t b = ((ts_logarithm_params_t *)c)->b;
- if (b == 0 || b == 1.0) return -1;
+ fp_t b = ((ts_logarithm_params_t const *)c)->b;
+ if (b <= 0 || b == 1.0 || isnan(b) || isinf(b)) return -1;
b = _ts_reciprocal( log( b ) );
diff --git a/lib/lowest_low.c b/lib/lowest_low.c
index d8ac284..687cdeb 100644
--- a/lib/lowest_low.c
+++ b/lib/lowest_low.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_lowest_low_p = { .n_inputs = 4, .n_outputs = 1, .n_const
uint_t ts_lowest_low_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_lowest_low_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_lowest_low_params_t const *)c)->k - 1 : 0 );
}
int ts_lowest_low(
@@ -33,7 +33,7 @@ int ts_lowest_low(
{
TS_PROLOGUE( ts_lowest_low_p );
if ( !c ) return -1;
- uint_t k = ((ts_lowest_low_params_t *)c)->k;
+ uint_t k = ((ts_lowest_low_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t min_val = ts_l( x, 0 );
diff --git a/lib/macd.c b/lib/macd.c
index 362f251..63db964 100644
--- a/lib/macd.c
+++ b/lib/macd.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_macd_p = { .n_inputs = 1, .n_outputs = 3, .n_constants =
uint_t ts_macd_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)(((ts_macd_params_t *)c)->slow_k + ((ts_macd_params_t *)c)->signal_k - 2) : 0 );
+ return ( c ? (uint_t)(((ts_macd_params_t const *)c)->slow_k + ((ts_macd_params_t const *)c)->signal_k - 2) : 0 );
}
int ts_macd(
@@ -37,13 +37,13 @@ int ts_macd(
TS_PROLOGUE( ts_macd_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- fp_t fast_k = ((ts_macd_params_t *)c)->fast_k;
- fp_t slow_k = ((ts_macd_params_t *)c)->slow_k;
- fp_t signal_k = ((ts_macd_params_t *)c)->signal_k;
+ fp_t fast_k = ((ts_macd_params_t const *)c)->fast_k;
+ fp_t slow_k = ((ts_macd_params_t const *)c)->slow_k;
+ fp_t signal_k = ((ts_macd_params_t const *)c)->signal_k;
if (fast_k < 1 || slow_k < 1 || signal_k < 1) return -1;
if (isnan(fast_k) || isnan(slow_k) || isnan(signal_k)) return -1;
- if (n == 0) return -1;
+ if (isinf(fast_k) || isinf(slow_k) || isinf(signal_k)) return -1;
fp_t fast_a = 2.0 / (fast_k + 1.0);
fp_t slow_a = 2.0 / (slow_k + 1.0);
@@ -52,9 +52,17 @@ int ts_macd(
fp_t fast_ema = x[0][0];
fp_t slow_ema = x[0][0];
+ if (slow_k > (fp_t)UINT64_MAX || signal_k > (fp_t)UINT64_MAX) return -1;
uint_t total_offset = (uint_t)(slow_k + signal_k - 2);
if (n <= total_offset) return -1;
+ // Initialize warm-up period to NAN
+ for (uint_t i = 0; i < total_offset; i++) {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ y[2][i] = NAN;
+ }
+
// Compute EMAs up to total_offset
for( uint_t i = 1; i <= total_offset; ++i )
{
diff --git a/lib/maximum.c b/lib/maximum.c
index f4d124a..0f1539b 100755
--- a/lib/maximum.c
+++ b/lib/maximum.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_maximum_p = { .n_inputs = 1, .n_outputs = 1, .n_constant
uint_t ts_maximum_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_maximum_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_maximum_params_t const *)c)->k - 1 : 0 );
}
int ts_maximum(
@@ -32,7 +32,7 @@ int ts_maximum(
{
TS_PROLOGUE( ts_maximum_p );
if ( !c ) return -1;
- uint_t k = ((ts_maximum_params_t *)c)->k;
+ uint_t k = ((ts_maximum_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k - 1;
diff --git a/lib/mesa_sine_wave.c b/lib/mesa_sine_wave.c
index 8ed5fa6..91fbcd2 100644
--- a/lib/mesa_sine_wave.c
+++ b/lib/mesa_sine_wave.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_mesa_sine_wave_p = { .n_inputs = 1, .n_outputs = 2, .n_c
uint_t ts_mesa_sine_wave_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_mesa_sine_wave_params_t *)c)->k : 0 );
+ return ( c ? ((ts_mesa_sine_wave_params_t const *)c)->k : 0 );
}
int ts_mesa_sine_wave(
@@ -35,64 +35,64 @@ int ts_mesa_sine_wave(
{
TS_PROLOGUE( ts_mesa_sine_wave_p );
if ( !c ) return -1;
- uint_t k = ((ts_mesa_sine_wave_params_t *)c)->k;
+ uint_t k = ((ts_mesa_sine_wave_params_t const *)c)->k;
if (k < 2 || n < k) return -1;
- fp_t *sma = calloc(n, sizeof(fp_t));
- if (!sma) return -1;
+ fp_t *sma = calloc( n, sizeof( fp_t ) );
+ if ( !sma ) return -1;
- for (uint_t i = 0; i < n; ++i)
+ for ( uint_t i = 0; i < n; ++i )
{
- if (i < k - 1)
+ if ( i < k - 1 )
{
fp_t sum = 0;
- for (uint_t j = 0; j <= i; ++j)
+ for ( uint_t j = 0; j <= i; ++j )
sum += x[0][j];
- sma[i] = sum / (i + 1);
+ sma[i] = sum / (fp_t)( i + 1 );
}
else
{
fp_t sum = 0;
- for (uint_t j = i - k + 1; j <= i; ++j)
+ for ( uint_t j = i - k + 1; j <= i; ++j )
sum += x[0][j];
- sma[i] = sum / k;
+ sma[i] = sum / (fp_t)k;
}
}
fp_t ema_roc = 0;
uint_t ema_period = 5;
- fp_t ema_a = 2.0 / (ema_period + 1);
+ fp_t ema_a = 2.0 / ( (fp_t)ema_period + 1 );
fp_t phase = 0;
int_t first = 1;
- for (uint_t j = 0; j < n && j < k; ++j) { y[0][j] = 0; y[1][j] = 0; }
- for (uint_t i = k; i < n; ++i)
+ for ( uint_t j = 0; j < n && j < k; ++j ) { y[0][j] = 0; y[1][j] = 0; }
+ for ( uint_t i = k; i < n; ++i )
{
fp_t roc = sma[i] - sma[i - 2];
- if (first)
+ if ( first )
{
ema_roc = roc;
first = 0;
}
else
{
- ema_roc = ema_roc + ema_a * (roc - ema_roc);
+ ema_roc = ema_roc + ema_a * ( roc - ema_roc );
}
fp_t smoothed = ema_roc;
- if (smoothed > 1.0) smoothed = 1.0;
- if (smoothed < 0.01) smoothed = 0.01;
+ if ( smoothed > 1.0 ) smoothed = 1.0;
+ if ( smoothed < 0.01 ) smoothed = 0.01;
fp_t wperiod = 2 * PI / smoothed;
- if (wperiod < 5) wperiod = 5;
- if (wperiod > 12) wperiod = 12;
+ if ( wperiod < 5 ) wperiod = 5;
+ if ( wperiod > 12 ) wperiod = 12;
- if (smoothed >= 1.0)
+ if ( smoothed >= 1.0 )
{
phase = 0;
}
- else if (smoothed <= 0.01)
+ else if ( smoothed <= 0.01 )
{
phase = 2 * PI;
}
@@ -100,13 +100,13 @@ int ts_mesa_sine_wave(
{
phase += 2 * PI / wperiod;
}
- while (phase > 2 * PI) phase -= 2 * PI;
+ while ( phase > 2 * PI ) phase -= 2 * PI;
- y[0][i] = cos(phase);
- y[1][i] = cos(phase + PI / 2);
+ y[0][i] = cos( phase );
+ y[1][i] = cos( phase + PI / 2 );
}
- free(sma);
+ free( sma );
return 0;
}
diff --git a/lib/mfi.c b/lib/mfi.c
index c93803c..155c347 100644
--- a/lib/mfi.c
+++ b/lib/mfi.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_mfi_p = { .n_inputs = 5, .n_outputs = 1, .n_constants =
uint_t ts_mfi_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_mfi_params_t *)c)->k : 0 );
+ return ( c ? ((ts_mfi_params_t const *)c)->k : 0 );
}
int ts_mfi(
@@ -34,7 +34,7 @@ int ts_mfi(
{
TS_PROLOGUE( ts_mfi_p );
if ( !c ) return -1;
- uint_t k = ((ts_mfi_params_t *)c)->k;
+ uint_t k = ((ts_mfi_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
fp_t *tp = calloc( n, sizeof( fp_t ) );
diff --git a/lib/midpoint.c b/lib/midpoint.c
index c28cdff..da24eba 100644
--- a/lib/midpoint.c
+++ b/lib/midpoint.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_midpoint_p = { .n_inputs = 1, .n_outputs = 1, .n_constan
uint_t ts_midpoint_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_midpoint_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_midpoint_params_t const *)c)->k - 1 : 0 );
}
int ts_midpoint(
@@ -33,7 +33,7 @@ int ts_midpoint(
{
TS_PROLOGUE( ts_midpoint_p );
if ( !c ) return -1;
- uint_t k = ((ts_midpoint_params_t *)c)->k;
+ uint_t k = ((ts_midpoint_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/midprice.c b/lib/midprice.c
index d26a58e..8c8dfe0 100644
--- a/lib/midprice.c
+++ b/lib/midprice.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_midprice_p = { .n_inputs = 1, .n_outputs = 1, .n_constan
uint_t ts_midprice_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_midprice_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_midprice_params_t const *)c)->k - 1 : 0 );
}
int ts_midprice(
@@ -33,7 +33,7 @@ int ts_midprice(
{
TS_PROLOGUE( ts_midprice_p );
if ( !c ) return -1;
- uint_t k = ((ts_midprice_params_t *)c)->k;
+ uint_t k = ((ts_midprice_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/minimum.c b/lib/minimum.c
index d2ba15f..5a2814c 100755
--- a/lib/minimum.c
+++ b/lib/minimum.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_minimum_p = { .n_inputs = 1, .n_outputs = 1, .n_constant
uint_t ts_minimum_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_minimum_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_minimum_params_t const *)c)->k - 1 : 0 );
}
int ts_minimum(
@@ -32,7 +32,7 @@ int ts_minimum(
{
TS_PROLOGUE( ts_minimum_p );
if ( !c ) return -1;
- uint_t k = ((ts_minimum_params_t *)c)->k;
+ uint_t k = ((ts_minimum_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k - 1;
diff --git a/lib/minmax.c b/lib/minmax.c
index 4bee598..8763266 100644
--- a/lib/minmax.c
+++ b/lib/minmax.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_minmax_p = { .n_inputs = 1, .n_outputs = 2, .n_constants
uint_t ts_minmax_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_minmax_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_minmax_params_t const *)c)->k - 1 : 0 );
}
int ts_minmax(
@@ -33,7 +33,7 @@ int ts_minmax(
{
TS_PROLOGUE( ts_minmax_p );
if ( !c ) return -1;
- uint_t k = ((ts_minmax_params_t *)c)->k;
+ uint_t k = ((ts_minmax_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/missing_bar_count.c b/lib/missing_bar_count.c
index e6f548e..d001a5f 100644
--- a/lib/missing_bar_count.c
+++ b/lib/missing_bar_count.c
@@ -34,8 +34,7 @@ int ts_missing_bar_count(
{
TS_PROLOGUE( ts_missing_bar_count_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t threshold = ((ts_missing_bar_count_params_t *)c)->threshold;
+ fp_t threshold = ((ts_missing_bar_count_params_t const *)c)->threshold;
y[0][0] = 0;
diff --git a/lib/momentum.c b/lib/momentum.c
index f0d89fd..8e1dcf4 100644
--- a/lib/momentum.c
+++ b/lib/momentum.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_momentum_p = { .n_inputs = 1, .n_outputs = 1, .n_constan
uint_t ts_momentum_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_momentum_params_t *)c)->k : 0 );
+ return ( c ? ((ts_momentum_params_t const *)c)->k : 0 );
}
int ts_momentum(
@@ -34,7 +34,7 @@ int ts_momentum(
TS_PROLOGUE( ts_momentum_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_momentum_params_t *)c)->k;
+ uint_t k = ((ts_momentum_params_t const *)c)->k;
for( uint_t i = k; i < n; ++i )
{
diff --git a/lib/moving_linear_regression.c b/lib/moving_linear_regression.c
index ceb34d5..66b750c 100644
--- a/lib/moving_linear_regression.c
+++ b/lib/moving_linear_regression.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_moving_linear_regression_p = { .n_inputs = 1, .n_outputs
uint_t ts_moving_linear_regression_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_moving_linear_regression_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_moving_linear_regression_params_t const *)c)->k - 1 : 0 );
}
int ts_moving_linear_regression(
@@ -33,7 +33,7 @@ int ts_moving_linear_regression(
{
TS_PROLOGUE( ts_moving_linear_regression_p );
if ( !c ) return -1;
- uint_t k = ((ts_moving_linear_regression_params_t *)c)->k;
+ uint_t k = ((ts_moving_linear_regression_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/moving_linear_regression_r2.c b/lib/moving_linear_regression_r2.c
index 3015a25..71eb081 100644
--- a/lib/moving_linear_regression_r2.c
+++ b/lib/moving_linear_regression_r2.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_moving_linear_regression_r2_p = { .n_inputs = 1, .n_outp
uint_t ts_moving_linear_regression_r2_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_moving_linear_regression_r2_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_moving_linear_regression_r2_params_t const *)c)->k - 1 : 0 );
}
int ts_moving_linear_regression_r2(
@@ -34,7 +34,7 @@ int ts_moving_linear_regression_r2(
{
TS_PROLOGUE( ts_moving_linear_regression_r2_p );
if ( !c ) return -1;
- uint_t k = ((ts_moving_linear_regression_r2_params_t *)c)->k;
+ uint_t k = ((ts_moving_linear_regression_r2_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum_x = 0, sum_x2 = 0;
diff --git a/lib/natr.c b/lib/natr.c
index ce58bb1..724e068 100644
--- a/lib/natr.c
+++ b/lib/natr.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_natr_p = { .n_inputs = 4, .n_outputs = 1, .n_constants =
uint_t ts_natr_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_natr_params_t *)c)->k : 0 );
+ return ( c ? ((ts_natr_params_t const *)c)->k : 0 );
}
int ts_natr(
@@ -36,10 +36,14 @@ int ts_natr(
{
TS_PROLOGUE( ts_natr_p );
if ( !c ) return -1;
- uint_t k = ((ts_natr_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_natr_params_t const *)c)->k;
if (k == 0) return -1;
if (n < k + 1) return -1;
+ for( uint_t i = 0; i < k; ++i )
+ y[0][i] = NAN;
+
for( uint_t i = k; i < n; ++i )
{
fp_t tr_sum = 0;
diff --git a/lib/nvi.c b/lib/nvi.c
index f4d3397..c38238d 100644
--- a/lib/nvi.c
+++ b/lib/nvi.c
@@ -30,7 +30,6 @@ int ts_nvi(
{
TS_PROLOGUE( ts_nvi_p );
(void)c;
- if (n == 0) return -1;
fp_t nvi = 1000;
diff --git a/lib/obv.c b/lib/obv.c
index 3765ba3..33bb7a7 100644
--- a/lib/obv.c
+++ b/lib/obv.c
@@ -31,7 +31,6 @@ int ts_obv(
TS_PROLOGUE( ts_obv_p );
(void)c;
TS_CHECK_INPUT(x, x_n, n);
- if (n == 0) return -1;
fp_t obv = 0;
y[0][0] = 0;
diff --git a/lib/on_balance_volume_rate.c b/lib/on_balance_volume_rate.c
index 7183c23..242f00a 100644
--- a/lib/on_balance_volume_rate.c
+++ b/lib/on_balance_volume_rate.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_on_balance_volume_rate_p = { .n_inputs = 5, .n_outputs =
uint_t ts_on_balance_volume_rate_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)((ts_on_balance_volume_rate_params_t *)c)->f0 + 1 : 0 );
+ return ( c ? (uint_t)((ts_on_balance_volume_rate_params_t const *)c)->f0 + 1 : 0 );
}
int ts_on_balance_volume_rate(
@@ -34,7 +34,7 @@ int ts_on_balance_volume_rate(
{
TS_PROLOGUE( ts_on_balance_volume_rate_p );
if ( !c ) return -1;
- uint_t k = (uint_t)((ts_on_balance_volume_rate_params_t *)c)->f0;
+ uint_t k = (uint_t)((ts_on_balance_volume_rate_params_t const *)c)->f0;
if (k == 0 || k >= n) return -1;
fp_t obv = 0;
diff --git a/lib/oscillator_cross.c b/lib/oscillator_cross.c
index 0c6c5f8..1510738 100644
--- a/lib/oscillator_cross.c
+++ b/lib/oscillator_cross.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_oscillator_cross_p = { .n_inputs = 1, .n_outputs = 1, .n
uint_t ts_oscillator_cross_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)((ts_oscillator_cross_params_t *)c)->slow : 0 );
+ return ( c ? (uint_t)((ts_oscillator_cross_params_t const *)c)->slow : 0 );
}
int ts_oscillator_cross(
@@ -34,10 +34,9 @@ int ts_oscillator_cross(
{
TS_PROLOGUE( ts_oscillator_cross_p );
if ( !c ) return -1;
- fp_t const fast = ((ts_oscillator_cross_params_t *)c)->fast;
- fp_t const slow = ((ts_oscillator_cross_params_t *)c)->slow;
+ fp_t const fast = ((ts_oscillator_cross_params_t const *)c)->fast;
+ fp_t const slow = ((ts_oscillator_cross_params_t const *)c)->slow;
if (fast == 0 || slow == 0) return -1;
- if (n == 0) return -1;
fp_t const fast_a = 1.0 / fast;
fp_t const slow_a = 1.0 / slow;
fp_t fast_e = x[0][0];
diff --git a/lib/osma.c b/lib/osma.c
index a5a2756..3698b09 100644
--- a/lib/osma.c
+++ b/lib/osma.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_osma_p = { .n_inputs = 5, .n_outputs = 1, .n_constants =
uint_t ts_osma_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)((ts_osma_params_t *)c)->slow_k : 0 );
+ return ( c ? (uint_t)((ts_osma_params_t const *)c)->slow_k : 0 );
}
int ts_osma(
@@ -35,12 +35,11 @@ int ts_osma(
{
TS_PROLOGUE( ts_osma_p );
if ( !c ) return -1;
- fp_t fast_k = ((ts_osma_params_t *)c)->fast_k;
- fp_t slow_k = ((ts_osma_params_t *)c)->slow_k;
- fp_t signal_k = ((ts_osma_params_t *)c)->signal_k;
+ fp_t fast_k = ((ts_osma_params_t const *)c)->fast_k;
+ fp_t slow_k = ((ts_osma_params_t const *)c)->slow_k;
+ fp_t signal_k = ((ts_osma_params_t const *)c)->signal_k;
if (fast_k == 0 || slow_k == 0 || signal_k == 0) return -1;
- if (n == 0) return -1;
fp_t fast_a = 1.0 / fast_k;
fp_t slow_a = 1.0 / slow_k;
diff --git a/lib/parabolic_sar.c b/lib/parabolic_sar.c
index ff84834..cd699aa 100644
--- a/lib/parabolic_sar.c
+++ b/lib/parabolic_sar.c
@@ -35,12 +35,11 @@ int ts_parabolic_sar(
{
TS_PROLOGUE( ts_parabolic_sar_p );
if ( !c ) return -1;
- fp_t step = ((ts_parabolic_sar_params_t *)c)->step;
- fp_t max_af = ((ts_parabolic_sar_params_t *)c)->max_af;
+ fp_t step = ((ts_parabolic_sar_params_t const *)c)->step;
+ fp_t max_af = ((ts_parabolic_sar_params_t const *)c)->max_af;
if (step <= 0 || max_af <= 0) return -1;
if (isnan(step) || isnan(max_af)) return -1;
if (step > max_af) return -1;
- if (n == 0) return -1;
int_t trend = 1;
fp_t sar = ts_l( x, 0 );
diff --git a/lib/performance_ratio.c b/lib/performance_ratio.c
index ffd0ece..a429b8b 100644
--- a/lib/performance_ratio.c
+++ b/lib/performance_ratio.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_performance_ratio_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_performance_ratio_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_performance_ratio_params_t *)c)->k : 0 );
+ return ( c ? ((ts_performance_ratio_params_t const *)c)->k : 0 );
}
int ts_performance_ratio(
@@ -34,8 +34,8 @@ int ts_performance_ratio(
{
TS_PROLOGUE( ts_performance_ratio_p );
if ( !c ) return -1;
- uint_t k = ((ts_performance_ratio_params_t *)c)->k;
- if (k <= 1 || n == 0) return -1;
+ uint_t k = ((ts_performance_ratio_params_t const *)c)->k;
+ if (k <= 1) return -1;
fp_t factor = (fp_t)k / (k - 1);
diff --git a/lib/poisson_pdf.c b/lib/poisson_pdf.c
index e1e2d59..60a62ac 100644
--- a/lib/poisson_pdf.c
+++ b/lib/poisson_pdf.c
@@ -34,7 +34,7 @@ int ts_poisson_pdf(
{
TS_PROLOGUE( ts_poisson_pdf_p );
if ( !c ) return -1;
- fp_t lambda = ((ts_poisson_pdf_params_t *)c)->lambda;
+ fp_t lambda = ((ts_poisson_pdf_params_t const *)c)->lambda;
if (lambda < 0.0 || isnan(lambda) || isinf(lambda)) return -1;
for( uint_t i = 0; i < n; ++i )
{
diff --git a/lib/polynomial.c b/lib/polynomial.c
index 2914fe6..82d8fba 100644
--- a/lib/polynomial.c
+++ b/lib/polynomial.c
@@ -33,7 +33,7 @@ int ts_polynomial(
{
fp_t base = x[0][i];
fp_t exponent = x[1][i];
- if( base < 0.0 && exponent != (fp_t)(long)exponent ) { y[0][i] = 0; continue; }
+ if( base < 0.0 && exponent != (fp_t)(long)exponent ) { y[0][i] = NAN; continue; }
y[0][i] = pow(base, exponent);
}
return 0;
diff --git a/lib/power.c b/lib/power.c
index 41bb644..1d9c8cd 100755
--- a/lib/power.c
+++ b/lib/power.c
@@ -36,7 +36,7 @@ int ts_power(
{
TS_PROLOGUE( ts_power_p );
if ( !c ) return -1;
- fp_t r = ((ts_power_params_t *)c)->r;
+ fp_t r = ((ts_power_params_t const *)c)->r;
for( uint_t i = 0; i < n; ++i )
{
diff --git a/lib/ppo.c b/lib/ppo.c
index b2b3bbf..f367c28 100644
--- a/lib/ppo.c
+++ b/lib/ppo.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_ppo_p = { .n_inputs = 5, .n_outputs = 2, .n_constants =
uint_t ts_ppo_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? (uint_t)(((ts_ppo_params_t *)c)->slow_k + ((ts_ppo_params_t *)c)->signal_k - 2) : 0 );
+ return ( c ? (uint_t)(((ts_ppo_params_t const *)c)->slow_k + ((ts_ppo_params_t const *)c)->signal_k - 2) : 0 );
}
int ts_ppo(
@@ -35,12 +35,11 @@ int ts_ppo(
{
TS_PROLOGUE( ts_ppo_p );
if ( !c ) return -1;
- fp_t fast_k = ((ts_ppo_params_t *)c)->fast_k;
- fp_t slow_k = ((ts_ppo_params_t *)c)->slow_k;
- fp_t signal_k = ((ts_ppo_params_t *)c)->signal_k;
+ fp_t fast_k = ((ts_ppo_params_t const *)c)->fast_k;
+ fp_t slow_k = ((ts_ppo_params_t const *)c)->slow_k;
+ fp_t signal_k = ((ts_ppo_params_t const *)c)->signal_k;
if (fast_k == 0 || slow_k == 0 || signal_k == 0) return -1;
- if (n == 0) return -1;
fp_t fast_a = 1.0 / fast_k;
fp_t slow_a = 1.0 / slow_k;
diff --git a/lib/pretty_good_oscillator.c b/lib/pretty_good_oscillator.c
index 65a05c2..2dbc6f1 100644
--- a/lib/pretty_good_oscillator.c
+++ b/lib/pretty_good_oscillator.c
@@ -30,7 +30,7 @@ int ts_pretty_good_oscillator(
{
TS_PROLOGUE( ts_pretty_good_oscillator_p );
(void)c;
- if (n == 0) return -1;
+
fp_t ema14 = x[0][0];
fp_t ema30 = x[0][0];
fp_t ema90 = x[0][0];
diff --git a/lib/price_channel.c b/lib/price_channel.c
index 9aba070..4a3129c 100644
--- a/lib/price_channel.c
+++ b/lib/price_channel.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_price_channel_p = { .n_inputs = 1, .n_outputs = 3, .n_co
uint_t ts_price_channel_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_price_channel_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_price_channel_params_t const *)c)->k - 1 : 0 );
}
int ts_price_channel(
@@ -33,7 +33,7 @@ int ts_price_channel(
{
TS_PROLOGUE( ts_price_channel_p );
if ( !c ) return -1;
- uint_t k = ((ts_price_channel_params_t *)c)->k;
+ uint_t k = ((ts_price_channel_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/price_momentum_oscillator.c b/lib/price_momentum_oscillator.c
index b03f350..d92fccb 100644
--- a/lib/price_momentum_oscillator.c
+++ b/lib/price_momentum_oscillator.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_price_momentum_oscillator_p = { .n_inputs = 1, .n_output
uint_t ts_price_momentum_oscillator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_price_momentum_oscillator_params_t *)c)->k : 0 );
+ return ( c ? ((ts_price_momentum_oscillator_params_t const *)c)->k : 0 );
}
int ts_price_momentum_oscillator(
@@ -33,7 +33,7 @@ int ts_price_momentum_oscillator(
{
TS_PROLOGUE( ts_price_momentum_oscillator_p );
if ( !c ) return -1;
- uint_t k = ((ts_price_momentum_oscillator_params_t *)c)->k;
+ uint_t k = ((ts_price_momentum_oscillator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = k; i < n; ++i)
diff --git a/lib/price_rate_of_change.c b/lib/price_rate_of_change.c
index 8f26548..4dc9834 100644
--- a/lib/price_rate_of_change.c
+++ b/lib/price_rate_of_change.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_price_rate_of_change_p = { .n_inputs = 1, .n_outputs = 1
uint_t ts_price_rate_of_change_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_price_rate_of_change_params_t *)c)->k : 0 );
+ return ( c ? ((ts_price_rate_of_change_params_t const *)c)->k : 0 );
}
int ts_price_rate_of_change(
@@ -33,7 +33,7 @@ int ts_price_rate_of_change(
{
TS_PROLOGUE( ts_price_rate_of_change_p );
if ( !c ) return -1;
- uint_t k = ((ts_price_rate_of_change_params_t *)c)->k;
+ uint_t k = ((ts_price_rate_of_change_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = k; i < n; ++i)
diff --git a/lib/prime_number_bands.c b/lib/prime_number_bands.c
index ac94e7b..bb01c2c 100644
--- a/lib/prime_number_bands.c
+++ b/lib/prime_number_bands.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_prime_number_bands_p = { .n_inputs = 1, .n_outputs = 3,
uint_t ts_prime_number_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_prime_number_bands_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_prime_number_bands_params_t const *)c)->k - 1 : 0 );
}
int ts_prime_number_bands(
@@ -34,7 +34,7 @@ int ts_prime_number_bands(
{
TS_PROLOGUE( ts_prime_number_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_prime_number_bands_params_t *)c)->k;
+ uint_t k = ((ts_prime_number_bands_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/prings_special_k.c b/lib/prings_special_k.c
index 91a40ba..9191567 100644
--- a/lib/prings_special_k.c
+++ b/lib/prings_special_k.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_prings_special_k_p = { .n_inputs = 4, .n_outputs = 2, .n
uint_t ts_prings_special_k_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_prings_special_k_params_t *)c)->k1 > 0 && ((ts_prings_special_k_params_t *)c)->k2 > 0 ? ((ts_prings_special_k_params_t *)c)->k1 + ((ts_prings_special_k_params_t *)c)->k2 - 2 : 0 : 0 );
+ return ( c ? ((ts_prings_special_k_params_t const *)c)->k1 > 0 && ((ts_prings_special_k_params_t const *)c)->k2 > 0 ? ((ts_prings_special_k_params_t const *)c)->k1 + ((ts_prings_special_k_params_t const *)c)->k2 - 2 : 0 : 0 );
}
int ts_prings_special_k(
@@ -34,8 +34,8 @@ int ts_prings_special_k(
{
TS_PROLOGUE( ts_prings_special_k_p );
if ( !c ) return -1;
- uint_t k1 = ((ts_prings_special_k_params_t *)c)->k1;
- uint_t k2 = ((ts_prings_special_k_params_t *)c)->k2;
+ uint_t k1 = ((ts_prings_special_k_params_t const *)c)->k1;
+ uint_t k2 = ((ts_prings_special_k_params_t const *)c)->k2;
if (k1 == 0 || k2 == 0) return -1;
fp_t ema = 0;
diff --git a/lib/psychological_line.c b/lib/psychological_line.c
index 35fd912..86ebcd3 100644
--- a/lib/psychological_line.c
+++ b/lib/psychological_line.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_psychological_line_p = { .n_inputs = 4, .n_outputs = 1,
uint_t ts_psychological_line_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_psychological_line_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_psychological_line_params_t const *)c)->k - 1 : 0 );
}
int ts_psychological_line(
@@ -33,7 +33,7 @@ int ts_psychological_line(
{
TS_PROLOGUE( ts_psychological_line_p );
if ( !c ) return -1;
- uint_t k = ((ts_psychological_line_params_t *)c)->k;
+ uint_t k = ((ts_psychological_line_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t sum = 0;
diff --git a/lib/pvi.c b/lib/pvi.c
index 26265d5..55ecb84 100644
--- a/lib/pvi.c
+++ b/lib/pvi.c
@@ -30,9 +30,8 @@ int ts_pvi(
{
TS_PROLOGUE( ts_pvi_p );
(void)c;
- fp_t pvi = 1000;
- if (n == 0) return -1;
+ fp_t pvi = 1000;
y[0][0] = pvi;
diff --git a/lib/qstick.c b/lib/qstick.c
index d2f4361..dd7d7da 100644
--- a/lib/qstick.c
+++ b/lib/qstick.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_qstick_p = { .n_inputs = 4, .n_outputs = 1, .n_constants
uint_t ts_qstick_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_qstick_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_qstick_params_t const *)c)->k - 1 : 0 );
}
int ts_qstick(
@@ -33,7 +33,7 @@ int ts_qstick(
{
TS_PROLOGUE( ts_qstick_p );
if ( !c ) return -1;
- uint_t k = ((ts_qstick_params_t *)c)->k;
+ uint_t k = ((ts_qstick_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/rainbow_oscillator.c b/lib/rainbow_oscillator.c
index 1a56b55..463577f 100644
--- a/lib/rainbow_oscillator.c
+++ b/lib/rainbow_oscillator.c
@@ -58,7 +58,7 @@ int ts_rainbow_oscillator(
max_ma = ma_values[p];
}
- if( max_ma == min_ma )
+ if( fabs(max_ma - min_ma) < TS_FILL_ZERO_THRESHOLD )
y[0][i] = 0;
else
y[0][i] = ( x[0][i] - min_ma ) / ( max_ma - min_ma ) * 100.0;
diff --git a/lib/random_walk_index.c b/lib/random_walk_index.c
index b4375e5..aa8e5f5 100644
--- a/lib/random_walk_index.c
+++ b/lib/random_walk_index.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_random_walk_index_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_random_walk_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_random_walk_index_params_t *)c)->k : 0 );
+ return ( c ? ((ts_random_walk_index_params_t const *)c)->k : 0 );
}
int ts_random_walk_index(
@@ -34,7 +34,7 @@ int ts_random_walk_index(
{
TS_PROLOGUE( ts_random_walk_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_random_walk_index_params_t *)c)->k;
+ uint_t k = ((ts_random_walk_index_params_t const *)c)->k;
if (k == 0 || n < k + 1) return -1;
fp_t sum_abs = 0;
diff --git a/lib/rank.c b/lib/rank.c
index 392b63f..200bbbe 100644
--- a/lib/rank.c
+++ b/lib/rank.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_rank_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_rank_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_rank_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_rank_params_t const *)c)->k - 1 : 0 );
}
int ts_rank(
@@ -33,7 +33,7 @@ int ts_rank(
{
TS_PROLOGUE( ts_rank_p );
if ( !c ) return -1;
- uint_t k = ((ts_rank_params_t *)c)->k;
+ uint_t k = ((ts_rank_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/ratio.c b/lib/ratio.c
index 8568476..813d46c 100755
--- a/lib/ratio.c
+++ b/lib/ratio.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_ratio_p = { .n_inputs = 1, .n_outputs = 1, .n_constants
uint_t ts_ratio_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_ratio_params_t *)c)->k : 0 );
+ return ( c ? ((ts_ratio_params_t const *)c)->k : 0 );
}
int ts_ratio(
@@ -35,7 +35,7 @@ int ts_ratio(
{
TS_PROLOGUE( ts_ratio_p );
if ( !c ) return -1;
- uint_t k = ((ts_ratio_params_t *)c)->k;
+ uint_t k = ((ts_ratio_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k;
diff --git a/lib/ravi.c b/lib/ravi.c
index fcb3095..efe8353 100644
--- a/lib/ravi.c
+++ b/lib/ravi.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_ravi_p = { .n_inputs = 4, .n_outputs = 2, .n_constants =
uint_t ts_ravi_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_ravi_params_t *)c)->k + (uint_t)((ts_ravi_params_t *)c)->k2 - 2 : 0 );
+ return ( c ? ((ts_ravi_params_t const *)c)->k + (uint_t)((ts_ravi_params_t const *)c)->k2 - 2 : 0 );
}
int ts_ravi(
@@ -36,19 +36,19 @@ int ts_ravi(
{
TS_PROLOGUE( ts_ravi_p );
if ( !c ) return -1;
- uint_t k = ((ts_ravi_params_t *)c)->k;
- fp_t k2 = ((ts_ravi_params_t *)c)->k2;
+ uint_t k = ((ts_ravi_params_t const *)c)->k;
+ fp_t k2 = ((ts_ravi_params_t const *)c)->k2;
- if( k == 0 || k2 == 0 ) return -1;
+ if( k == 0 || k2 <= 0 || isnan(k2) || isinf(k2) ) return -1;
- fp_t *num_buf = calloc( n, sizeof( fp_t ) );
+ fp_t *num_buf = calloc( n, sizeof( fp_t ) );
fp_t *den_buf = calloc( n, sizeof( fp_t ) );
if( !num_buf || !den_buf ) { free( num_buf ); free( den_buf ); return -1; }
for( uint_t i = 0; i < n; ++i )
{
- num_buf[i] = (x[3][i] - x[0][i]) + (x[3][i] - (i > 0 ? x[3][i - 1] : x[3][i]));
- den_buf[i] = fabs(x[1][i] - x[2][i]) + fabs(x[3][i] - x[0][i]);
+ num_buf[i] = ( x[3][i] - x[0][i] ) + ( x[3][i] - ( i > 0 ? x[3][i - 1] : x[3][i] ) );
+ den_buf[i] = fabs( x[1][i] - x[2][i] ) + fabs( x[3][i] - x[0][i] );
}
fp_t num_sum = 0;
@@ -65,14 +65,14 @@ int ts_ravi(
fp_t sig_a = 1.0 / k2;
uint_t offset = k + (uint_t)k2 - 2;
- for (uint_t i = 0; i < offset; ++i) { y[0][i] = 0; y[1][i] = 0; }
+ for ( uint_t i = 0; i < offset; ++i ) { y[0][i] = 0; y[1][i] = 0; }
for( uint_t i = k; i < n; ++i )
{
num_sum = num_sum - num_buf[i - k] + num_buf[i];
den_sum = den_sum - den_buf[i - k] + den_buf[i];
rvi = ( den_sum != 0 ) ? num_sum / den_sum : 0;
- sig = sig + sig_a * (rvi - sig);
+ sig = sig + sig_a * ( rvi - sig );
if( i >= offset )
{
diff --git a/lib/regression_linear_least_squares.c b/lib/regression_linear_least_squares.c
index 49123bb..5e37e38 100755
--- a/lib/regression_linear_least_squares.c
+++ b/lib/regression_linear_least_squares.c
@@ -34,7 +34,7 @@ ts_parameter_t const ts_regression_linear_least_squares_p = { .n_inputs = 2, .n_
uint_t ts_regression_linear_least_squares_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_regression_linear_least_squares_params_t *)c)->k : 0 );
+ return ( c ? ((ts_regression_linear_least_squares_params_t const *)c)->k : 0 );
}
int ts_regression_linear_least_squares(
@@ -45,7 +45,7 @@ int ts_regression_linear_least_squares(
{
TS_PROLOGUE( ts_regression_linear_least_squares_p );
if ( !c ) return -1;
- uint_t k = ((ts_regression_linear_least_squares_params_t *)c)->k;
+ uint_t k = ((ts_regression_linear_least_squares_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k;
diff --git a/lib/relative_volatility.c b/lib/relative_volatility.c
index 9682a2d..77b6968 100644
--- a/lib/relative_volatility.c
+++ b/lib/relative_volatility.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_relative_volatility_p = { .n_inputs = 1, .n_outputs = 1,
uint_t ts_relative_volatility_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_relative_volatility_params_t *)c)->k - 1 : 0 );
+ return ( c ? ((ts_relative_volatility_params_t const *)c)->k - 1 : 0 );
}
int ts_relative_volatility(
@@ -34,7 +34,7 @@ int ts_relative_volatility(
{
TS_PROLOGUE( ts_relative_volatility_p );
if ( !c ) return -1;
- uint_t k = ((ts_relative_volatility_params_t *)c)->k;
+ uint_t k = ((ts_relative_volatility_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/roc.c b/lib/roc.c
index 3b45ecd..cfa16aa 100644
--- a/lib/roc.c
+++ b/lib/roc.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_roc_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_roc_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_roc_params_t *)c)->k : 0 );
+ return ( c ? ((ts_roc_params_t const *)c)->k : 0 );
}
int ts_roc(
@@ -34,7 +34,7 @@ int ts_roc(
TS_PROLOGUE( ts_roc_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_roc_params_t *)c)->k;
+ uint_t k = ((ts_roc_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/rocp.c b/lib/rocp.c
index 6575d85..4a1ddad 100644
--- a/lib/rocp.c
+++ b/lib/rocp.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_rocp_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_rocp_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_rocp_params_t *)c)->k : 0 );
+ return ( c ? ((ts_rocp_params_t const *)c)->k : 0 );
}
int ts_rocp(
@@ -33,7 +33,7 @@ int ts_rocp(
{
TS_PROLOGUE( ts_rocp_p );
if ( !c ) return -1;
- uint_t k = ((ts_rocp_params_t *)c)->k;
+ uint_t k = ((ts_rocp_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/rocr.c b/lib/rocr.c
index d11cb91..35a2351 100644
--- a/lib/rocr.c
+++ b/lib/rocr.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_rocr_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_rocr_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_rocr_params_t *)c)->k : 0 );
+ return ( c ? ((ts_rocr_params_t const *)c)->k : 0 );
}
int ts_rocr(
@@ -33,7 +33,7 @@ int ts_rocr(
{
TS_PROLOGUE( ts_rocr_p );
if ( !c ) return -1;
- uint_t k = ((ts_rocr_params_t *)c)->k;
+ uint_t k = ((ts_rocr_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/rocr100.c b/lib/rocr100.c
index b90413f..22b6dbf 100644
--- a/lib/rocr100.c
+++ b/lib/rocr100.c
@@ -21,7 +21,7 @@ ts_parameter_t const ts_rocr100_p = { .n_inputs = 1, .n_outputs = 1, .n_constant
uint_t ts_rocr100_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_rocr100_params_t *)c)->k : 0 );
+ return ( c ? ((ts_rocr100_params_t const *)c)->k : 0 );
}
int ts_rocr100(
@@ -32,7 +32,7 @@ int ts_rocr100(
{
TS_PROLOGUE( ts_rocr100_p );
if ( !c ) return -1;
- uint_t k = ((ts_rocr100_params_t *)c)->k;
+ uint_t k = ((ts_rocr100_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/root.c b/lib/root.c
index a5e7dca..140a3c6 100755
--- a/lib/root.c
+++ b/lib/root.c
@@ -36,7 +36,7 @@ int ts_root(
{
TS_PROLOGUE( ts_root_p );
if ( !c ) return -1;
- fp_t r = ((ts_root_params_t *)c)->r;
+ fp_t r = ((ts_root_params_t const *)c)->r;
if (r == 0) return -1;
for( uint_t i = 0; i < n; ++i )
diff --git a/lib/rsi.c b/lib/rsi.c
index bf21c5e..4bc6e60 100644
--- a/lib/rsi.c
+++ b/lib/rsi.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_rsi_p = { .n_inputs = 1, .n_outputs = 1, .n_constants =
uint_t ts_rsi_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_rsi_params_t *)c)->k : 0 );
+ return ( c ? ((ts_rsi_params_t const *)c)->k : 0 );
}
int ts_rsi(
@@ -37,7 +37,7 @@ int ts_rsi(
TS_PROLOGUE( ts_rsi_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_rsi_params_t *)c)->k;
+ uint_t k = ((ts_rsi_params_t const *)c)->k;
if (k == 0 || n <= k) return -1;
for (uint_t i = 0; i < k; ++i) y[0][i] = NAN;
diff --git a/lib/schaff_trend_cycle.c b/lib/schaff_trend_cycle.c
index f4584e6..0ff3e1c 100644
--- a/lib/schaff_trend_cycle.c
+++ b/lib/schaff_trend_cycle.c
@@ -35,9 +35,8 @@ int ts_schaff_trend_cycle(
{
TS_PROLOGUE( ts_schaff_trend_cycle_p );
if ( !c ) return -1;
- uint_t period = ((ts_schaff_trend_cycle_params_t *)c)->period;
+ uint_t period = ((ts_schaff_trend_cycle_params_t const *)c)->period;
if (period == 0) period = 3;
- if (n == 0) return -1;
if (period > n) { for (uint_t j = 0; j < n; ++j) { y[0][j] = 0; y[1][j] = 0; } return 0; }
uint_t fast = 10;
diff --git a/lib/shinohara_intensity_ratio.c b/lib/shinohara_intensity_ratio.c
index fcdd364..5476892 100644
--- a/lib/shinohara_intensity_ratio.c
+++ b/lib/shinohara_intensity_ratio.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_shinohara_intensity_ratio_p = { .n_inputs = 4, .n_output
uint_t ts_shinohara_intensity_ratio_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_shinohara_intensity_ratio_params_t *)c)->k > 0 ? ((ts_shinohara_intensity_ratio_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_shinohara_intensity_ratio_params_t const *)c)->k > 0 ? ((ts_shinohara_intensity_ratio_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_shinohara_intensity_ratio(
@@ -35,7 +35,7 @@ int ts_shinohara_intensity_ratio(
{
TS_PROLOGUE( ts_shinohara_intensity_ratio_p );
if ( !c ) return -1;
- uint_t k = ((ts_shinohara_intensity_ratio_params_t *)c)->k;
+ uint_t k = ((ts_shinohara_intensity_ratio_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t *intensity = calloc( n, sizeof( fp_t ) );
diff --git a/lib/sigmoid.c b/lib/sigmoid.c
index 05ea126..33fd58b 100644
--- a/lib/sigmoid.c
+++ b/lib/sigmoid.c
@@ -44,10 +44,11 @@ int ts_sigmoid(
{
TS_PROLOGUE( ts_sigmoid_p );
if ( !c ) return -1;
- fp_t m = ((ts_sigmoid_params_t *)c)->m;
- fp_t L = ((ts_sigmoid_params_t *)c)->L;
- fp_t b = ((ts_sigmoid_params_t *)c)->b;
+ fp_t m = ((ts_sigmoid_params_t const *)c)->m;
+ fp_t L = ((ts_sigmoid_params_t const *)c)->L;
+ fp_t b = ((ts_sigmoid_params_t const *)c)->b;
+ if (L == 0 || isnan(L) || isinf(L) || isnan(m) || isinf(m)) return -1;
m = -( 4.0 * m ) / L;
b = b - ( 0.5 * L );
diff --git a/lib/slope.c b/lib/slope.c
index ca4fd22..5005fff 100755
--- a/lib/slope.c
+++ b/lib/slope.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_slope_p = { .n_inputs = 1, .n_outputs = 1, .n_constants
uint_t ts_slope_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_slope_params_t *)c)->k : 0 );
+ return ( c ? ((ts_slope_params_t const *)c)->k : 0 );
}
int ts_slope(
@@ -35,7 +35,7 @@ int ts_slope(
{
TS_PROLOGUE( ts_slope_p );
if ( !c ) return -1;
- uint_t k = ((ts_slope_params_t *)c)->k;
+ uint_t k = ((ts_slope_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = k;
diff --git a/lib/softplus.c b/lib/softplus.c
index b61f96b..6853f66 100644
--- a/lib/softplus.c
+++ b/lib/softplus.c
@@ -34,7 +34,12 @@ int ts_softplus(
for( uint_t i = 0; i < n; ++i )
{
fp_t xi = x[0][i];
- y[0][i] = xi > 20 ? xi : log( 1 + exp( xi ) );
+ if ( xi > 20 )
+ y[0][i] = xi;
+ else if ( xi < -37 )
+ y[0][i] = exp( xi );
+ else
+ y[0][i] = log( 1 + exp( xi ) );
}
return 0;
}
diff --git a/lib/standard_error.c b/lib/standard_error.c
index 9b0ac3b..e090deb 100644
--- a/lib/standard_error.c
+++ b/lib/standard_error.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_standard_error_p = { .n_inputs = 1, .n_outputs = 1, .n_c
uint_t ts_standard_error_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_standard_error_params_t *)c)->k > 0 ? ((ts_standard_error_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_standard_error_params_t const *)c)->k > 0 ? ((ts_standard_error_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_standard_error(
@@ -34,7 +34,7 @@ int ts_standard_error(
{
TS_PROLOGUE( ts_standard_error_p );
if ( !c ) return -1;
- uint_t k = ((ts_standard_error_params_t *)c)->k;
+ uint_t k = ((ts_standard_error_params_t const *)c)->k;
if (k < 2) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/starc_bands.c b/lib/starc_bands.c
index 0c545f8..4975952 100644
--- a/lib/starc_bands.c
+++ b/lib/starc_bands.c
@@ -26,7 +26,7 @@ ts_parameter_t const ts_starc_bands_p = { .n_inputs = 4, .n_outputs = 3, .n_cons
uint_t ts_starc_bands_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_starc_bands_params_t *)c)->k : 0 );
+ return ( c ? ((ts_starc_bands_params_t const *)c)->k : 0 );
}
int ts_starc_bands(
@@ -37,11 +37,20 @@ int ts_starc_bands(
{
TS_PROLOGUE( ts_starc_bands_p );
if ( !c ) return -1;
- uint_t k = ((ts_starc_bands_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_starc_bands_params_t const *)c)->k;
if (k == 0) return -1;
if (n < k + 1) return -1;
- fp_t mult = ((ts_starc_bands_params_t *)c)->mult;
+ fp_t mult = ((ts_starc_bands_params_t const *)c)->mult;
+ if (mult < 0 || isnan(mult) || isinf(mult)) return -1;
+
+ for( uint_t i = 0; i < k; ++i )
+ {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ y[2][i] = NAN;
+ }
for( uint_t i = k; i < n; ++i )
{
diff --git a/lib/starc_lower.c b/lib/starc_lower.c
index 97ac02f..16c5084 100644
--- a/lib/starc_lower.c
+++ b/lib/starc_lower.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_starc_lower_p = { .n_inputs = 4, .n_outputs = 1, .n_cons
uint_t ts_starc_lower_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_starc_lower_params_t *)c)->k > 0 ? ((ts_starc_lower_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_starc_lower_params_t const *)c)->k > 0 ? ((ts_starc_lower_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_starc_lower(
@@ -35,9 +35,11 @@ int ts_starc_lower(
{
TS_PROLOGUE( ts_starc_lower_p );
if ( !c ) return -1;
- uint_t k = ((ts_starc_lower_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_starc_lower_params_t const *)c)->k;
if( k == 0 ) return -1;
- fp_t mult = ((ts_starc_lower_params_t *)c)->mult;
+ fp_t mult = ((ts_starc_lower_params_t const *)c)->mult;
+ if (mult < 0 || isnan(mult) || isinf(mult)) return -1;
uint_t half_k = k / 2;
if (n <= half_k) return -1;
diff --git a/lib/starc_upper.c b/lib/starc_upper.c
index bcccb95..ad80b07 100644
--- a/lib/starc_upper.c
+++ b/lib/starc_upper.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_starc_upper_p = { .n_inputs = 4, .n_outputs = 1, .n_cons
uint_t ts_starc_upper_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_starc_upper_params_t *)c)->k : 0 );
+ return ( c ? ((ts_starc_upper_params_t const *)c)->k : 0 );
}
int ts_starc_upper(
@@ -35,8 +35,8 @@ int ts_starc_upper(
{
TS_PROLOGUE( ts_starc_upper_p );
if ( !c ) return -1;
- uint_t k = ((ts_starc_upper_params_t *)c)->k;
- fp_t mult = ((ts_starc_upper_params_t *)c)->mult;
+ uint_t k = ((ts_starc_upper_params_t const *)c)->k;
+ fp_t mult = ((ts_starc_upper_params_t const *)c)->mult;
if ( k == 0 || k >= n ) return -1;
for ( uint_t i = k; i < n; ++i )
diff --git a/lib/std_error.c b/lib/std_error.c
index f55d34e..ebcab35 100644
--- a/lib/std_error.c
+++ b/lib/std_error.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_std_error_p = { .n_inputs = 1, .n_outputs = 1, .n_consta
uint_t ts_std_error_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_std_error_params_t *)c)->k > 0 ? ((ts_std_error_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_std_error_params_t const *)c)->k > 0 ? ((ts_std_error_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_std_error(
@@ -34,7 +34,7 @@ int ts_std_error(
{
TS_PROLOGUE( ts_std_error_p );
if ( !c ) return -1;
- uint_t k = ((ts_std_error_params_t *)c)->k;
+ uint_t k = ((ts_std_error_params_t const *)c)->k;
if ( k == 0 ) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/stoch_rsi.c b/lib/stoch_rsi.c
index 81992a6..97427be 100644
--- a/lib/stoch_rsi.c
+++ b/lib/stoch_rsi.c
@@ -25,7 +25,7 @@ ts_parameter_t const ts_stoch_rsi_p = { .n_inputs = 1, .n_outputs = 2, .n_consta
uint_t ts_stoch_rsi_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_stoch_rsi_params_t *)c)->rsi_period + ((ts_stoch_rsi_params_t *)c)->stoch_period - 1 : 0 );
+ return ( c ? ((ts_stoch_rsi_params_t const *)c)->rsi_period + ((ts_stoch_rsi_params_t const *)c)->stoch_period - 1 : 0 );
}
int ts_stoch_rsi(
@@ -36,8 +36,8 @@ int ts_stoch_rsi(
{
TS_PROLOGUE( ts_stoch_rsi_p );
if ( !c ) return -1;
- uint_t rsi_period = ((ts_stoch_rsi_params_t *)c)->rsi_period;
- uint_t stoch_period = ((ts_stoch_rsi_params_t *)c)->stoch_period;
+ uint_t rsi_period = ((ts_stoch_rsi_params_t const *)c)->rsi_period;
+ uint_t stoch_period = ((ts_stoch_rsi_params_t const *)c)->stoch_period;
if (rsi_period == 0 || stoch_period == 0) return -1;
fp_t *rsi_values = NULL;
diff --git a/lib/stochastic_fast.c b/lib/stochastic_fast.c
index eb203c8..d9340ad 100644
--- a/lib/stochastic_fast.c
+++ b/lib/stochastic_fast.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_stochastic_fast_p = { .n_inputs = 4, .n_outputs = 2, .n_
uint_t ts_stochastic_fast_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_stochastic_fast_params_t *)c)->k > 0 ? 2 * ((ts_stochastic_fast_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_stochastic_fast_params_t const *)c)->k > 0 ? 2 * ((ts_stochastic_fast_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_stochastic_fast(
@@ -34,7 +34,7 @@ int ts_stochastic_fast(
TS_PROLOGUE( ts_stochastic_fast_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_stochastic_fast_params_t *)c)->k;
+ uint_t k = ((ts_stochastic_fast_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
// Initial window max/min
diff --git a/lib/stochastic_momentum_index.c b/lib/stochastic_momentum_index.c
index 5491c30..35af230 100644
--- a/lib/stochastic_momentum_index.c
+++ b/lib/stochastic_momentum_index.c
@@ -26,7 +26,7 @@ ts_parameter_t const ts_stochastic_momentum_index_p = { .n_inputs = 4, .n_output
uint_t ts_stochastic_momentum_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_stochastic_momentum_index_params_t *)c)->k1 + ((ts_stochastic_momentum_index_params_t *)c)->k2 : 0 );
+ return ( c ? ((ts_stochastic_momentum_index_params_t const *)c)->k1 + ((ts_stochastic_momentum_index_params_t const *)c)->k2 : 0 );
}
int ts_stochastic_momentum_index(
@@ -37,9 +37,9 @@ int ts_stochastic_momentum_index(
{
TS_PROLOGUE( ts_stochastic_momentum_index_p );
if ( !c ) return -1;
- uint_t k1 = ((ts_stochastic_momentum_index_params_t *)c)->k1;
- uint_t k2 = ((ts_stochastic_momentum_index_params_t *)c)->k2;
- uint_t signal_period = ((ts_stochastic_momentum_index_params_t *)c)->signal_period;
+ uint_t k1 = ((ts_stochastic_momentum_index_params_t const *)c)->k1;
+ uint_t k2 = ((ts_stochastic_momentum_index_params_t const *)c)->k2;
+ uint_t signal_period = ((ts_stochastic_momentum_index_params_t const *)c)->signal_period;
if (k1 == 0 || k2 == 0) return -1;
fp_t *midpoint = calloc(n, sizeof(fp_t));
diff --git a/lib/stochastic_slow.c b/lib/stochastic_slow.c
index 0f84e1a..35f8b47 100644
--- a/lib/stochastic_slow.c
+++ b/lib/stochastic_slow.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_stochastic_slow_p = { .n_inputs = 4, .n_outputs = 2, .n_
uint_t ts_stochastic_slow_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_stochastic_slow_params_t *)c)->k > 0 ? 3 * ((ts_stochastic_slow_params_t *)c)->k - 3 : 0 : 0 );
+ return ( c ? ((ts_stochastic_slow_params_t const *)c)->k > 0 ? 3 * ((ts_stochastic_slow_params_t const *)c)->k - 3 : 0 : 0 );
}
int ts_stochastic_slow(
@@ -35,7 +35,7 @@ int ts_stochastic_slow(
TS_PROLOGUE( ts_stochastic_slow_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_stochastic_slow_params_t *)c)->k;
+ uint_t k = ((ts_stochastic_slow_params_t const *)c)->k;
if (k == 0) return -1;
fp_t *fast_k = calloc( k, sizeof( fp_t ) );
diff --git a/lib/student_t_pdf.c b/lib/student_t_pdf.c
index 67c9f1d..ad8f256 100644
--- a/lib/student_t_pdf.c
+++ b/lib/student_t_pdf.c
@@ -34,7 +34,7 @@ int ts_student_t_pdf(
{
TS_PROLOGUE( ts_student_t_pdf_p );
if ( !c ) return -1;
- fp_t nu = ((ts_student_t_pdf_params_t *)c)->nu;
+ fp_t nu = ((ts_student_t_pdf_params_t const *)c)->nu;
if ( nu <= 0 )
{
for( uint_t i = 0; i < n; ++i ) y[0][i] = 0;
diff --git a/lib/summation.c b/lib/summation.c
index 6d0020b..01d6735 100755
--- a/lib/summation.c
+++ b/lib/summation.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_summation_p = { .n_inputs = 1, .n_outputs = 1, .n_consta
uint_t ts_summation_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_summation_params_t *)c)->k > 0 ? ((ts_summation_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_summation_params_t const *)c)->k > 0 ? ((ts_summation_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_summation(
@@ -35,7 +35,7 @@ int ts_summation(
{
TS_PROLOGUE( ts_summation_p );
if ( !c ) return -1;
- uint_t k = ((ts_summation_params_t *)c)->k;
+ uint_t k = ((ts_summation_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/supertrend.c b/lib/supertrend.c
index 4487e96..c062805 100644
--- a/lib/supertrend.c
+++ b/lib/supertrend.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_supertrend_p = { .n_inputs = 4, .n_outputs = 2, .n_const
uint_t ts_supertrend_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_supertrend_params_t *)c)->k : 0 );
+ return ( c ? ((ts_supertrend_params_t const *)c)->k : 0 );
}
int ts_supertrend(
@@ -36,8 +36,8 @@ int ts_supertrend(
TS_PROLOGUE( ts_supertrend_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_supertrend_params_t *)c)->k;
- fp_t mult = ((ts_supertrend_params_t *)c)->mult;
+ uint_t k = ((ts_supertrend_params_t const *)c)->k;
+ fp_t mult = ((ts_supertrend_params_t const *)c)->mult;
if (k == 0 || n <= k) return -1;
fp_t tr = ts_h( x, 1 ) - ts_l( x, 1 );
diff --git a/lib/swish.c b/lib/swish.c
index 7d09787..ae0105f 100644
--- a/lib/swish.c
+++ b/lib/swish.c
@@ -34,7 +34,12 @@ int ts_swish(
for( uint_t i = 0; i < n; ++i )
{
fp_t xi = x[0][i];
- y[0][i] = xi / ( 1 + exp( -xi ) );
+ if ( xi > 20 )
+ y[0][i] = xi;
+ else if ( xi < -20 )
+ y[0][i] = xi * exp( xi );
+ else
+ y[0][i] = xi / ( 1 + exp( -xi ) );
}
return 0;
}
diff --git a/lib/synthetic_yield.c b/lib/synthetic_yield.c
index c2c8d62..fecde51 100644
--- a/lib/synthetic_yield.c
+++ b/lib/synthetic_yield.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_synthetic_yield_p = { .n_inputs = 1, .n_outputs = 1, .n_
uint_t ts_synthetic_yield_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_synthetic_yield_params_t *)c)->k : 0 );
+ return ( c ? ((ts_synthetic_yield_params_t const *)c)->k : 0 );
}
int ts_synthetic_yield(
@@ -34,9 +34,10 @@ int ts_synthetic_yield(
{
TS_PROLOGUE( ts_synthetic_yield_p );
if ( !c ) return -1;
- uint_t k = ((ts_synthetic_yield_params_t *)c)->k;
+ uint_t k = ((ts_synthetic_yield_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
+ for( uint_t i = 0; i < k; ++i ) y[0][i] = 0;
for( uint_t i = k; i < n; ++i )
{
if( x[0][i - k] == 0 ) { y[0][i] = 0; continue; }
diff --git a/lib/t3.c b/lib/t3.c
index 4689d54..34aff86 100644
--- a/lib/t3.c
+++ b/lib/t3.c
@@ -29,7 +29,6 @@ int ts_t3(
{
TS_PROLOGUE( ts_t3_p );
(void)c;
- if (n == 0) return -1;
uint_t k = 5;
diff --git a/lib/test.c b/lib/test.c
index 56c47eb..d022f6e 100755
--- a/lib/test.c
+++ b/lib/test.c
@@ -33,42 +33,55 @@ void ts_test_all( void )
}
bool ts_test(
- void ( *ts_function )(
- fp_t * const *y,
- fp_t const * const *x,
- uint_t n,
- ts_constant_t const *c
+ int ( *ts_function )(
+ 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
),
- uint_t ( *ts_offset )(
- ts_constant_t const *c
+ uint_t ( *ts_offset )(
+ ts_constant_t const *c
),
fp_t const * const *x,
fp_t const * const *e,
uint_t n,
ts_constant_t const *c,
ts_parameter_t const *m )
-{
+{
+ if ( !ts_function || !ts_offset || !m || !e || !x ) return false;
+
uint_t offset = ts_offset( c );
- uint_t y_n = n - offset;
+ if ( offset >= n ) return false;
+ uint_t y_len = n - offset;
bool result = true;
-
- fp_t *y[m->y];
- for( uint_t i = 0; i < m->y; i++ )
+ fp_t *y[m->n_outputs];
+
+ for( uint_t i = 0; i < m->n_outputs; i++ )
{
- fp_t *tmp = malloc( y_n * sizeof( fp_t ) );
+ fp_t *tmp = calloc( y_len, sizeof( fp_t ) );
+ if ( !tmp )
+ {
+ for ( uint_t j = 0; j < i; j++ ) free( y[j] );
+ return false;
+ }
y[i] = tmp;
}
- ts_function( y, x, n, c );
+ if ( ts_function( y, m->n_outputs, x, m->n_inputs, n, c ) != 0 )
+ {
+ for ( uint_t i = 0; i < m->n_outputs; i++ ) free( y[i] );
+ return false;
+ }
- for( uint_t i = 0; i < m->y; ++i )
+ for( uint_t i = 0; i < m->n_outputs; ++i )
{
- for( uint_t j = 0; j < y_n; ++j )
+ for( uint_t j = 0; j < y_len; ++j )
{
- // _ts_assert_approximate( y[i][j], e[i][j], TS_TEST_EPSILON );
- result &= _ts_is_approximate( y[i][j], e[i][j], TS_TEST_EPSILON );
- }
+ result &= _ts_is_approximate( y[i][j], e[i][j], TS_TEST_EPSILON );
+ }
free( y[i] );
}
diff --git a/lib/trade_volume_index.c b/lib/trade_volume_index.c
index 2e1b50d..a123379 100644
--- a/lib/trade_volume_index.c
+++ b/lib/trade_volume_index.c
@@ -24,20 +24,20 @@ uint_t ts_trade_volume_index_offset( ts_constant_t const *c )
}
int ts_trade_volume_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_trade_volume_index_p );
- (void)c;
+ 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_trade_volume_index_p );
+ (void)c;
if (n < 2) return -1;
for( uint_t i = 0; i + 1 < n; ++i )
- {
- fp_t roc = x[3][i] != 0 ? ( x[3][i + 1] - x[3][i] ) / x[3][i] : 0;
- y[0][i] = ( i == 0 ? 0 : y[0][i - 1] ) + roc * x[4][i + 1];
- }
- y[0][n - 1] = y[0][n - 2];
- return 0;
+ {
+ fp_t roc = x[3][i] != 0 ? ( x[3][i + 1] - x[3][i] ) / x[3][i] : 0;
+ y[0][i] = ( i == 0 ? 0 : y[0][i - 1] ) + roc * x[4][i + 1];
}
+ y[0][n - 1] = y[0][n - 2];
+ return 0;
+}
diff --git a/lib/trend_intensity_index.c b/lib/trend_intensity_index.c
index 451e440..2f8a628 100644
--- a/lib/trend_intensity_index.c
+++ b/lib/trend_intensity_index.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_trend_intensity_index_p = { .n_inputs = 5, .n_outputs =
uint_t ts_trend_intensity_index_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_trend_intensity_index_params_t *)c)->k > 0 ? ((ts_trend_intensity_index_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_trend_intensity_index_params_t const *)c)->k > 0 ? ((ts_trend_intensity_index_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_trend_intensity_index(
@@ -33,7 +33,7 @@ int ts_trend_intensity_index(
{
TS_PROLOGUE( ts_trend_intensity_index_p );
if ( !c ) return -1;
- uint_t k = ((ts_trend_intensity_index_params_t *)c)->k;
+ uint_t k = ((ts_trend_intensity_index_params_t const *)c)->k;
if ( k == 0 || n < k ) return -1;
fp_t signed_sum = 0;
diff --git a/lib/trix.c b/lib/trix.c
index a9aac88..ee5ed71 100755
--- a/lib/trix.c
+++ b/lib/trix.c
@@ -31,9 +31,8 @@ int ts_trix(
{
TS_PROLOGUE( ts_trix_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t a = ((ts_trix_params_t *)c)->a;
+ fp_t a = ((ts_trix_params_t const *)c)->a;
if (a == 0) return -1;
fp_t ema1 = x[0][0];
diff --git a/lib/ts.c b/lib/ts.c
index 68e2f41..e035625 100755
--- a/lib/ts.c
+++ b/lib/ts.c
@@ -7,18 +7,19 @@
fp_t * ts_fill( fp_t *x, uint_t n, fp_t x0, fp_t x1 )
{
- fp_t step = ( x1 - x0 ) / ( n - 1 );
+ if ( !x || n == 0 ) return x;
- if( x0 == 0.0 && x1 == 0.0 )
+ fp_t step = n > 1 ? ( x1 - x0 ) / ( fp_t )( n - 1 ) : 0.0;
+
+ if( fabs( x0 ) < TS_FILL_ZERO_THRESHOLD && fabs( x1 ) < TS_FILL_ZERO_THRESHOLD )
{
- memset(x, 0, sizeof( fp_t ) * n );
+ memset( x, 0, sizeof( fp_t ) * n );
}
-
else
{
for( uint_t i = 0; i < n; i++ )
{
- x[i] = x0 + ( i * step );
+ x[i] = x0 + ( (fp_t)i * step );
}
}
@@ -26,42 +27,48 @@ fp_t * ts_fill( fp_t *x, uint_t n, fp_t x0, fp_t x1 )
}
-void ts_print( fp_t *x, uint_t n )
+void ts_print( fp_t const *x, uint_t n, FILE *stream )
{
- fputc('[', stdout);
+ if ( !x || n == 0 ) return;
+
+ FILE *out = stream ? stream : stdout;
- uint_t i;
- for( i = 0; i < n - 1; i++ )
- {
- fprintf(stdout, "%f,", x[i]);
- }
+ fputc( '[', out );
+
+ for ( uint_t i = 0; i < n - 1; i++ )
+ {
+ fprintf( out, "%f,", x[i] );
+ }
- fprintf(stdout, "%f]", x[i]);
+ fprintf( out, "%f]", x[n - 1] );
}
-void ts_pretty_print( fp_t const * const *x, uint_t m, uint_t n )
+void ts_pretty_print( fp_t const * const *x, uint_t m, uint_t n, FILE *stream )
{
- if( m > 1 )
- {
- for( uint_t i = 0; i < n; i++ )
- {
- uint_t j = 0;
- for( ; j < m; j++ )
- {
- fprintf( stdout, "%f ", x[i][j] );
- }
+ if ( !x || m == 0 || n == 0 ) return;
- fputs( "\n", stdout );
- }
- }
- else
- {
- for( uint_t i = 0; i < n; i++ )
- {
- fprintf( stdout, "%f\n", x[0][i] );
- }
- }
+ FILE *out = stream ? stream : stdout;
+
+ if( m > 1 )
+ {
+ for( uint_t i = 0; i < n; i++ )
+ {
+ for( uint_t j = 0; j < m; j++ )
+ {
+ fprintf( out, "%f ", x[j][i] );
+ }
+
+ fputs( "\n", out );
+ }
+ }
+ else
+ {
+ for( uint_t i = 0; i < n; i++ )
+ {
+ fprintf( out, "%f\n", x[0][i] );
+ }
+ }
}
@@ -91,29 +98,19 @@ fp_t _ts_triangle_number( fp_t x )
fp_t _ts_sum_to_covariance( fp_t sum_xy, fp_t sum_x, fp_t sum_y, uint_t k )
{
+ if ( k == 0 ) return 0.0;
return ( sum_xy - ( sum_x * sum_y / k ) ) / k;
}
fp_t _ts_sum_to_variance( fp_t sum_x2, fp_t sum_x, uint_t k )
{
- return _ts_sum_to_covariance( sum_x2, sum_x, sum_x, k );
+ return fmax( 0.0, _ts_sum_to_covariance( sum_x2, sum_x, sum_x, k ) );
}
uint_t _ts_circle_increment( uint_t i, uint_t k )
{
+ if ( k == 0 ) return i;
return ( i + 1 ) % k;
-}
-
-
-// ts_constant_t * ts_constant_init( uint_t n, ... )
-// {
-// va_list args;
-// va_start( args, n );
-
-// for( uint_t i = 0; i < n; i++ )
-// {
-
-// }
-// } \ No newline at end of file
+} \ No newline at end of file
diff --git a/lib/ulcer_index.c b/lib/ulcer_index.c
index ca70734..1063880 100644
--- a/lib/ulcer_index.c
+++ b/lib/ulcer_index.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_ulcer_index_p = { .n_inputs = 1, .n_outputs = 1, .n_cons
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 );
+ return ( c ? ((ts_ulcer_index_params_t const *)c)->k > 0 ? ((ts_ulcer_index_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_ulcer_index(
@@ -35,8 +35,8 @@ int ts_ulcer_index(
{
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;
+ uint_t k = ((ts_ulcer_index_params_t const *)c)->k;
+ if (k == 0) return -1;
/* Precompute cumulative highest-high for each index: O(n) */
fp_t *cum_hhv = calloc( n, sizeof( fp_t ) );
@@ -50,13 +50,13 @@ int ts_ulcer_index(
}
}
- for( uint_t i = k - 1; i < n; ++i )
+ 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;
+ if ( v > hhv ) hhv = v;
}
fp_t d_sq_sum = 0;
diff --git a/lib/valuation_lines.c b/lib/valuation_lines.c
index b56a871..cba9b2e 100644
--- a/lib/valuation_lines.c
+++ b/lib/valuation_lines.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_valuation_lines_p = { .n_inputs = 4, .n_outputs = 2, .n_
uint_t ts_valuation_lines_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_valuation_lines_params_t *)c)->k > 0 ? ((ts_valuation_lines_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_valuation_lines_params_t const *)c)->k > 0 ? ((ts_valuation_lines_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_valuation_lines(
@@ -34,7 +34,7 @@ int ts_valuation_lines(
{
TS_PROLOGUE( ts_valuation_lines_p );
if ( !c ) return -1;
- uint_t k = ((ts_valuation_lines_params_t *)c)->k;
+ uint_t k = ((ts_valuation_lines_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k - 1; i < n; ++i )
diff --git a/lib/variable_index_dynamic_average.c b/lib/variable_index_dynamic_average.c
index 5f4ae4f..0e78d13 100644
--- a/lib/variable_index_dynamic_average.c
+++ b/lib/variable_index_dynamic_average.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_variable_index_dynamic_average_p = { .n_inputs = 1, .n_o
uint_t ts_variable_index_dynamic_average_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_variable_index_dynamic_average_params_t *)c)->period : 0 );
+ return ( c ? ((ts_variable_index_dynamic_average_params_t const *)c)->period : 0 );
}
int ts_variable_index_dynamic_average(
@@ -34,7 +34,7 @@ int ts_variable_index_dynamic_average(
{
TS_PROLOGUE( ts_variable_index_dynamic_average_p );
if ( !c ) return -1;
- uint_t period = ((ts_variable_index_dynamic_average_params_t *)c)->period;
+ uint_t period = ((ts_variable_index_dynamic_average_params_t const *)c)->period;
if (period < 2 || n <= period) return -1;
fp_t vidya = x[0][period];
diff --git a/lib/variance.c b/lib/variance.c
index f307198..e288233 100755
--- a/lib/variance.c
+++ b/lib/variance.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_variance_p = { .n_inputs = 1, .n_outputs = 1, .n_constan
uint_t ts_variance_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_variance_params_t *)c)->k > 0 ? ((ts_variance_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_variance_params_t const *)c)->k > 0 ? ((ts_variance_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_variance(
@@ -34,7 +34,7 @@ int ts_variance(
TS_PROLOGUE( ts_variance_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_variance_params_t *)c)->k;
+ uint_t k = ((ts_variance_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t xi = 0;
diff --git a/lib/variance_exponential.c b/lib/variance_exponential.c
index 338a140..0700aee 100755
--- a/lib/variance_exponential.c
+++ b/lib/variance_exponential.c
@@ -30,9 +30,8 @@ int ts_variance_exponential(
{
TS_PROLOGUE( ts_variance_exponential_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t a = ((ts_variance_exponential_params_t *)c)->a;
+ fp_t a = ((ts_variance_exponential_params_t const *)c)->a;
if (a == 0) return -1;
y[0][0] = 0;
diff --git a/lib/vertical_horizontal_filter.c b/lib/vertical_horizontal_filter.c
index f5c91cf..e032dbd 100644
--- a/lib/vertical_horizontal_filter.c
+++ b/lib/vertical_horizontal_filter.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_vertical_horizontal_filter_p = { .n_inputs = 4, .n_outpu
uint_t ts_vertical_horizontal_filter_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_vertical_horizontal_filter_params_t *)c)->k : 0 );
+ return ( c ? ((ts_vertical_horizontal_filter_params_t const *)c)->k : 0 );
}
int ts_vertical_horizontal_filter(
@@ -34,7 +34,7 @@ int ts_vertical_horizontal_filter(
{
TS_PROLOGUE( ts_vertical_horizontal_filter_p );
if ( !c ) return -1;
- uint_t k = ((ts_vertical_horizontal_filter_params_t *)c)->k;
+ uint_t k = ((ts_vertical_horizontal_filter_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t cum_den = 0;
diff --git a/lib/volatility_stop.c b/lib/volatility_stop.c
index bfb207b..6055144 100644
--- a/lib/volatility_stop.c
+++ b/lib/volatility_stop.c
@@ -24,7 +24,7 @@ ts_parameter_t const ts_volatility_stop_p = { .n_inputs = 4, .n_outputs = 2, .n_
uint_t ts_volatility_stop_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_volatility_stop_params_t *)c)->k : 0 );
+ return ( c ? ((ts_volatility_stop_params_t const *)c)->k : 0 );
}
int ts_volatility_stop(
@@ -35,9 +35,17 @@ int ts_volatility_stop(
{
TS_PROLOGUE( ts_volatility_stop_p );
if ( !c ) return -1;
- uint_t k = ((ts_volatility_stop_params_t *)c)->k;
- fp_t mult = ((ts_volatility_stop_params_t *)c)->mult;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_volatility_stop_params_t const *)c)->k;
+ fp_t mult = ((ts_volatility_stop_params_t const *)c)->mult;
if (k == 0 || n < k) return -1;
+ if (mult < 0 || isnan(mult) || isinf(mult)) return -1;
+
+ for( uint_t i = 0; i < k; ++i )
+ {
+ y[0][i] = NAN;
+ y[1][i] = NAN;
+ }
for( uint_t i = k; i < n; ++i )
{
diff --git a/lib/volatility_system.c b/lib/volatility_system.c
index dbb74d1..b8e0c33 100644
--- a/lib/volatility_system.c
+++ b/lib/volatility_system.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_volatility_system_p = { .n_inputs = 4, .n_outputs = 1, .
uint_t ts_volatility_system_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? 2 * ((ts_volatility_system_params_t *)c)->k : 0 );
+ return ( c ? 2 * ((ts_volatility_system_params_t const *)c)->k : 0 );
}
int ts_volatility_system(
@@ -34,12 +34,16 @@ int ts_volatility_system(
{
TS_PROLOGUE( ts_volatility_system_p );
if ( !c ) return -1;
- uint_t k = ((ts_volatility_system_params_t *)c)->k;
+ TS_CHECK_INPUT(x, x_n, n);
+ uint_t k = ((ts_volatility_system_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
uint_t range_period = 2 * k;
if (n < range_period) return -1;
+ for ( uint_t i = 0; i < range_period; ++i )
+ y[0][i] = NAN;
+
fp_t ema = (ts_c(x, range_period - 2) + ts_c(x, range_period - 1)) / 2.0;
for( uint_t i = range_period; i < n; ++i )
diff --git a/lib/volume_moving_average.c b/lib/volume_moving_average.c
index 93eb592..33f263c 100644
--- a/lib/volume_moving_average.c
+++ b/lib/volume_moving_average.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_volume_moving_average_p = { .n_inputs = 5, .n_outputs =
uint_t ts_volume_moving_average_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_volume_moving_average_params_t *)c)->k > 0 ? ((ts_volume_moving_average_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_volume_moving_average_params_t const *)c)->k > 0 ? ((ts_volume_moving_average_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_volume_moving_average(
@@ -33,7 +33,7 @@ int ts_volume_moving_average(
{
TS_PROLOGUE( ts_volume_moving_average_p );
if ( !c ) return -1;
- uint_t k = ((ts_volume_moving_average_params_t *)c)->k;
+ uint_t k = ((ts_volume_moving_average_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = k - 1; i < n; ++i)
diff --git a/lib/volume_oscillator.c b/lib/volume_oscillator.c
index 6aa59f0..37d34c4 100644
--- a/lib/volume_oscillator.c
+++ b/lib/volume_oscillator.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_volume_oscillator_p = { .n_inputs = 1, .n_outputs = 1, .
uint_t ts_volume_oscillator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_volume_oscillator_params_t *)c)->slow_k > 0 ? (uint_t)(((ts_volume_oscillator_params_t *)c)->slow_k - 1) : 0 : 0 );
+ return ( c ? ((ts_volume_oscillator_params_t const *)c)->slow_k > 0 ? (uint_t)(((ts_volume_oscillator_params_t const *)c)->slow_k - 1) : 0 : 0 );
}
int ts_volume_oscillator(
@@ -34,10 +34,9 @@ int ts_volume_oscillator(
{
TS_PROLOGUE( ts_volume_oscillator_p );
if ( !c ) return -1;
- fp_t fast_k = ((ts_volume_oscillator_params_t *)c)->fast_k;
- fp_t slow_k = ((ts_volume_oscillator_params_t *)c)->slow_k;
+ fp_t fast_k = ((ts_volume_oscillator_params_t const *)c)->fast_k;
+ fp_t slow_k = ((ts_volume_oscillator_params_t const *)c)->slow_k;
if (fast_k == 0 || slow_k == 0) return -1;
- if (n == 0) return -1;
fp_t fast_a = 2.0 / (fast_k + 1);
fp_t slow_a = 2.0 / (slow_k + 1);
diff --git a/lib/volume_rate_of_change.c b/lib/volume_rate_of_change.c
index ae9c776..b9d09c8 100644
--- a/lib/volume_rate_of_change.c
+++ b/lib/volume_rate_of_change.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_volume_rate_of_change_p = { .n_inputs = 5, .n_outputs =
uint_t ts_volume_rate_of_change_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_volume_rate_of_change_params_t *)c)->k : 0 );
+ return ( c ? ((ts_volume_rate_of_change_params_t const *)c)->k : 0 );
}
int ts_volume_rate_of_change(
@@ -34,7 +34,7 @@ int ts_volume_rate_of_change(
{
TS_PROLOGUE( ts_volume_rate_of_change_p );
if ( !c ) return -1;
- uint_t k = ((ts_volume_rate_of_change_params_t *)c)->k;
+ uint_t k = ((ts_volume_rate_of_change_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for (uint_t i = k; i < n; ++i)
diff --git a/lib/volume_weighted_moving_average.c b/lib/volume_weighted_moving_average.c
index d6cd6bd..a7dc781 100644
--- a/lib/volume_weighted_moving_average.c
+++ b/lib/volume_weighted_moving_average.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_volume_weighted_moving_average_p = { .n_inputs = 5, .n_o
uint_t ts_volume_weighted_moving_average_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_volume_weighted_moving_average_params_t *)c)->k > 0 ? ((ts_volume_weighted_moving_average_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_volume_weighted_moving_average_params_t const *)c)->k > 0 ? ((ts_volume_weighted_moving_average_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_volume_weighted_moving_average(
@@ -33,7 +33,7 @@ int ts_volume_weighted_moving_average(
{
TS_PROLOGUE( ts_volume_weighted_moving_average_p );
if ( !c ) return -1;
- uint_t k = ((ts_volume_weighted_moving_average_params_t *)c)->k;
+ uint_t k = ((ts_volume_weighted_moving_average_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
fp_t cv_sum = 0;
diff --git a/lib/vortex_indicator.c b/lib/vortex_indicator.c
index 39ecfbc..6e80974 100644
--- a/lib/vortex_indicator.c
+++ b/lib/vortex_indicator.c
@@ -23,7 +23,7 @@ ts_parameter_t const ts_vortex_indicator_p = { .n_inputs = 4, .n_outputs = 2, .n
uint_t ts_vortex_indicator_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_vortex_indicator_params_t *)c)->k : 0 );
+ return ( c ? ((ts_vortex_indicator_params_t const *)c)->k : 0 );
}
int ts_vortex_indicator(
@@ -34,7 +34,7 @@ int ts_vortex_indicator(
{
TS_PROLOGUE( ts_vortex_indicator_p );
if ( !c ) return -1;
- uint_t k = ((ts_vortex_indicator_params_t *)c)->k;
+ uint_t k = ((ts_vortex_indicator_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
for( uint_t i = k; i < n; ++i )
diff --git a/lib/vwap_period.c b/lib/vwap_period.c
index b8af2bd..58873ed 100644
--- a/lib/vwap_period.c
+++ b/lib/vwap_period.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_vwap_period_p = { .n_inputs = 5, .n_outputs = 1, .n_cons
uint_t ts_vwap_period_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_vwap_period_params_t *)c)->k > 0 ? ((ts_vwap_period_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_vwap_period_params_t const *)c)->k > 0 ? ((ts_vwap_period_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_vwap_period(
@@ -33,7 +33,7 @@ int ts_vwap_period(
{
TS_PROLOGUE( ts_vwap_period_p );
if ( !c ) return -1;
- uint_t k = ((ts_vwap_period_params_t *)c)->k;
+ uint_t k = ((ts_vwap_period_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
/* Periodic VWAP: reset cumulative sums every k bars */
diff --git a/lib/weibull_pdf.c b/lib/weibull_pdf.c
index 894c94a..ddfd77d 100644
--- a/lib/weibull_pdf.c
+++ b/lib/weibull_pdf.c
@@ -34,7 +34,7 @@ int ts_weibull_pdf(
{
TS_PROLOGUE( ts_weibull_pdf_p );
if ( !c ) return -1;
- fp_t k = ((ts_weibull_pdf_params_t *)c)->k;
+ fp_t k = ((ts_weibull_pdf_params_t const *)c)->k;
if (k <= 0.0 || isnan(k) || isinf(k)) return -1;
for( uint_t i = 0; i < n; ++i )
{
diff --git a/lib/wilders_smoothing.c b/lib/wilders_smoothing.c
index 7aca8ad..f6a48b2 100644
--- a/lib/wilders_smoothing.c
+++ b/lib/wilders_smoothing.c
@@ -33,9 +33,8 @@ int ts_wilders_smoothing(
{
TS_PROLOGUE( ts_wilders_smoothing_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t k = ((ts_wilders_smoothing_params_t *)c)->k;
+ fp_t k = ((ts_wilders_smoothing_params_t const *)c)->k;
if (k == 0) return -1;
fp_t a = 1.0 / k;
diff --git a/lib/williams_r.c b/lib/williams_r.c
index f0fae3f..f755284 100644
--- a/lib/williams_r.c
+++ b/lib/williams_r.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_williams_r_p = { .n_inputs = 4, .n_outputs = 1, .n_const
uint_t ts_williams_r_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_williams_r_params_t *)c)->k > 0 ? ((ts_williams_r_params_t *)c)->k - 1 : 0 : 0 );
+ return ( c ? ((ts_williams_r_params_t const *)c)->k > 0 ? ((ts_williams_r_params_t const *)c)->k - 1 : 0 : 0 );
}
int ts_williams_r(
@@ -34,7 +34,7 @@ int ts_williams_r(
TS_PROLOGUE( ts_williams_r_p );
if ( !c ) return -1;
TS_CHECK_INPUT(x, x_n, n);
- uint_t k = ((ts_williams_r_params_t *)c)->k;
+ uint_t k = ((ts_williams_r_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
// Initial window max/min
diff --git a/lib/zero_lag_ema.c b/lib/zero_lag_ema.c
index c78adbd..a2b27d9 100644
--- a/lib/zero_lag_ema.c
+++ b/lib/zero_lag_ema.c
@@ -22,7 +22,7 @@ ts_parameter_t const ts_zero_lag_ema_p = { .n_inputs = 1, .n_outputs = 1, .n_con
uint_t ts_zero_lag_ema_offset( ts_constant_t const *c )
{
( void )c;
- return ( c ? ((ts_zero_lag_ema_params_t *)c)->k : 0 );
+ return ( c ? ((ts_zero_lag_ema_params_t const *)c)->k : 0 );
}
int ts_zero_lag_ema(
@@ -33,7 +33,7 @@ int ts_zero_lag_ema(
{
TS_PROLOGUE( ts_zero_lag_ema_p );
if ( !c ) return -1;
- uint_t k = ((ts_zero_lag_ema_params_t *)c)->k;
+ uint_t k = ((ts_zero_lag_ema_params_t const *)c)->k;
if (k == 0 || n < k) return -1;
/* Zero-lag EMA: compute lag, then apply EMA to (2*x - x_lag) */
diff --git a/lib/zigzag.c b/lib/zigzag.c
index 50549e2..db4a5f2 100644
--- a/lib/zigzag.c
+++ b/lib/zigzag.c
@@ -35,9 +35,8 @@ int ts_zigzag(
{
TS_PROLOGUE( ts_zigzag_p );
if ( !c ) return -1;
- if (n == 0) return -1;
- fp_t threshold = ((ts_zigzag_params_t *)c)->threshold;
+ fp_t threshold = ((ts_zigzag_params_t const *)c)->threshold;
if (threshold <= 0 || isnan(threshold) || isinf(threshold)) return -1;
y[0][0] = x[0][0];
diff --git a/main.c b/main.c
index 4308e55..473e556 100755
--- a/main.c
+++ b/main.c
@@ -41,17 +41,8 @@ int main(int argc, char *argv[]) {
}
period = (uint_t)val;
}
- if (period == 0 || period > BUFFER_SIZE) {
- fprintf(stderr, "Error: period must be between 1 and %d\n", BUFFER_SIZE);
- usage(argv[0]);
- return 1;
- }
-
fp_t input[BUFFER_SIZE];
fp_t output[BUFFER_SIZE];
- for (int_t i = 0; i < (int_t)BUFFER_SIZE; i++) {
- output[i] = 0;
- }
if (!ts_fill(input, BUFFER_SIZE, 0, (fp_t)BUFFER_SIZE)) {
fprintf(stderr, "ts_fill failed\n");
@@ -63,19 +54,15 @@ int main(int argc, char *argv[]) {
ts_constant_t c;
memset(&c, 0, sizeof(c));
- *(uint_t *)c.data = period;
+ memcpy(c.data, &period, sizeof(period));
int ret = ts_average(y, 1, x, 1, BUFFER_SIZE, &c);
if (ret == -1) {
fprintf(stderr, "ts_average failed\n");
return 1;
}
- /* Validate output: first valid value is at index period-1 */
+ /* First valid SMA value is at index period-1 */
uint_t offset = period - 1;
- if (offset >= BUFFER_SIZE) {
- fprintf(stderr, "error: period exceeds buffer size\n");
- return 1;
- }
/* Clamp display range to valid output */
uint_t display_end = DISPLAY_N < BUFFER_SIZE ? DISPLAY_N : BUFFER_SIZE;
@@ -85,7 +72,7 @@ int main(int argc, char *argv[]) {
}
for (uint_t i = offset; i < display_end; i++) {
- printf("input[%" TS_PRIuint "] = %f SMA[%" TS_PRIuint "] = %f\n", i, input[i], i, output[i]);
+ printf("input[%" TS_PRIuint "] = %" TS_PRIfp " SMA[%" TS_PRIuint "] = %" TS_PRIfp "\n", i, input[i], i, output[i]);
}
return 0;
diff --git a/scripts/gen_bindings.py b/scripts/gen_bindings.py
index 845c8a5..f7c0486 100644
--- a/scripts/gen_bindings.py
+++ b/scripts/gen_bindings.py
@@ -36,6 +36,7 @@ MIN_PARAM_DEFAULTS = {
"choppiness_index": {"k": 2},
"performance_ratio": {"k": 2},
"standard_error": {"k": 2},
+ "mesa_sine_wave": {"k": 2},
}
@@ -64,6 +65,7 @@ def main():
f.write("import ctypes\n")
f.write("import ctypes.util\n")
f.write("import os\n")
+ f.write("import subprocess\n")
f.write("import numpy as np\n")
f.write("import threading\n\n")
@@ -81,11 +83,14 @@ def main():
f.write(" libdir = subprocess.check_output(\n")
f.write(' ["pkg-config", "--variable=libdir", "ts"],\n')
f.write(" stderr=subprocess.DEVNULL,\n")
+ f.write(" timeout=10,\n")
f.write(" ).decode().strip()\n")
f.write(
' return ctypes.CDLL(os.path.join(libdir, "libts.so"), ctypes.RTLD_GLOBAL)\n'
)
- f.write(" except (OSError, subprocess.CalledProcessError):\n")
+ f.write(
+ " except (OSError, subprocess.CalledProcessError, subprocess.TimeoutExpired):\n"
+ )
f.write(" pass\n")
f.write(" build_dir = os.path.join(\n")
f.write(
@@ -100,7 +105,11 @@ def main():
' raise OSError("Cannot find libts.so. Run make install or build from source.")\n\n\n'
)
- f.write("__version__ = '0.1.0'\n\n")
+ f.write("try:\n")
+ f.write(" from importlib.metadata import version as _version\n")
+ f.write(" __version__ = _version(__name__)\n")
+ f.write("except Exception:\n")
+ f.write(" __version__ = '0.1.0'\n\n")
f.write("_lib = _find_lib()\n\n")
# --- Helpers ---
@@ -108,7 +117,11 @@ def main():
f.write("def _cp(arr):\n")
f.write(' """Copy numpy array to ctypes buffer (tracked in TLS list)."""\n')
- f.write(" buf = (_CD * len(arr))(*arr)\n")
+ f.write(" if len(arr) == 0:\n")
+ f.write(" buf = (_CD * 1)()\n")
+ f.write(" buf[0] = 0.0\n")
+ f.write(" else:\n")
+ f.write(" buf = (_CD * len(arr))(*arr)\n")
f.write(" if not hasattr(_tls, 'bufs'):\n")
f.write(" _tls.bufs = []\n")
f.write(" _tls.bufs.append(buf)\n")
@@ -119,7 +132,7 @@ def main():
f.write(" try:\n")
f.write(" if hasattr(_tls, 'bufs'):\n")
f.write(" _tls.bufs.clear()\n")
- f.write(" except Exception:\n")
+ f.write(" except AttributeError:\n")
f.write(" pass\n\n\n")
# --- Parameter structs ---
diff --git a/scripts/gen_registry.py b/scripts/gen_registry.py
index e80759e..dbe6f04 100644
--- a/scripts/gen_registry.py
+++ b/scripts/gen_registry.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
"""Generate ts_registry_generated.c with registry array and getter functions."""
+import glob
import importlib.util
import os
import re
@@ -39,9 +40,9 @@ def _resolve_params_size(params_size, name):
return params_size
except FileNotFoundError:
pass
- # Struct not in header, compute size from definition
- import glob
-
+ # Struct not in header, compute size from definition.
+ # Both fp_t (double) and uint_t (uint64_t) are 8 bytes on 64-bit.
+ # This is a fallback; sizeof() in the generated C code is preferred.
lib_dir = os.path.join(ROOT, "lib")
for cfile in glob.glob(os.path.join(lib_dir, "*.c")):
try:
@@ -57,7 +58,11 @@ def _resolve_params_size(params_size, name):
body = struct_m.group(1)
n_fp = len(re.findall(r"fp_t\s+", body))
n_uint = len(re.findall(r"uint_t\s+", body))
- return str(n_fp * 8 + n_uint * 8)
+ n_total = n_fp + n_uint
+ if n_total == 0:
+ return "0"
+ # Assume 8-byte alignment (valid for fp_t=double, uint_t=uint64_t)
+ return str(n_total * 8)
return "0"
diff --git a/scripts/ts_parser.py b/scripts/ts_parser.py
index 2ad3629..31d926d 100644
--- a/scripts/ts_parser.py
+++ b/scripts/ts_parser.py
@@ -41,6 +41,19 @@ class FuncMeta:
self.struct_fields = struct_fields or []
+def _strip_strings_comments(text):
+ """Remove C string literals and comments to avoid false brace matches."""
+ # Remove block comments
+ text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL)
+ # Remove line comments
+ text = re.sub(r"//.*", "", text)
+ # Remove string literals
+ text = re.sub(r'"(?:[^"\\]|\\.)*"', '""', text)
+ # Remove character literals
+ text = re.sub(r"'(?:[^'\\]|\\.)*'", "''", text)
+ return text
+
+
def _detect_actual_x_n(content, match_end, name):
"""Detect actual x[N] access in function body."""
remaining = content[match_end:]
@@ -48,18 +61,21 @@ def _detect_actual_x_n(content, match_end, name):
if not func_def:
return 0
brace_pos = remaining.find("{", func_def.start())
+ # Strip strings and comments for safe brace matching
+ cleaned = _strip_strings_comments(remaining[brace_pos:])
depth = 0
- func_body = ""
- for i in range(brace_pos, len(remaining)):
- if remaining[i] == "{":
+ end_pos = 0
+ for i, ch in enumerate(cleaned):
+ if ch == "{":
depth += 1
- elif remaining[i] == "}":
+ elif ch == "}":
depth -= 1
if depth == 0:
- func_body = remaining[brace_pos : i + 1]
+ end_pos = i
break
+ func_body = remaining[brace_pos : brace_pos + end_pos + 1] if end_pos else ""
indices = [
- int(xm.group(1)) for xm in re.finditer(r"x\s*\[\s*(\d+)\s*\]", func_body)
+ int(xm.group(1)) for xm in re.finditer(r"\bx\s*\[\s*(\d+)\s*\]", func_body)
]
return max(indices) + 1 if indices else 0
@@ -133,11 +149,6 @@ def parse_all(detect_x_access=True):
actual = _detect_actual_x_n(content, m.end(), name)
if actual > x_n:
x_n = actual
- if x_n < OHLCV_COUNT and re.search(
- r"\bx\s*\[\s*" + str(VOLUME_INDEX) + r"\s*\]",
- content[m.end() :],
- ):
- x_n = OHLCV_COUNT
struct_fields = _parse_struct_fields(content, name) if c_n > 0 else []
@@ -153,7 +164,7 @@ def parse_names_only():
Dict mapping name -> {"x_n": int, "y_n": int}.
"""
meta = {}
- for fm in parse_all(detect_x_access=True):
+ for fm in parse_all(detect_x_access=False):
if fm.name not in meta:
meta[fm.name] = {"x_n": fm.x_n, "y_n": fm.y_n}
return meta
diff --git a/test/adx.c b/test/adx.c
index e8df67e..aac452d 100644
--- a/test/adx.c
+++ b/test/adx.c
@@ -13,6 +13,11 @@ bool ts_test_adx( void )
x[1] = malloc( n * sizeof( fp_t ) );
x[2] = malloc( n * sizeof( fp_t ) );
x[3] = malloc( n * sizeof( fp_t ) );
+ if ( !x[0 ] || !x[1] || !x[2] || !x[3] )
+ {
+ free( x[0] ); free( x[1] ); free( x[2] ); free( x[3] );
+ return false;
+ }
for ( uint_t i = 0; i < n; ++i )
{
@@ -36,7 +41,16 @@ bool ts_test_adx( void )
* indices [offset..n-1], not compacted [0..y_n-1] */
fp_t *y[4];
for ( uint_t i = 0; i < 4; ++i )
+ {
y[i] = calloc( n, sizeof( fp_t ) );
+ if ( !y[i] )
+ {
+ for ( uint_t j = 0; j < i; ++j )
+ free( y[j] );
+ free( x[0] ); free( x[1] ); free( x[2] ); free( x[3] );
+ return false;
+ }
+ }
uint8_t c[TS_CONSTANT_SIZE] = { 0 };
*( uint_t * )c = k;
diff --git a/test/awesome_oscillator.c b/test/awesome_oscillator.c
index 205bf78..08947c2 100644
--- a/test/awesome_oscillator.c
+++ b/test/awesome_oscillator.c
@@ -26,6 +26,11 @@ bool ts_test_awesome_oscillator( void )
}
fp_t *result = calloc( n, sizeof( fp_t ) );
+ if ( !result )
+ {
+ free( o ); free( h ); free( l ); free( c );
+ return false;
+ }
ts_awesome_oscillator(&result, 1, (fp_t const * const []){ o, h, l, c }, 4, n, NULL);
diff --git a/test/bench.c b/test/bench.c
index 83330aa..19023d4 100644
--- a/test/bench.c
+++ b/test/bench.c
@@ -1,3 +1,4 @@
+#define _POSIX_C_SOURCE 200809L
#define TS_IMPLEMENTATION
#include "ts.h"
#include <stdio.h>
diff --git a/test/bollinger_bands.c b/test/bollinger_bands.c
index 37bc138..153b8a7 100644
--- a/test/bollinger_bands.c
+++ b/test/bollinger_bands.c
@@ -14,7 +14,7 @@ bool ts_test_bollinger_bands( void )
fp_t const em[] = { 11, 12, 13, 14, 15, 16, 17, 18 };
fp_t const eu[] = { 12.632993, 13.632993, 14.632993, 15.632993, 16.632993, 17.632993, 18.632993, 19.632993 };
fp_t const el[] = { 9.367007, 10.367007, 11.367007, 12.367007, 13.367007, 14.367007, 15.367007, 16.367007 };
- fp_t const * const exp[3] = { em, eu, el };
+ fp_t const * const exp[3] = { eu, em, el };
typedef struct { uint_t k; fp_t std_mult; } c_t;
c_t c = { .k = 3, .std_mult = 2.0 };
diff --git a/test/cv.c b/test/cv.c
index 2c41604..45cf635 100644
--- a/test/cv.c
+++ b/test/cv.c
@@ -7,9 +7,8 @@ bool ts_test_cv( void )
fp_t const h[] = { 12, 13, 14, 12, 14, 15, 16, 14, 16, 17, 16 };
fp_t const l[] = { 8, 9, 10, 9, 10, 11, 12, 11, 12, 13, 12 };
fp_t const c[] = { 11, 12, 10, 11, 11, 14, 15, 13, 15, 16, 15 };
- fp_t const v[] = { 100, 200, 300, 400, 500, 150, 250, 350, 450, 550, 650 };
- fp_t const * const x[] = { o, h, l, c, v };
+ fp_t const * const x[] = { o, h, l, c };
fp_t fast = 3;
fp_t slow = 5;
diff --git a/test/edge_cases.c b/test/edge_cases.c
index ce47f72..46c19d4 100644
--- a/test/edge_cases.c
+++ b/test/edge_cases.c
@@ -1,3 +1,4 @@
+#define _POSIX_C_SOURCE 200809L
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
diff --git a/test/fuzz.c b/test/fuzz.c
index 3f11d9d..49964b1 100644
--- a/test/fuzz.c
+++ b/test/fuzz.c
@@ -1,3 +1,4 @@
+#define _POSIX_C_SOURCE 200809L
#include "ts.h"
#include <stdint.h>
#include <stdlib.h>
@@ -62,7 +63,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
if (xn > 5) xn = 5;
if (yn > 3) yn = 3;
- (void)entry.func(y_arrays, yn, (fp_t const * const *)x_arrays, xn, n, (ts_constant_t *)&period);
+ ts_constant_t c;
+ memset(&c, 0, sizeof(c));
+ memcpy(c.data, &period, sizeof(period));
+ (void)entry.func(y_arrays, yn, (fp_t const * const *)x_arrays, xn, n, &c);
return 0;
}
diff --git a/test/gen_test_data.c b/test/gen_test_data.c
index 6ef54af..30bb7ff 100644
--- a/test/gen_test_data.c
+++ b/test/gen_test_data.c
@@ -1,6 +1,7 @@
/* gen_test_data.c - Validate all ts functions run without error.
* Note: excluded from default build. Fix and add target to use.
*/
+#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -41,7 +42,11 @@ int main(void) {
size_t nsamples = sizeof(samples) / sizeof(samples[0]);
for (size_t fi = 0; fi < nsamples; fi++) {
- typeof(samples[fi]) f = samples[fi];
+ struct {
+ const char *name;
+ int (*func)(fp_t * const y[], fp_t const * const x[], uint_t, ts_constant_t const *);
+ uint_t x_n, y_n;
+ } f = samples[fi];
/* Allocate input arrays */
fp_t **x = calloc(f.x_n, sizeof(fp_t *));
diff --git a/test/hurst_exponent.c b/test/hurst_exponent.c
index ccf54c8..a200de9 100644
--- a/test/hurst_exponent.c
+++ b/test/hurst_exponent.c
@@ -1,3 +1,4 @@
+#include <math.h>
#include <stddef.h>
#include "ts.h"
@@ -6,6 +7,17 @@ bool ts_test_hurst_exponent( void )
uint_t const c[] = { 5 };
fp_t const x0[] = { 1,2,3,4,5,6,7,8,9,10 };
fp_t e0[10];
- ts_hurst_exponent((fp_t*[]){e0}, 1, (fp_t const *[]){x0}, 1, 10, (ts_constant_t *)&c);
+ int ret = ts_hurst_exponent((fp_t*[]){e0}, 1, (fp_t const *[]){x0}, 1, 10, (ts_constant_t *)&c);
+ if ( ret != 0 )
+ return false;
+
+ /* Verify output is finite (no NaN/Inf for valid input) */
+ for ( uint_t i = 0; i < 10; ++i )
+ {
+ fp_t v = e0[i];
+ if ( v != v ) return false;
+ if ( v == (fp_t)INFINITY || v == (fp_t)-INFINITY ) return false;
+ }
+
return true;
}
diff --git a/test/main.c b/test/main.c
index 2854d1c..0e14d44 100644
--- a/test/main.c
+++ b/test/main.c
@@ -42,7 +42,9 @@ int main(void)
if (result < 0) {
if (errno == EINTR) {
kill(pid, SIGKILL);
- waitpid(pid, &status, 0);
+ if (waitpid(pid, &status, 0) < 0) {
+ fprintf(stderr, " CRASH %s (waitpid after SIGKILL failed: %s)\n", tests[i].name, strerror(errno));
+ }
fprintf(stderr, " CRASH %s (timeout)\n", tests[i].name);
crashed++;
} else {
diff --git a/test/nextafter.c b/test/nextafter.c
index c7e882b..eaa1f21 100644
--- a/test/nextafter.c
+++ b/test/nextafter.c
@@ -3,9 +3,9 @@
bool ts_test_nextafter( void )
{
- fp_t const x0[] = { 1.000000, 1.000000, 0.000000 };
- fp_t const x1[] = { 2.000000, 0.000000, 1.000000 };
- fp_t const e0[] = { 1.000000, 1.000000, 0.000000 };
+ fp_t const x0[] = { 1.000000, 2.000000, 10.000000 };
+ fp_t const x1[] = { 2.000000, 1.000000, 20.000000 };
+ fp_t const e0[] = { 1.0000000000000002, 1.9999999999999998, 10.000000000000002 };
fp_t const * const x[2] = { x0, x1 };
fp_t const * const e[1] = { e0 };
diff --git a/test/nexttoward.c b/test/nexttoward.c
index 32d41cc..97935d7 100644
--- a/test/nexttoward.c
+++ b/test/nexttoward.c
@@ -3,9 +3,9 @@
bool ts_test_nexttoward( void )
{
- fp_t const x0[] = { 1.000000, 1.000000, 0.000000 };
- fp_t const x1[] = { 2.000000, 0.000000, 1.000000 };
- fp_t const e0[] = { 1.000000, 1.000000, 0.000000 };
+fp_t const x0[] = { 1.000000, 2.000000, 10.000000 };
+ fp_t const x1[] = { 2.000000, 1.000000, 20.000000 };
+ fp_t const e0[] = { 1.0000000000000002, 1.9999999999999998, 10.000000000000002 };
fp_t const * const x[2] = { x0, x1 };
fp_t const * const e[1] = { e0 };
diff --git a/test/nvi.c b/test/nvi.c
index 87b3ddb..8a8f300 100644
--- a/test/nvi.c
+++ b/test/nvi.c
@@ -12,8 +12,6 @@ bool ts_test_nvi( void )
fp_t const * const x[] = { o, h, l, c, v };
fp_t nvi = 1000;
-
- nvi = 1000;
fp_t e[5] = { nvi };
e[1] = nvi;
diff --git a/test/test_python.py b/test/test_python.py
index a4aa7e2..cfa983b 100644
--- a/test/test_python.py
+++ b/test/test_python.py
@@ -429,16 +429,21 @@ def parse_test_file(test_path):
params = resolved
if params is None:
- scalar_match = re.search(
+ # Extract ALL scalar variables (not just the first)
+ scalar_matches = re.finditer(
r"(?:uint_t|fp_t|int)\s+(?:const\s+)?(\w+)\s*=\s*([^;]+);", content
)
- if scalar_match:
- var_name = scalar_match.group(1)
- if var_name not in ("n", "offset", "y_n", "i", "j"):
- val_text = scalar_match.group(2).strip()
- result = _safe_float(val_text)
- if result is not None:
- params = {var_name: result}
+ collected = {}
+ for sm in scalar_matches:
+ var_name = sm.group(1)
+ if var_name in ("n", "offset", "y_n", "i", "j"):
+ continue
+ val_text = sm.group(2).strip()
+ result = _safe_float(val_text)
+ if result is not None:
+ collected[var_name] = result
+ if collected:
+ params = collected
return {
"inputs": inputs,
@@ -565,12 +570,6 @@ def _run_tests():
if not parsed:
# Fallback: random inputs + default params from binding signature
rng.seed(SEED)
- rng.jumpahead(rng_offsets.get(fname, 0)) if hasattr(
- rng, "jumpahead"
- ) else None
- for _ in range(x_n * N):
- rng.uniform(0, 100)
- rng.seed(SEED)
if hasattr(rng, "jumpahead"):
rng.jumpahead(rng_offsets.get(fname, 0))
inputs = [[rng.uniform(0, 100) for _ in range(N)] for _ in range(x_n)]
@@ -595,7 +594,7 @@ def _run_tests():
py_params = binding_params
else:
c_params = params
- py_params = None
+ py_params = params
# Call Python binding
func = getattr(ts, fname, None)
@@ -620,16 +619,21 @@ def _run_tests():
else:
py_result = func(*np_inputs)
py_result = normalize_result(py_result, y_n, n)
- except Exception as e:
- err_msg = str(e)
- if (
- re.search(r"ts_\w+\s+error", err_msg)
- and not binding_params
- and c_params
- ):
- skipped += 1
- print(f" SKIP {fname} (binding missing params, C needs them)")
+ except TypeError as e:
+ # Param name mismatch: retry with no params (binding defaults)
+ if py_params:
+ try:
+ py_result = func(*np_inputs)
+ py_result = normalize_result(py_result, y_n, n)
+ except Exception as e2:
+ failed += 1
+ print(f" FAIL {fname}: {e2}")
+ continue
+ else:
+ failed += 1
+ print(f" FAIL {fname}: {e}")
continue
+ except Exception as e:
failed += 1
print(f" FAIL {fname}: {e}")
continue
diff --git a/ts.c b/ts.c
index a85bf0a..ad6081c 100644
--- a/ts.c
+++ b/ts.c
@@ -14,7 +14,7 @@
* Uses a running accumulator to avoid floating-point drift,
* and forces the last element to exactly x1.
*/
-fp_t* ts_fill(fp_t *x, uint_t n, fp_t x0, fp_t x1 )
+fp_t * ts_fill( fp_t *x, uint_t n, fp_t x0, fp_t x1 )
{
if( !x || n == 0 ) return NULL;
if( n == 1 )
@@ -52,7 +52,6 @@ fp_t* ts_fill(fp_t *x, uint_t n, fp_t x0, fp_t x1 )
*/
void ts_print( fp_t const *x, uint_t n, FILE *stream )
{
- assert( x != NULL );
if( !stream ) stream = stdout;
fputc( '[', stream );
if( !x || n == 0 )
@@ -61,13 +60,12 @@ void ts_print( fp_t const *x, uint_t n, FILE *stream )
return;
}
- uint_t i;
- for( i = 0; i < n - 1; i++ )
+ for( uint_t i = 0; i < n - 1; i++ )
{
fprintf( stream, "%.17g,", x[i] );
}
- fprintf( stream, "%.17g]", x[i] );
+ fprintf( stream, "%.17g]", x[n - 1] );
}
@@ -141,16 +139,15 @@ fp_t _ts_sum_to_covariance( fp_t sum_xy, fp_t sum_x, fp_t sum_y, uint_t k )
{
if( k == 0 )
return 0.0;
- fp_t result = ( sum_xy - ( sum_x * sum_y / k ) ) / k;
- if( result < 0.0 )
- result = 0.0;
- return result;
+ return ( sum_xy - ( sum_x * sum_y / k ) ) / k;
}
fp_t _ts_sum_to_variance( fp_t sum_x2, fp_t sum_x, uint_t k )
{
- return _ts_sum_to_covariance( sum_x2, sum_x, sum_x, k );
+ /* Variance must be non-negative. Clamp to zero to handle
+ * catastrophic cancellation in the naive summation formula. */
+ return fmax( 0.0, _ts_sum_to_covariance( sum_x2, sum_x, sum_x, k ) );
}
@@ -165,7 +162,7 @@ uint_t _ts_circle_increment( uint_t i, uint_t k )
/**
* Allocate and zero-initialize a ts_constant_t structure.
*/
-ts_constant_t* ts_constant( void )
+ts_constant_t * ts_constant( void )
{
return calloc( 1, sizeof( ts_constant_t ) );
}
@@ -202,17 +199,23 @@ bool ts_test(
ts_constant_t const *c,
ts_parameter_t const *m )
{
- if ( !ts_function || !ts_offset )
+ if( !ts_function || !ts_offset )
return false;
if( !m ) return false;
if( !e ) return false;
if( !x ) return false;
if( m->n_constants > 0 && !c ) return false;
- if( m->n_outputs > 1024 ) return false;
+ if( m->n_outputs > TS_MAX_LENGTH ) return false;
+
+ if( n > SIZE_MAX / sizeof( fp_t ) )
+ return false;
+
+ if( m->n_outputs > SIZE_MAX / sizeof( fp_t * ) )
+ return false;
uint_t offset = ts_offset( c );
- if ( offset >= n )
+ if( offset >= n )
{
return false;
}
@@ -225,11 +228,6 @@ bool ts_test(
return false;
}
- if ( n > UINT64_MAX / sizeof( fp_t ) )
- {
- return false;
- }
-
for( uint_t i = 0; i < m->n_outputs; i++ )
{
fp_t *tmp = calloc( n, sizeof( fp_t ) );
@@ -260,7 +258,7 @@ bool ts_test(
fp_t ev = e[i][j];
if( isnan( yv ) || isnan( ev ) )
{
- fprintf( stderr, "FAIL NaN y[%d][%d]=%f exp=%f\n", (int)i, (int)j, yv, ev );
+ fprintf( stderr, "FAIL NaN y[%" TS_PRIuint "][%" TS_PRIuint "]=%" TS_PRIfp " exp=%" TS_PRIfp "\n", i, j, yv, ev );
result = false;
continue;
}
@@ -269,7 +267,7 @@ bool ts_test(
continue;
if( isinf( yv ) || isinf( ev ) )
{
- fprintf( stderr, "FAIL inf y[%d][%d]=%f exp=%f\n", (int)i, (int)j, yv, ev );
+ fprintf( stderr, "FAIL inf y[%" TS_PRIuint "][%" TS_PRIuint "]=%" TS_PRIfp " exp=%" TS_PRIfp "\n", i, j, yv, ev );
result = false;
continue;
}
@@ -277,9 +275,10 @@ bool ts_test(
fp_t abs_e = fabs( ev );
fp_t tol = TS_TEST_EPSILON + abs_e * TS_TEST_EPSILON;
if( diff > tol )
- fprintf( stderr, "FAIL y[%d][%d]=%.6f exp=%.6f diff=%.8f tol=%.8f\n", (int)i, (int)j, yv, ev, diff, tol );
- if( diff > tol )
+ {
+ fprintf( stderr, "FAIL y[%" TS_PRIuint "][%" TS_PRIuint "]=%.6f exp=%.6f diff=%.8f tol=%.8f\n", i, j, yv, ev, diff, tol );
result = false;
+ }
}
free( y[i] );
diff --git a/ts.h b/ts.h
index fdb522e..43761ea 100644
--- a/ts.h
+++ b/ts.h
@@ -232,8 +232,7 @@ static inline int_t _ts_read_int_t( const uint8_t *p )
/*
* ts_fill — Linearly fill array x with values from x0 to x1.
- * RETURNS: the same pointer x (for convenience). Caller retains ownership.
- * PRECONDITION: x must not be NULL; n > 0.
+ * RETURNS: x on success, NULL if x is NULL or n == 0. Caller retains ownership.
*/
fp_t * ts_fill( fp_t *x, uint_t n, fp_t x0, fp_t x1 );
@@ -278,44 +277,50 @@ fp_t _ts_sum_to_variance( fp_t, fp_t, uint_t );
* PRECONDITION: pointer w must not be NULL for all ts_welford_* functions.
*/
typedef struct {
- fp_t mean;
- fp_t m2;
- uint_t count;
+ fp_t mean;
+ fp_t m2;
+ uint_t count;
} ts_welford_t;
static inline void ts_welford_init( ts_welford_t *w )
{
- if (!w) return;
- w->mean = 0; w->m2 = 0; w->count = 0;
+ if ( !w ) return;
+ w->mean = 0; w->m2 = 0; w->count = 0;
}
static inline void ts_welford_add( ts_welford_t *w, fp_t x )
{
- if (!w) return;
- w->count++;
- fp_t delta = x - w->mean;
- w->mean += delta / w->count;
- fp_t delta2 = x - w->mean;
- w->m2 += delta * delta2;
+ if ( !w ) return;
+ w->count++;
+ fp_t delta = x - w->mean;
+ w->mean += delta / w->count;
+ fp_t delta2 = x - w->mean;
+ w->m2 += delta * delta2;
}
static inline void ts_welford_remove( ts_welford_t *w, fp_t x )
{
- if (!w) return;
- if (w->count <= 1) { ts_welford_init(w); return; }
- fp_t old_mean = w->mean;
- w->count--;
- w->mean = (old_mean * (w->count + 1) - x) / w->count;
- fp_t delta = x - old_mean;
- fp_t delta2 = x - w->mean;
- w->m2 -= delta * delta2;
- if (w->m2 < 0) w->m2 = 0;
+ if ( !w ) return;
+ if ( w->count <= 1 ) { ts_welford_init( w ); return; }
+ fp_t old_mean = w->mean;
+ w->count--;
+ w->mean = old_mean + ( old_mean - x ) / w->count;
+ fp_t delta = x - old_mean;
+ fp_t delta2 = x - w->mean;
+ w->m2 -= delta * delta2;
+ w->m2 = fmax( 0.0, w->m2 );
}
static inline fp_t ts_welford_variance( ts_welford_t *w )
{
- if (!w) return 0;
- return w->count > 0 ? w->m2 / w->count : 0;
+ if ( !w ) return 0;
+ return w->count > 0 ? w->m2 / w->count : 0;
+}
+
+static inline fp_t ts_welford_sample_variance( ts_welford_t *w )
+{
+ if ( !w ) return 0;
+ return w->count > 1 ? w->m2 / ( w->count - 1 ) : 0;
}