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 /scripts/gen_flat.py | |
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 'scripts/gen_flat.py')
| -rw-r--r-- | scripts/gen_flat.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/scripts/gen_flat.py b/scripts/gen_flat.py new file mode 100644 index 0000000..c659432 --- /dev/null +++ b/scripts/gen_flat.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Generate flat-array C wrappers for all ts functions. + +Each wrapper takes flat input/output arrays instead of pointer-of-pointers, +eliminating ctypes pointer marshaling overhead. +""" + +import argparse +import importlib.util +import os +import sys + +_spec = importlib.util.spec_from_file_location( + "ts_parser", + os.path.join(os.path.dirname(os.path.abspath(__file__)), "ts_parser.py"), +) +if _spec and _spec.loader: + _ts_parser = importlib.util.module_from_spec(_spec) + _spec.loader.exec_module(_ts_parser) + parse_all = _ts_parser.parse_all +else: + print("Error: could not load ts_parser", file=sys.stderr) + sys.exit(1) + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +OUT = os.path.join(ROOT, "lib", "ts_flat_generated.c") + + +def generate_wrappers(funcs, dry_run=False): + """Generate flat-array C wrapper functions.""" + if dry_run: + print(f"[dry-run] Would generate {len(funcs)} flat wrappers -> {OUT}") + return + + with open(OUT, "w", encoding="utf-8") as f: + f.write("/* Auto-generated flat-array wrappers. Do not edit. */\n\n") + f.write("#include <string.h>\n") + f.write('#include "ts.h"\n\n') + + for fm in funcs: + safe_x_n = max(fm.x_n, 1) + safe_y_n = max(fm.y_n, 1) + + f.write(f"/* {fm.name}: x_n={fm.x_n}, y_n={fm.y_n}, c_n={fm.c_n} */\n") + f.write(f"int ts_{fm.name}_flat(\n") + + for i in range(fm.y_n): + f.write(f" fp_t *y{i},\n") + + for i in range(fm.x_n): + f.write(f" fp_t const *x{i},\n") + + f.write(f" uint_t n,\n") + f.write(f" ts_constant_t const *params\n") + f.write(f")\n{{\n") + + f.write(f" fp_t * const _y[{safe_y_n}] = {{") + f.write(", ".join(f"y{i}" for i in range(fm.y_n))) + f.write("};\n") + + f.write(f" fp_t const * const _x[{safe_x_n}] = {{") + f.write(", ".join(f"x{i}" for i in range(fm.x_n))) + f.write("};\n") + + for i in range(fm.y_n): + f.write(f" memset(y{i}, 0, n * sizeof(fp_t));\n") + + f.write( + f" return ts_{fm.name}(_y, {fm.y_n}, _x, {fm.x_n}, n, params);\n" + ) + f.write("}\n\n") + + +def main(): + parser = argparse.ArgumentParser(description="Generate flat-array C wrappers") + parser.add_argument( + "--dry-run", + action="store_true", + help="Print what would be generated without writing", + ) + args = parser.parse_args() + + funcs = parse_all(detect_x_access=True) + + if not funcs: + print("Warning: no ts_parameter declarations found.", file=sys.stderr) + sys.exit(1) + + generate_wrappers(funcs, dry_run=args.dry_run) + + if not args.dry_run: + print(f"Generated {len(funcs)} flat wrappers -> {OUT}") + + +if __name__ == "__main__": + main() |