1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Convolution: pure correlation kernels, NaN-aware wrappers, and thin
//! domain entry points.
//!
//! Three layers, mirroring `bins::overlap` (pure `for_each` kernel ->
//! `rebin`/`coverage` semantic wrappers -> `Spectrum::rebin` domain
//! entry):
//!
//! - **Pure kernels** ([`conv1d`], [`conv_axis`], [`conv2d`]):
//! NaN-naive `Σ w·v`, no normalization, no boundary renormalization.
//! - **Normalized-convolution wrappers** ([`conv2d_renorm`],
//! [`conv_axis_renorm`]): NaN-as-missing, backend-uniform.
//! - **Domain entries** (later, `Spectrum::convolve_lsf`,
//! `image::convolve_*`): the only surface that crosses FFI.
//!
//! The bare kernels compute **correlation** — the kernel is *not*
//! flipped. True convolution is a wrapper that flips the kernel first
//! (see `image::convolve_psf`). For a symmetric kernel correlation and
//! convolution coincide; they differ only for an asymmetric kernel,
//! where convolution mirrors it.
pub use ;
pub use conv2d;
pub use ;
pub use ;
// Shared crate-internal: the variable-width LSF path reuses this single
// erf source so it stays consistent with the fixed-kernel constructor.
pub use normal_cdf;
/// Out-of-bounds handling for the bare correlation kernels.
///
/// Applies only to the pure [`conv1d`] / [`conv_axis`] / [`conv2d`].
/// The normalized-convolution wrappers deliberately do *not*
/// take a `Boundary`: they treat every out-of-bounds tap as missing
/// (zero-extension on both the filled and the validity pass), which is a
/// distinct and mutually exclusive boundary model. Reflect/Nearest would
/// keep the validity pass saturated at the edge, defeating the
/// missing-data renormalization, so the two are kept orthogonal.
/// Kernel normalization, applied at kernel-construction time.
///
/// This is orthogonal to the boundary renormalization performed by the
/// NaN wrappers (ROADMAP D4): one is decided when the kernel is built,
/// the other when the convolution runs. Folding both into a single
/// "mode" enum would combinatorially explode, so they stay separate.
/// Resolve a (possibly out-of-range) source index against an axis of
/// length `length` under `boundary`. Returns `None` only for a
/// [`Boundary::Zero`] out-of-range index (the tap contributes nothing).
///
/// This is the single shared boundary resolver for *every* bare kernel
/// ([`conv1d`], [`conv_axis`], [`conv2d`]) — 2-D correlation applies it
/// per axis. Keeping one implementation is a structural guarantee that
/// 1-D and 2-D agree at the edges; were each kernel to fold indices on
/// its own, any drift would silently desynchronize them. `length` is
/// assumed `>= 1` (callers early-return on empty axes).
pub