trueno/vector/ops/transcendental/trigonometric.rs
1//! Trigonometric and inverse trigonometric functions: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`
2
3use crate::backends::VectorBackend;
4use crate::vector::Vector;
5use crate::{dispatch_unary_op, Result};
6
7impl Vector<f32> {
8 /// Element-wise sine: result\[i\] = sin(x\[i\])
9 ///
10 /// Computes the sine for each element (input in radians).
11 /// Uses Rust's optimized f32::sin() method.
12 ///
13 /// # Examples
14 ///
15 /// ```
16 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
17 /// use trueno::Vector;
18 /// use std::f32::consts::PI;
19 ///
20 /// let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);
21 /// let result = v.sin()?;
22 /// // result ≈ [0.0, 1.0, 0.0]
23 /// # Ok(())
24 /// # }
25 /// ```
26 ///
27 /// # Special Cases
28 ///
29 /// - `sin(0)` returns 0.0
30 /// - `sin(π/2)` returns 1.0
31 /// - `sin(π)` returns 0.0 (approximately)
32 /// - `sin(-x)` returns -sin(x) (odd function)
33 /// - Periodic with period 2π: sin(x + 2π) = sin(x)
34 ///
35 /// # Applications
36 ///
37 /// - Signal processing: Waveform generation, oscillators, modulation
38 /// - Physics: Harmonic motion, wave propagation, pendulums
39 /// - Audio: Synthesizers, tone generation, effects processing
40 /// - Graphics: Animation, rotation transformations, procedural generation
41 /// - Fourier analysis: Frequency decomposition, spectral analysis
42 pub fn sin(&self) -> Result<Vector<f32>> {
43 // Uninit: backend writes every element before any read.
44 let n = self.len();
45 let mut result_data: Vec<f32> = Vec::with_capacity(n);
46 // SAFETY: Backend writes all elements before any read.
47 unsafe {
48 result_data.set_len(n);
49 }
50
51 if !self.data.is_empty() {
52 dispatch_unary_op!(self.backend, sin, &self.data, &mut result_data);
53 }
54
55 Ok(Vector { data: result_data, backend: self.backend })
56 }
57
58 /// Element-wise cosine: result\[i\] = cos(x\[i\])
59 ///
60 /// Computes the cosine for each element (input in radians).
61 /// Uses Rust's optimized f32::cos() method.
62 ///
63 /// # Examples
64 ///
65 /// ```
66 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
67 /// use trueno::Vector;
68 /// use std::f32::consts::PI;
69 ///
70 /// let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);
71 /// let result = v.cos()?;
72 /// // result ≈ [1.0, 0.0, -1.0]
73 /// # Ok(())
74 /// # }
75 /// ```
76 ///
77 /// # Special Cases
78 ///
79 /// - `cos(0)` returns 1.0
80 /// - `cos(π/2)` returns 0.0 (approximately)
81 /// - `cos(π)` returns -1.0
82 /// - `cos(-x)` returns cos(x) (even function)
83 /// - Periodic with period 2π: cos(x + 2π) = cos(x)
84 /// - Relation to sine: cos(x) = sin(x + π/2)
85 ///
86 /// # Applications
87 ///
88 /// - Signal processing: Phase-shifted waveforms, I/Q modulation, quadrature signals
89 /// - Physics: Projectile motion, wave interference, damped oscillations
90 /// - Graphics: Rotation matrices, camera transforms, circular motion
91 /// - Audio: Stereo panning, spatial audio, frequency synthesis
92 /// - Engineering: Control systems, frequency response, AC circuits
93 pub fn cos(&self) -> Result<Vector<f32>> {
94 // Uninit: backend writes every element before any read.
95 let n = self.len();
96 let mut result_data: Vec<f32> = Vec::with_capacity(n);
97 // SAFETY: Backend writes all elements before any read.
98 unsafe {
99 result_data.set_len(n);
100 }
101
102 if !self.data.is_empty() {
103 dispatch_unary_op!(self.backend, cos, &self.data, &mut result_data);
104 }
105
106 Ok(Vector { data: result_data, backend: self.backend })
107 }
108
109 /// Computes element-wise tangent (tan) of the vector.
110 ///
111 /// Returns a new vector where each element is the tangent of the corresponding input element.
112 /// tan(x) = sin(x) / cos(x)
113 ///
114 /// # Returns
115 /// - `Ok(Vector<f32>)`: New vector with tan(x) for each element
116 ///
117 /// # Properties
118 /// - Odd function: tan(-x) = -tan(x)
119 /// - Period: 2π (not π, despite common misconception)
120 /// - Undefined at x = π/2 + nπ (where n is any integer)
121 /// - tan(x) = sin(x) / cos(x)
122 /// - Range: (-∞, +∞)
123 ///
124 /// # Performance
125 /// - Iterator map pattern for cache efficiency
126 /// - Leverages Rust's optimized f32::tan()
127 /// - Auto-vectorized by LLVM on supporting platforms
128 ///
129 /// # Examples
130 /// ```
131 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
132 /// use trueno::Vector;
133 /// use std::f32::consts::PI;
134 ///
135 /// let angles = Vector::from_slice(&[0.0, PI / 4.0, -PI / 4.0]);
136 /// let result = angles.tan()?;
137 /// // Result: [0.0, 1.0, -1.0] (approximately)
138 /// # Ok(())
139 /// # }
140 /// ```
141 ///
142 /// # Use Cases
143 /// - Trigonometry: Slope calculations, angle relationships
144 /// - Signal processing: Phase analysis, modulation
145 /// - Physics: Projectile trajectories, optics (Snell's law angles)
146 /// - Graphics: Perspective projection, field of view calculations
147 /// - Engineering: Slope gradients, tangent lines to curves
148 pub fn tan(&self) -> Result<Vector<f32>> {
149 // Uninit: backend writes every element before any read.
150 let n = self.len();
151 let mut result_data: Vec<f32> = Vec::with_capacity(n);
152 // SAFETY: Backend writes all elements before any read.
153 unsafe {
154 result_data.set_len(n);
155 }
156
157 if !self.data.is_empty() {
158 dispatch_unary_op!(self.backend, tan, &self.data, &mut result_data);
159 }
160
161 Ok(Vector { data: result_data, backend: self.backend })
162 }
163
164 /// Computes element-wise arcsine (asin/sin⁻¹) of the vector.
165 ///
166 /// Returns a new vector where each element is the inverse sine of the corresponding input element.
167 /// This is the inverse function of sin: if y = sin(x), then x = asin(y).
168 ///
169 /// # Returns
170 /// - `Ok(Vector<f32>)`: New vector with asin(x) for each element
171 ///
172 /// # Properties
173 /// - Domain: [-1, 1] (inputs outside this range produce NaN)
174 /// - Range: [-π/2, π/2]
175 /// - Odd function: asin(-x) = -asin(x)
176 /// - Inverse relation: asin(sin(x)) = x for x ∈ [-π/2, π/2]
177 /// - asin(0) = 0
178 /// - asin(1) = π/2
179 /// - asin(-1) = -π/2
180 ///
181 /// # Performance
182 /// - Iterator map pattern for cache efficiency
183 /// - Leverages Rust's optimized f32::asin()
184 /// - Auto-vectorized by LLVM on supporting platforms
185 ///
186 /// # Examples
187 /// ```
188 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
189 /// use trueno::Vector;
190 /// use std::f32::consts::PI;
191 ///
192 /// let values = Vector::from_slice(&[0.0, 0.5, 1.0]);
193 /// let result = values.asin()?;
194 /// // Result: [0.0, π/6, π/2] (approximately)
195 /// # Ok(())
196 /// # }
197 /// ```
198 ///
199 /// # Use Cases
200 /// - Physics: Calculating angles from sine values in mechanics, optics
201 /// - Signal processing: Phase recovery, demodulation
202 /// - Graphics: Inverse transformations, angle calculations
203 /// - Navigation: GPS calculations, spherical trigonometry
204 /// - Control systems: Inverse kinematics, servo positioning
205 pub fn asin(&self) -> Result<Vector<f32>> {
206 let asin_data: Vec<f32> = self.data.iter().map(|x| x.asin()).collect();
207 Ok(Vector { data: asin_data, backend: self.backend })
208 }
209
210 /// Computes element-wise arccosine (acos/cos⁻¹) of the vector.
211 ///
212 /// Returns a new vector where each element is the inverse cosine of the corresponding input element.
213 /// This is the inverse function of cos: if y = cos(x), then x = acos(y).
214 ///
215 /// # Returns
216 /// - `Ok(Vector<f32>)`: New vector with acos(x) for each element
217 ///
218 /// # Properties
219 /// - Domain: [-1, 1] (inputs outside this range produce NaN)
220 /// - Range: [0, π]
221 /// - Symmetry: acos(-x) = π - acos(x)
222 /// - Inverse relation: acos(cos(x)) = x for x ∈ [0, π]
223 /// - acos(0) = π/2
224 /// - acos(1) = 0
225 /// - acos(-1) = π
226 ///
227 /// # Performance
228 /// - Iterator map pattern for cache efficiency
229 /// - Leverages Rust's optimized f32::acos()
230 /// - Auto-vectorized by LLVM on supporting platforms
231 ///
232 /// # Examples
233 /// ```
234 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
235 /// use trueno::Vector;
236 /// use std::f32::consts::PI;
237 ///
238 /// let values = Vector::from_slice(&[0.0, 0.5, 1.0]);
239 /// let result = values.acos()?;
240 /// // Result: [π/2, π/3, 0.0] (approximately)
241 /// # Ok(())
242 /// # }
243 /// ```
244 ///
245 /// # Use Cases
246 /// - Physics: Angle calculations in mechanics, optics, reflections
247 /// - Signal processing: Phase analysis, correlation functions
248 /// - Graphics: View angle calculations, lighting models
249 /// - Navigation: Bearing calculations, great circle distances
250 /// - Robotics: Joint angle solving, orientation calculations
251 pub fn acos(&self) -> Result<Vector<f32>> {
252 let acos_data: Vec<f32> = self.data.iter().map(|x| x.acos()).collect();
253 Ok(Vector { data: acos_data, backend: self.backend })
254 }
255
256 /// Computes element-wise arctangent (atan/tan⁻¹) of the vector.
257 ///
258 /// Returns a new vector where each element is the inverse tangent of the corresponding input element.
259 /// This is the inverse function of tan: if y = tan(x), then x = atan(y).
260 ///
261 /// # Returns
262 /// - `Ok(Vector<f32>)`: New vector with atan(x) for each element
263 ///
264 /// # Properties
265 /// - Domain: All real numbers (-∞, +∞)
266 /// - Range: (-π/2, π/2)
267 /// - Odd function: atan(-x) = -atan(x)
268 /// - Inverse relation: atan(tan(x)) = x for x ∈ (-π/2, π/2)
269 /// - atan(0) = 0
270 /// - atan(1) = π/4
271 /// - atan(-1) = -π/4
272 /// - lim(x→∞) atan(x) = π/2
273 /// - lim(x→-∞) atan(x) = -π/2
274 ///
275 /// # Performance
276 /// - Iterator map pattern for cache efficiency
277 /// - Leverages Rust's optimized f32::atan()
278 /// - Auto-vectorized by LLVM on supporting platforms
279 ///
280 /// # Examples
281 /// ```
282 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
283 /// use trueno::Vector;
284 /// use std::f32::consts::PI;
285 ///
286 /// let values = Vector::from_slice(&[0.0, 1.0, -1.0]);
287 /// let result = values.atan()?;
288 /// // Result: [0.0, π/4, -π/4] (approximately)
289 /// # Ok(())
290 /// # }
291 /// ```
292 ///
293 /// # Use Cases
294 /// - Physics: Angle calculations from slopes, velocity components
295 /// - Signal processing: Phase unwrapping, FM demodulation
296 /// - Graphics: Rotation calculations, camera orientation
297 /// - Robotics: Inverse kinematics, steering angles
298 /// - Navigation: Heading calculations from coordinates
299 pub fn atan(&self) -> Result<Vector<f32>> {
300 let atan_data: Vec<f32> = self.data.iter().map(|x| x.atan()).collect();
301 Ok(Vector { data: atan_data, backend: self.backend })
302 }
303}