Skip to main content

oxifft_codegen_impl/
winograd_constants.rs

1//! Mirror of `oxifft::dft::codelets::winograd_constants` for use by codegen-impl.
2//!
3//! Values must stay in sync — run the cross-validation test to verify.
4//!
5//! All constants are f64 precision, computed from exact expressions
6//! cos(2πk/N) and sin(2πk/N). The forward DFT convention used throughout
7//! is `W_N` = e^{-2πi/N}, so:
8//!   - real parts: cos(2πk/N)
9//!   - imaginary parts (for the negative sign): -sin(2πk/N)
10
11// ─── DFT-3 ───────────────────────────────────────────────────────────────────
12// cos(2π/3) = -1/2,  sin(2π/3) = √3/2
13
14/// cos(2π/3) = −1/2
15pub const C3_1: f64 = -0.5_f64;
16/// sin(2π/3) = √3/2
17pub const C3_2: f64 = 0.866_025_403_784_438_7_f64;
18
19// ─── DFT-5 ───────────────────────────────────────────────────────────────────
20// cos(2πk/5) and sin(2πk/5) for k = 1, 2
21
22/// cos(2π/5)
23pub const C5_COS1: f64 = 0.309_016_994_374_947_45_f64;
24/// cos(4π/5)
25pub const C5_COS2: f64 = -0.809_016_994_374_947_3_f64;
26/// sin(2π/5)
27pub const C5_SIN1: f64 = 0.951_056_516_295_153_5_f64;
28/// sin(4π/5)
29pub const C5_SIN2: f64 = 0.587_785_252_292_473_2_f64;
30
31// ─── DFT-7 ───────────────────────────────────────────────────────────────────
32// cos(2πk/7) and sin(2πk/7) for k = 1, 2, 3
33
34/// cos(2π/7)
35pub const C7_COS1: f64 = 0.623_489_801_858_733_6_f64;
36/// cos(4π/7)
37pub const C7_COS2: f64 = -0.222_520_933_956_314_34_f64;
38/// cos(6π/7)
39pub const C7_COS3: f64 = -0.900_968_867_902_419_f64;
40/// sin(2π/7)
41pub const C7_SIN1: f64 = 0.781_831_482_468_029_8_f64;
42/// sin(4π/7)
43pub const C7_SIN2: f64 = 0.974_927_912_181_823_6_f64;
44/// sin(6π/7)
45pub const C7_SIN3: f64 = 0.433_883_739_117_558_23_f64;
46
47// ─── DFT-9 ───────────────────────────────────────────────────────────────────
48// cos(2πk/9) and sin(2πk/9) for k = 1, 2, 3, 4
49
50/// cos(2π/9)
51pub const C9_COS1: f64 = 0.766_044_443_118_978_f64;
52/// cos(4π/9)
53pub const C9_COS2: f64 = 0.173_648_177_666_930_41_f64;
54/// cos(6π/9) = cos(2π/3) = -1/2
55pub const C9_COS3: f64 = -0.5_f64;
56/// cos(8π/9)
57pub const C9_COS4: f64 = -0.939_692_620_785_908_3_f64;
58/// sin(2π/9)
59pub const C9_SIN1: f64 = 0.642_787_609_686_539_3_f64;
60/// sin(4π/9)
61pub const C9_SIN2: f64 = 0.984_807_753_012_208_f64;
62/// sin(6π/9) = sin(2π/3) = √3/2
63pub const C9_SIN3: f64 = 0.866_025_403_784_438_7_f64;
64/// sin(8π/9)
65pub const C9_SIN4: f64 = 0.342_020_143_325_668_9_f64;
66
67// ─── DFT-11 ──────────────────────────────────────────────────────────────────
68// cos(2πk/11) and sin(2πk/11) for k = 1..5
69
70/// cos(2π/11)
71pub const C11_COS1: f64 = 0.841_253_532_831_181_2_f64;
72/// cos(4π/11)
73pub const C11_COS2: f64 = 0.415_415_013_001_886_44_f64;
74/// cos(6π/11)
75pub const C11_COS3: f64 = -0.142_314_838_273_285_f64;
76/// cos(8π/11)
77pub const C11_COS4: f64 = -0.654_860_733_945_285_1_f64;
78/// cos(10π/11)
79pub const C11_COS5: f64 = -0.959_492_973_614_497_4_f64;
80/// sin(2π/11)
81pub const C11_SIN1: f64 = 0.540_640_817_455_597_6_f64;
82/// sin(4π/11)
83pub const C11_SIN2: f64 = 0.909_631_995_354_518_3_f64;
84/// sin(6π/11)
85pub const C11_SIN3: f64 = 0.989_821_441_880_932_8_f64;
86/// sin(8π/11)
87pub const C11_SIN4: f64 = 0.755_749_574_354_258_3_f64;
88/// sin(10π/11)
89pub const C11_SIN5: f64 = 0.281_732_556_841_429_67_f64;
90
91// ─── DFT-13 ──────────────────────────────────────────────────────────────────
92// cos(2πk/13) and sin(2πk/13) for k = 1..6
93
94/// cos(2π/13)
95pub const C13_COS1: f64 = 0.885_456_025_653_209_9_f64;
96/// cos(4π/13)
97pub const C13_COS2: f64 = 0.568_064_746_731_155_8_f64;
98/// cos(6π/13)
99pub const C13_COS3: f64 = 0.120_536_680_255_323_f64;
100/// cos(8π/13)
101pub const C13_COS4: f64 = -0.354_604_887_042_535_45_f64;
102/// cos(10π/13)
103pub const C13_COS5: f64 = -0.748_510_748_171_101_2_f64;
104/// cos(12π/13)
105pub const C13_COS6: f64 = -0.970_941_817_426_052_f64;
106/// sin(2π/13)
107pub const C13_SIN1: f64 = 0.464_723_172_043_768_5_f64;
108/// sin(4π/13)
109pub const C13_SIN2: f64 = 0.822_983_865_893_656_4_f64;
110/// sin(6π/13)
111pub const C13_SIN3: f64 = 0.992_708_874_098_054_f64;
112/// sin(8π/13)
113pub const C13_SIN4: f64 = 0.935_016_242_685_414_8_f64;
114/// sin(10π/13)
115pub const C13_SIN5: f64 = 0.663_122_658_240_795_2_f64;
116/// sin(12π/13)
117pub const C13_SIN6: f64 = 0.239_315_664_287_557_68_f64;
118
119// ─── Cross-validation test ────────────────────────────────────────────────────
120
121#[cfg(test)]
122pub(crate) fn verify_constants_match_runtime() {
123    // Verify that this mirror matches the runtime winograd_constants exactly.
124    // These are the same values — just check they agree within f64 precision.
125    let tol = 1e-13;
126    let two_pi = 2.0 * std::f64::consts::PI;
127
128    // DFT-3
129    assert!((C3_1 - f64::cos(two_pi / 3.0)).abs() < tol, "C3_1");
130    assert!((C3_2 - f64::sin(two_pi / 3.0)).abs() < tol, "C3_2");
131
132    // DFT-5
133    assert!((C5_COS1 - f64::cos(two_pi / 5.0)).abs() < tol, "C5_COS1");
134    assert!(
135        (C5_COS2 - f64::cos(2.0 * two_pi / 5.0)).abs() < tol,
136        "C5_COS2"
137    );
138    assert!((C5_SIN1 - f64::sin(two_pi / 5.0)).abs() < tol, "C5_SIN1");
139    assert!(
140        (C5_SIN2 - f64::sin(2.0 * two_pi / 5.0)).abs() < tol,
141        "C5_SIN2"
142    );
143
144    // DFT-7
145    assert!((C7_COS1 - f64::cos(two_pi / 7.0)).abs() < tol, "C7_COS1");
146    assert!(
147        (C7_COS2 - f64::cos(2.0 * two_pi / 7.0)).abs() < tol,
148        "C7_COS2"
149    );
150    assert!(
151        (C7_COS3 - f64::cos(3.0 * two_pi / 7.0)).abs() < tol,
152        "C7_COS3"
153    );
154    assert!((C7_SIN1 - f64::sin(two_pi / 7.0)).abs() < tol, "C7_SIN1");
155    assert!(
156        (C7_SIN2 - f64::sin(2.0 * two_pi / 7.0)).abs() < tol,
157        "C7_SIN2"
158    );
159    assert!(
160        (C7_SIN3 - f64::sin(3.0 * two_pi / 7.0)).abs() < tol,
161        "C7_SIN3"
162    );
163}