Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
simd_dispatch.hpp
Go to the documentation of this file.
1#pragma once
2/**
3 * @file simd_dispatch.hpp
4 * @brief Public API for SIMD-accelerated β and γ batch computation.
5 *
6 * Module: include/srfm/simd/
7 * Owner: AGT-08 — 2026-03-01
8 *
9 * Responsibility
10 * --------------
11 * Expose two vectorised batch functions and a stateful BetaCalculator that
12 * wire into the hot path of the SRFM financial signal pipeline.
13 *
14 * computeBetaBatch() — batch |v_i| / running_max → vector<BetaVelocity>
15 * computeGammaBatch() — batch 1/√(1−β²) → vector<LorentzFactor>
16 *
17 * At program start-up the module probes the CPU (via cpu_features.hpp) and
18 * selects AVX-512F → AVX2 → scalar automatically. Existing callers see no
19 * interface change.
20 *
21 * Guarantees
22 * ----------
23 * • All functions are noexcept.
24 * • computeBetaBatch() returns one BetaVelocity per input velocity.
25 * • computeGammaBatch() returns one LorentzFactor per input BetaVelocity.
26 * • Results are numerically identical to the scalar reference path
27 * (verified by the test suite in tests/momentum/test_simd.cpp).
28 * • BetaCalculator is NOT thread-safe (it owns mutable running_max state).
29 * Use one BetaCalculator per thread, or protect with a mutex.
30 *
31 * NOT Responsible For
32 * -------------------
33 * • Sourcing raw velocity data — caller provides the input vector.
34 * • Cross-session running_max persistence — call reset() between sessions.
35 * • Thread safety for BetaCalculator — caller's responsibility.
36 */
37
38#include "cpu_features.hpp"
39#include "momentum/momentum.hpp" // BetaVelocity, LorentzFactor (src/ on include path)
40
41#include <vector>
42
43namespace srfm::simd {
44
45// ── SimdGammaCompute ──────────────────────────────────────────────────────────
46
47/**
48 * @brief Internal factory helper for constructing LorentzFactor objects
49 * from pre-computed gamma scalars (friend of LorentzFactor).
50 *
51 * This struct is an implementation detail of the SIMD dispatch layer.
52 * It is declared here (in the public header) solely because friend
53 * declarations in LorentzFactor must refer to a fully-qualified name.
54 * Do NOT use this struct in application code.
55 */
57 /// Wrap a pre-validated gamma value in a LorentzFactor.
58 /// Precondition: gamma_val >= 1.0 && std::isfinite(gamma_val).
59 [[nodiscard]] static srfm::momentum::LorentzFactor
60 make(double gamma_val) noexcept {
61 return srfm::momentum::LorentzFactor{gamma_val};
62 }
63};
64
65// ── Free-function batch API ───────────────────────────────────────────────────
66
67/**
68 * @brief Compute β_i = |velocities[i]| / running_max for every element.
69 *
70 * running_max is updated monotonically across successive calls: it equals
71 * max(running_max_in, max(|velocities[i]|)). Pass running_max=0.0 on the
72 * first call.
73 *
74 * The selected SIMD kernel processes blocks of 8 (AVX-512) or 4 (AVX2)
75 * doubles per cycle; tail elements use the scalar fallback.
76 *
77 * @param velocities Raw price velocities (any finite double, arbitrary sign).
78 * @param running_max Current session maximum |velocity|; updated in-place.
79 * @return One BetaVelocity per input velocity, in order.
80 * Empty vector when velocities is empty.
81 *
82 * # Panics
83 * This function never panics.
84 *
85 * @example
86 * @code
87 * double rmax = 0.0;
88 * auto betas = srfm::simd::computeBetaBatch(velocities, rmax);
89 * @endcode
90 */
91[[nodiscard]] std::vector<srfm::momentum::BetaVelocity>
92computeBetaBatch(const std::vector<double>& velocities,
93 double& running_max) noexcept;
94
95/**
96 * @brief Compute γ_i = 1/√(1 − β_i²) for every element.
97 *
98 * Inputs are clamped to [0, BETA_MAX_SAFE) before the sqrt to prevent NaN.
99 * SIMD kernel processes 8 (AVX-512) or 4 (AVX2) elements per cycle.
100 *
101 * @param betas Validated BetaVelocity values from computeBetaBatch().
102 * @return One LorentzFactor per input beta, in order.
103 * Empty vector when betas is empty.
104 *
105 * # Panics
106 * This function never panics.
107 */
108[[nodiscard]] std::vector<srfm::momentum::LorentzFactor>
109computeGammaBatch(const std::vector<srfm::momentum::BetaVelocity>& betas) noexcept;
110
111// ── BetaCalculator ────────────────────────────────────────────────────────────
112
113/**
114 * @brief Stateful wrapper around computeBetaBatch / computeGammaBatch.
115 *
116 * Maintains a session-scoped running_max so callers do not need to manage
117 * it manually. Existing call sites that use RelativisticSignalProcessor
118 * can migrate by:
119 *
120 * @code
121 * // Before (scalar):
122 * double rmax = 0.0;
123 * auto betas = scalar_beta_batch(velocities, rmax);
124 * auto gammas = scalar_gamma_batch(betas);
125 *
126 * // After (SIMD-dispatched, same semantics):
127 * BetaCalculator calc;
128 * auto betas = calc.computeBetaBatch(velocities);
129 * auto gammas = calc.computeGammaBatch(betas);
130 * @endcode
131 *
132 * NOT thread-safe. Create one BetaCalculator per thread.
133 */
135public:
136 /// Construct a fresh calculator. running_max starts at 0.0.
137 BetaCalculator() noexcept;
138
139 /**
140 * @brief Compute β_i = |v_i| / running_max for a batch of velocities.
141 *
142 * Delegates to the runtime-selected SIMD kernel.
143 * running_max is advanced to include this batch's maximum |velocity|.
144 *
145 * @param velocities Raw price velocities (any finite double).
146 * @return One BetaVelocity per velocity, in order.
147 */
148 [[nodiscard]] std::vector<srfm::momentum::BetaVelocity>
149 computeBetaBatch(const std::vector<double>& velocities) noexcept;
150
151 /**
152 * @brief Compute γ_i = 1/√(1 − β_i²) for a batch of betas.
153 *
154 * Delegates to the runtime-selected SIMD kernel.
155 *
156 * @param betas Output from a previous call to computeBetaBatch().
157 * @return One LorentzFactor per beta, in order.
158 */
159 [[nodiscard]] std::vector<srfm::momentum::LorentzFactor>
161 const std::vector<srfm::momentum::BetaVelocity>& betas) noexcept;
162
163 /**
164 * @brief Reset the running maximum to 0.0.
165 *
166 * Call between trading sessions to prevent stale state from inflating
167 * the denominator and artificially suppressing beta values.
168 */
169 void reset() noexcept;
170
171 /// Returns the current running maximum (read-only).
172 [[nodiscard]] double running_max() const noexcept;
173
174 /// Returns the SIMD level selected for this process.
175 [[nodiscard]] SimdLevel simd_level() const noexcept;
176
177private:
178 double running_max_{ 0.0 };
179 SimdLevel simd_level_{ SimdLevel::SCALAR };
180};
181
182} // namespace srfm::simd
Pre-computed Lorentz factor γ = 1/√(1−β²). Always ≥ 1.0.
Definition momentum.hpp:98
Stateful wrapper around computeBetaBatch / computeGammaBatch.
std::vector< srfm::momentum::LorentzFactor > computeGammaBatch(const std::vector< srfm::momentum::BetaVelocity > &betas) noexcept
Compute γ_i = 1/√(1 − β_i²) for a batch of betas.
void reset() noexcept
Reset the running maximum to 0.0.
std::vector< srfm::momentum::BetaVelocity > computeBetaBatch(const std::vector< double > &velocities) noexcept
Compute β_i = |v_i| / running_max for a batch of velocities.
SimdLevel simd_level() const noexcept
Returns the SIMD level selected for this process.
double running_max() const noexcept
Returns the current running maximum (read-only).
BetaCalculator() noexcept
Construct a fresh calculator. running_max starts at 0.0.
Runtime SIMD capability detection for the SRFM acceleration layer.
std::vector< srfm::momentum::LorentzFactor > computeGammaBatch(const std::vector< srfm::momentum::BetaVelocity > &betas) noexcept
Compute γ_i = 1/√(1 − β_i²) for every element.
SimdLevel
Ordered enumeration of SIMD capability tiers.
@ SCALAR
No SIMD; pure scalar C++ path.
std::vector< srfm::momentum::BetaVelocity > computeBetaBatch(const std::vector< double > &velocities, double &running_max) noexcept
Momentum-Velocity Signal Processor (AGT-03 / SRFM)
Internal factory helper for constructing LorentzFactor objects from pre-computed gamma scalars (frien...
static srfm::momentum::LorentzFactor make(double gamma_val) noexcept