![]() |
OpenSWMM Engine
6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
|
Bit-exact geometry-table interpolation — the single source of truth. More...
Go to the source code of this file.
Namespaces | |
| namespace | openswmm |
| namespace | openswmm::xsect |
Functions | |
| double | openswmm::xsect::lookup_exact (double x, const double *t, int n) noexcept |
| Bit-exact transliteration of legacy xsect.c:lookup(). | |
| double | openswmm::xsect::lookup_fast (double x, const double *t, int n) noexcept |
| Reciprocal-multiply lookup (fast, NOT bit-exact — see §6). | |
| double | openswmm::xsect::norm_x (double depth, double param) noexcept |
| double | openswmm::xsect::norm_lookup (double depth, double param, const double *t, int n) noexcept |
| Mode-aware normalize + table lookup (bit-exact by default; §6 fast if opted in). | |
Bit-exact geometry-table interpolation — the single source of truth.
lookup_exact() is an op-for-op transliteration of legacy src/legacy/engine/xsect.c:lookup(). It is shared by BOTH the per-element accessor (xsect::lookup) and the batch geometry kernels (XSectBatch.cpp) so the two paths can never drift. The circular / force-main hot path and every shared-table shape (egg, horseshoe, arch, ellipse, baskethandle, …) interpolate through this one routine.
Bit-exactness contract (see docs/plans/xsect_bitexact_vectorization.md):
x / delta), never a precomputed reciprocal (x * inv_delta): a*(1/b) != a/b in double.mul+add and silently diverges NEON from x86). The global -ffp-contract=off / /fp:precise presets stop the compiler from contracting; do not reintroduce std::fma/intrinsic FMA in callers. IEEE division is correctly rounded and identical on every platform, so this routine is bit-identical on Windows/MSVC, Linux, and macOS(arm64/x86).Preconditions (mirror legacy, whose callers guarantee them): x must be finite and in [0, 1] on entry (values > 1 are tolerated via the i >= n-1 early-out, matching legacy). static_cast<int> of a non-finite double is undefined behavior, so callers that can produce non-finite / negative x — e.g. a conduit normalized by a zero full-depth — MUST guard before calling (see xsect::lookup and the batch kernels).