Behavior-preserving deduplication of numeric helpers in Utils.py, proven
bit-for-bit identical across a broad input grid (all smooth methods,
ceil/floor/round over int/np.integer/float/non-finite/invalid inputs).
- smooth: replace the four near-identical zero-phase filter branches and
the gaussian else-fallback with a table-driven dispatch
`_SMOOTHING_FILTER_SPECS: method -> (kernel, window_selector)`, mirroring
the get_ma_fn/get_price_fn `.get(key, default)` idiom. std stays derived
from the odd window for every kernel.
- ceil_to_step/floor_to_step: extract a shared `_step_round(value, step,
int_op, float_op)` core (validation, integer fast-path, finiteness guard,
float path); lru_cache stays on the public wrappers only. round_to_step
is left untouched (distinct banker's/half-step tie-breaking).
- get_odd_window/get_even_window merge (F6) intentionally skipped: they are
used as first-class callables in the smooth dispatch table and merging
would churn a stable public API and split lru_cache capacity for no gain.
Closes #174
* refactor(quickadapter): tighten smooth dispatch comment and step typing
- _SMOOTHING_FILTER_SPECS comment: it does not mirror the get_ma_fn/
get_price_fn idiom (those build a local dict per call); it is a
module-level Final table of the _*_SPECS family consumed via
.get(method, default). Correct the wording; keep the load-bearing
invariants (std stays odd-window-derived; default reproduces the
legacy gaussian/odd else-branch).
- _step_round: annotate float_op as Callable[[float], int] since only
math.ceil/math.floor are passed and both return int.
* refactor(quickadapter): rename smooth dispatch table, fix its comment
- Rename _SMOOTHING_FILTER_SPECS -> _ZERO_PHASE_FILTER_DISPATCH. The
_*_SPECS suffix is reserved for the dict[str, _ParamSpec] config
validation family (e.g. _SMOOTHING_SPECS); this is a runtime dispatch
table feeding zero_phase_filter, and the near-homonym _SMOOTHING_SPECS
was ambiguous. Module-private symbol, both occurrences updated.
- Fix its comment: it is not a _*_SPECS family member, and both the
kernel and the window parity vary per method (the invariant is std,
which stays odd-window-derived), not "only the window parity".
Review-driven, no-op (comment only, behavior bit-for-bit unchanged):
the previous "Both the kernel and the window parity vary per method"
put kernel and parity in a false parallel. The kernel varies per method,
but the window parity is odd for every method except kaiser_bessel_derived
(even). Restate precisely; keep the std-odd-derived and .get-default notes.
Review-driven, no-op (behavior bit-for-bit unchanged): the smooth
zero-phase dispatch `.get` default duplicated the gaussian entry value
verbatim. Reference the entry (_ZERO_PHASE_FILTER_DISPATCH[SMOOTHING_METHODS[1]])
instead, matching the get_ma_fn/get_price_fn `.get(key, table[default])`
idiom and single-sourcing the fallback. The default is only reachable
for methods outside the closed SmoothingMethod enum (defensive).
* docs(quickadapter): drop redundant dispatch-table paraphrase
* docs(quickadapter): drop self-documented dispatch-table header comment