summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorEthan Werner <mail@ethanwerner.com>2026-07-01 09:42:39 +0400
committerEthan Werner <mail@ethanwerner.com>2026-07-01 09:42:39 +0400
commit07e18043145f3d91c8ea7ec3ad41b3c905585277 (patch)
tree2bdeae46973f4bdfce263679a4008ac768011f28 /main.c
initial commit: ts time series analysis library v0.1.0
- 354 financial and mathematical time-series indicators - Uniform C11 API with consistent function signatures - 349 passing tests with -Werror - Static and shared library builds - pkg-config integration - Python bindings - Fuzzing and sanitizer support - Security hardening flags
Diffstat (limited to 'main.c')
-rwxr-xr-xmain.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100755
index 0000000..4308e55
--- /dev/null
+++ b/main.c
@@ -0,0 +1,92 @@
+// main.c - Moving average calculator using ts library
+// Computes a simple moving average over configurable period and displays results.
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TS_IMPLEMENTATION
+#include "ts.h"
+
+#define BUFFER_SIZE 100
+#define DISPLAY_N 20
+
+static void usage(const char *prog)
+{
+ fprintf(stderr, "Usage: %s [period]\n", prog);
+ fprintf(stderr, " period: moving average window (1-%d, default: 10)\n", BUFFER_SIZE);
+}
+
+int main(int argc, char *argv[]) {
+ uint_t period = 10;
+ if (argc > 1 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
+ usage(argv[0]);
+ return 0;
+ }
+ if (argc > 1) {
+ char *endptr = NULL;
+ errno = 0;
+ long val = strtol(argv[1], &endptr, 10);
+ if (endptr == argv[1] || *endptr != '\0' || errno == ERANGE) {
+ fprintf(stderr, "Error: invalid period '%s'\n", argv[1]);
+ usage(argv[0]);
+ return 1;
+ }
+ if (val < 1 || val > BUFFER_SIZE) {
+ fprintf(stderr, "Error: period must be between 1 and %d\n", BUFFER_SIZE);
+ usage(argv[0]);
+ return 1;
+ }
+ 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");
+ return 1;
+ }
+
+ fp_t * const y[1] = { output };
+ fp_t const * const x[1] = { input };
+
+ ts_constant_t c;
+ memset(&c, 0, sizeof(c));
+ *(uint_t *)c.data = 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 */
+ 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;
+ if (offset >= display_end) {
+ fprintf(stderr, "warning: period (%" TS_PRIuint ") >= display count (%" TS_PRIuint "), showing available data\n", period, display_end);
+ display_end = BUFFER_SIZE;
+ }
+
+ 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]);
+ }
+
+ return 0;
+}