diff options
| author | Ethan Werner <mail@ethanwerner.com> | 2026-07-01 09:42:39 +0400 |
|---|---|---|
| committer | Ethan Werner <mail@ethanwerner.com> | 2026-07-01 09:42:39 +0400 |
| commit | 07e18043145f3d91c8ea7ec3ad41b3c905585277 (patch) | |
| tree | 2bdeae46973f4bdfce263679a4008ac768011f28 /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-x | main.c | 92 |
1 files changed, 92 insertions, 0 deletions
@@ -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; +} |