oxifft/api/types.rs
1//! Public type definitions for the OxiFFT API.
2
3use core::fmt;
4use core::ops::BitOr;
5
6/// Transform direction.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum Direction {
10 /// Forward transform (analysis): time domain → frequency domain
11 Forward,
12 /// Backward/Inverse transform (synthesis): frequency domain → time domain
13 Backward,
14}
15
16impl Direction {
17 /// Get the sign for the exponential: -1 for forward, +1 for backward.
18 ///
19 /// This matches the FFTW convention where the forward (analysis) transform
20 /// uses a negative exponent and the backward (synthesis) transform uses a
21 /// positive exponent.
22 #[must_use]
23 pub const fn sign(self) -> i32 {
24 match self {
25 Self::Forward => -1,
26 Self::Backward => 1,
27 }
28 }
29}
30
31impl TryFrom<i32> for Direction {
32 type Error = InvalidDirection;
33
34 /// Construct a `Direction` from its FFTW-style sign convention:
35 /// `-1` means [`Direction::Forward`] (negative exponent) and
36 /// `+1` means [`Direction::Backward`] (positive exponent).
37 ///
38 /// # Errors
39 ///
40 /// Returns [`InvalidDirection`] if `value` is not `-1` or `1`.
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use oxifft::Direction;
46 ///
47 /// let fwd = Direction::try_from(-1_i32).expect("forward");
48 /// assert_eq!(fwd, Direction::Forward);
49 ///
50 /// let bwd = Direction::try_from(1_i32).expect("backward");
51 /// assert_eq!(bwd, Direction::Backward);
52 ///
53 /// assert!(Direction::try_from(0_i32).is_err());
54 /// ```
55 fn try_from(value: i32) -> Result<Self, Self::Error> {
56 match value {
57 -1 => Ok(Self::Forward),
58 1 => Ok(Self::Backward),
59 n => Err(InvalidDirection(n)),
60 }
61 }
62}
63
64/// Error returned when an integer cannot be converted to a [`Direction`].
65///
66/// Valid values are `-1` (forward, negative exponent) and `1` (backward, positive exponent),
67/// following the FFTW sign convention.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub struct InvalidDirection(pub i32);
70
71impl fmt::Display for InvalidDirection {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(
74 f,
75 "invalid direction value {}: expected -1 (forward) or 1 (backward)",
76 self.0
77 )
78 }
79}
80
81impl core::error::Error for InvalidDirection {}
82
83/// Planning flags that control algorithm selection.
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
85pub struct Flags(u32);
86
87impl Flags {
88 /// Use heuristics only, don't measure (fastest planning, may not be optimal).
89 pub const ESTIMATE: Self = Self(0);
90
91 /// Measure a few algorithms and pick the best.
92 pub const MEASURE: Self = Self(1 << 0);
93
94 /// Try harder to find the optimal algorithm.
95 pub const PATIENT: Self = Self(1 << 1);
96
97 /// Try all possible algorithms exhaustively.
98 pub const EXHAUSTIVE: Self = Self(1 << 2);
99
100 /// Preserve input array (default behavior).
101 pub const PRESERVE_INPUT: Self = Self(1 << 3);
102
103 /// Allow destroying input array for potentially better performance.
104 pub const DESTROY_INPUT: Self = Self(1 << 4);
105
106 /// Plan for unaligned data.
107 pub const UNALIGNED: Self = Self(1 << 5);
108
109 /// Check if MEASURE flag is set.
110 #[must_use]
111 pub const fn is_measure(self) -> bool {
112 self.0 & Self::MEASURE.0 != 0
113 }
114
115 /// Check if PATIENT flag is set.
116 #[must_use]
117 pub const fn is_patient(self) -> bool {
118 self.0 & Self::PATIENT.0 != 0
119 }
120
121 /// Check if EXHAUSTIVE flag is set.
122 #[must_use]
123 pub const fn is_exhaustive(self) -> bool {
124 self.0 & Self::EXHAUSTIVE.0 != 0
125 }
126
127 /// Check if input destruction is allowed.
128 #[must_use]
129 pub const fn can_destroy_input(self) -> bool {
130 self.0 & Self::DESTROY_INPUT.0 != 0
131 }
132}
133
134impl BitOr for Flags {
135 type Output = Self;
136
137 fn bitor(self, rhs: Self) -> Self::Output {
138 Self(self.0 | rhs.0)
139 }
140}
141
142/// Real-to-real transform kind (DCT/DST variants).
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144#[non_exhaustive]
145pub enum R2rKind {
146 /// DCT-I (REDFT00)
147 DctI,
148 /// DCT-II (REDFT10) - "the DCT"
149 DctII,
150 /// DCT-III (REDFT01) - inverse of DCT-II
151 DctIII,
152 /// DCT-IV (REDFT11)
153 DctIV,
154 /// DST-I (RODFT00)
155 DstI,
156 /// DST-II (RODFT10)
157 DstII,
158 /// DST-III (RODFT01)
159 DstIII,
160 /// DST-IV (RODFT11)
161 DstIV,
162 /// Discrete Hartley Transform
163 Dht,
164 /// Half-complex to real (used internally)
165 Hc2r,
166 /// Real to half-complex (used internally)
167 R2hc,
168}