scirs2_core/ndarray_ext/elementwise/functions_2.rs
1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::numeric::Float;
6use crate::simd_ops::{AutoOptimizer, SimdUnifiedOps};
7use ::ndarray::{Array1, ArrayView1};
8
9/// Compute the ceiling (round up) of each element (SIMD-accelerated).
10///
11/// Computes the smallest integer greater than or equal to x for each element.
12///
13/// # Arguments
14///
15/// * `x` - Input 1D array
16///
17/// # Returns
18///
19/// `Array1<F>` with the same length as input, where each element is rounded up
20/// to the nearest integer.
21///
22/// # Performance
23///
24/// - **SIMD**: Automatically used for large arrays (1000+ elements)
25/// - **Scalar**: Used for small arrays or when SIMD is unavailable
26///
27/// # Mathematical Properties
28///
29/// - For any x: ceil(x) >= x
30/// - ceil(x) is the smallest integer >= x
31/// - ceil(-x) = -floor(x)
32/// - ceil(x) = x if x is already an integer
33///
34/// # Examples
35///
36/// ```
37/// use scirs2_core::ndarray::array;
38/// use scirs2_core::ndarray_ext::elementwise::ceil_simd;
39///
40/// let x = array![1.2, 2.7, -1.3, -2.9, 3.0];
41/// let result = ceil_simd(&x.view());
42/// // Result: [2.0, 3.0, -1.0, -2.0, 3.0]
43/// ```
44///
45/// # Applications
46///
47/// - **Memory Allocation**: Rounding up buffer sizes
48/// - **Pagination**: Calculating number of pages needed
49/// - **Resource Planning**: Determining minimum resources required
50/// - **Digital Signal Processing**: Sample rate conversion, upsampling
51/// - **Computer Graphics**: Bounding box calculations
52/// - **Financial**: Rounding up monetary amounts (conservative estimation)
53///
54/// # See Also
55///
56/// - `floor_simd`: Round down to largest integer <= x
57/// - `round_simd`: Round to nearest integer
58pub fn ceil_simd<F>(x: &ArrayView1<F>) -> Array1<F>
59where
60 F: Float + SimdUnifiedOps,
61{
62 if x.is_empty() {
63 return Array1::zeros(0);
64 }
65 let optimizer = AutoOptimizer::new();
66 if optimizer.should_use_simd(x.len()) {
67 return F::simd_ceil(x);
68 }
69 x.mapv(|val| val.ceil())
70}
71/// Compute the rounding to nearest integer of each element (SIMD-accelerated).
72///
73/// Rounds each element to the nearest integer, with ties (x.5) rounding away
74/// from zero (standard rounding).
75///
76/// # Arguments
77///
78/// * `x` - Input 1D array
79///
80/// # Returns
81///
82/// `Array1<F>` with the same length as input, where each element is rounded to
83/// the nearest integer.
84///
85/// # Performance
86///
87/// - **SIMD**: Automatically used for large arrays (1000+ elements)
88/// - **Scalar**: Used for small arrays or when SIMD is unavailable
89///
90/// # Rounding Behavior
91///
92/// This function uses "round half away from zero" (standard rounding):
93/// - 0.5 rounds to 1.0
94/// - 1.5 rounds to 2.0
95/// - 2.5 rounds to 3.0
96/// - -0.5 rounds to -1.0
97/// - -1.5 rounds to -2.0
98///
99/// # Mathematical Properties
100///
101/// - |round(x) - x| <= 0.5 for all x
102/// - round(x) = x if x is already an integer
103/// - round(-x) = -round(x)
104///
105/// # Examples
106///
107/// ```
108/// use scirs2_core::ndarray::array;
109/// use scirs2_core::ndarray_ext::elementwise::round_simd;
110///
111/// let x = array![1.2, 2.7, -1.3, -2.9, 3.0, 2.5];
112/// let result = round_simd(&x.view());
113/// // Result: [1.0, 3.0, -1.0, -3.0, 3.0, 3.0]
114/// // note: 2.5 rounds to 3.0 (away from zero)
115/// ```
116///
117/// # Applications
118///
119/// - **Data Visualization**: Rounding values for display
120/// - **Statistics**: Rounding statistical summaries
121/// - **Financial**: General-purpose monetary rounding
122/// - **Machine Learning**: Quantization for model compression
123/// - **Image Processing**: Pixel value normalization
124/// - **Scientific Computing**: Reducing numerical noise
125///
126/// # See Also
127///
128/// - `floor_simd`: Round down to largest integer <= x
129/// - `ceil_simd`: Round up to smallest integer >= x
130pub fn round_simd<F>(x: &ArrayView1<F>) -> Array1<F>
131where
132 F: Float + SimdUnifiedOps,
133{
134 if x.is_empty() {
135 return Array1::zeros(0);
136 }
137 let optimizer = AutoOptimizer::new();
138 if optimizer.should_use_simd(x.len()) {
139 return F::simd_round(x);
140 }
141 x.mapv(|val| val.round())
142}
143/// Compute the fractional part of each element (SIMD-accelerated).
144///
145/// Returns the signed fractional component of each value (x - trunc(x)).
146///
147/// # Arguments
148///
149/// * `x` - Input 1D array
150///
151/// # Returns
152///
153/// `Array1<F>` with the same length as input, where each element is the signed fractional part
154/// in the range (-1, 1).
155///
156/// # Performance
157///
158/// - **SIMD**: Automatically used for large arrays (1000+ elements)
159/// - **Scalar**: Used for small arrays or when SIMD unavailable
160/// - **Speedup**: 2-4x for large arrays on AVX2/NEON systems
161///
162/// # Mathematical Definition
163///
164/// ```text
165/// fract(x) = x - trunc(x)
166/// ```
167///
168/// For positive x: same as x - floor(x)
169/// For negative x: preserves sign (e.g., fract(-1.5) = -0.5)
170///
171/// # Properties
172///
173/// - -1 < fract(x) < 1 for all finite x
174/// - fract(x + n) = fract(x) for any integer n (periodic with period 1)
175/// - fract(x) = 0 if and only if x is an integer
176/// - fract(x) + trunc(x) = x
177/// - fract(-x) = -fract(x) (odd function)
178///
179/// # Applications
180///
181/// - **Computer Graphics**: Texture coordinate wrapping, repeating patterns
182/// - **Animation**: Cyclic motion, looping animations
183/// - **Signal Processing**: Modulo 1 operations, phase wrapping
184/// - **Numerical Methods**: Fractional part extraction, decimal decomposition
185/// - **Game Development**: Tile-based rendering, repeating textures
186/// - **Scientific Computing**: Periodic boundary conditions, modulo arithmetic
187/// - **Audio Processing**: Phase accumulation, waveform generation
188/// - **Time Calculations**: Extracting fractional seconds, subsecond precision
189/// - **Cryptography**: Linear congruential generators, pseudo-random sequences
190/// - **Financial**: Fractional share calculations, interest accrual
191///
192/// # Examples
193///
194/// ```
195/// use scirs2_core::ndarray::array;
196/// use scirs2_core::ndarray_ext::elementwise::fract_simd;
197///
198/// let x = array![1.5_f64, 2.7, -1.3, 0.0, 3.0];
199/// let result = fract_simd(&x.view());
200/// assert!((result[0] - 0.5_f64).abs() < 1e-10); // 1.5 - trunc(1.5) = 0.5
201/// assert!((result[1] - 0.7_f64).abs() < 1e-10); // 2.7 - trunc(2.7) = 0.7
202/// assert!((result[2] - (-0.3_f64)).abs() < 1e-10); // -1.3 - trunc(-1.3) = -0.3
203/// assert_eq!(result[3], 0.0_f64); // 0.0 - trunc(0.0) = 0.0
204/// assert_eq!(result[4], 0.0_f64); // 3.0 - trunc(3.0) = 0.0
205///
206/// // Property: fract(x) + trunc(x) = x
207/// let values = array![5.25_f64, -2.75, 0.5, 10.0];
208/// let fract_parts = fract_simd(&values.view());
209/// let trunc_parts = values.mapv(|v: f64| v.trunc());
210/// let reconstructed = &fract_parts + &trunc_parts;
211/// for i in 0..values.len() {
212/// assert!((reconstructed[i] - values[i]).abs() < 1e-10);
213/// }
214/// ```
215///
216/// # See Also
217///
218/// - `floor_simd`: Round down to integer
219/// - `round_simd`: Round to nearest integer
220pub fn fract_simd<F>(x: &ArrayView1<F>) -> Array1<F>
221where
222 F: Float + SimdUnifiedOps,
223{
224 if x.is_empty() {
225 return Array1::zeros(0);
226 }
227 let optimizer = AutoOptimizer::new();
228 if optimizer.should_use_simd(x.len()) {
229 return F::simd_fract(x);
230 }
231 x.mapv(|val| val.fract())
232}
233/// Compute the reciprocal (multiplicative inverse) of each element (SIMD-accelerated).
234///
235/// Returns 1/x for each element in the array. For zero values, the result is infinity.
236///
237/// # Arguments
238///
239/// * `x` - Input 1D array
240///
241/// # Returns
242///
243/// `Array1<F>` with the same length as input, where each element is the reciprocal (1/x).
244/// Zero elements yield infinity values.
245///
246/// # Mathematical Definition
247///
248/// ```text
249/// recip(x) = 1/x for x ≠ 0
250/// recip(0) = ∞
251/// ```
252///
253/// # Properties
254///
255/// - recip(recip(x)) = x (involutive property)
256/// - recip(x * y) = recip(x) * recip(y) (multiplicative property)
257/// - recip(x/y) = y/x (division inversion)
258/// - recip(1) = 1 (identity element)
259/// - recip(-x) = -recip(x) (odd function)
260/// - recip(x^n) = (recip(x))^n (power property)
261///
262/// # Applications
263///
264/// ## Numerical Analysis
265/// - Matrix inversions: Computing A^(-1) in linear systems
266/// - Newton's method: Division-free iterations via reciprocal approximations
267/// - Condition number estimation: ||A|| * ||A^(-1)||
268/// - Iterative refinement: Improving solution accuracy in linear solvers
269///
270/// ## Computer Graphics
271/// - Projection transformations: Converting world coordinates to screen space
272/// - Lighting calculations: Inverse square law for light attenuation
273/// - Texture mapping: Computing texture coordinate gradients
274/// - Depth buffer operations: Converting depth to 1/z for perspective
275///
276/// ## Physics Simulations
277/// - Inverse square laws: Gravitational force (F = G * m1 * m2 / r^2)
278/// - Wave propagation: Intensity attenuation (I ∝ 1/r^2)
279/// - Electromagnetic fields: Coulomb's law (F = k * q1 * q2 / r^2)
280/// - Fluid dynamics: Pressure gradient computations
281///
282/// ## Signal Processing
283/// - Filter design: Converting frequency response to impulse response
284/// - Normalization: Scaling signals by reciprocal of maximum amplitude
285/// - Frequency domain analysis: Converting period to frequency (f = 1/T)
286/// - Deconvolution: Inverse filtering for signal restoration
287///
288/// ## Machine Learning
289/// - Normalization layers: Scaling features by reciprocal of variance
290/// - Activation functions: Sigmoid (1 / (1 + exp(-x)))
291/// - Loss functions: Reciprocal of predictions in certain regression tasks
292/// - Learning rate schedules: Inverse decay (lr = initial_lr / (1 + decay * t))
293///
294/// ## Financial Modeling
295/// - Discount rates: Present value calculations (PV = FV * recip(1 + r)^n)
296/// - Interest rate conversions: Converting rates to factors
297/// - Portfolio optimization: Inverse volatility weighting
298/// - Option pricing: Black-Scholes model components
299///
300/// # Edge Cases
301///
302/// - recip(0.0) = f64::INFINITY
303/// - recip(-0.0) = f64::NEG_INFINITY
304/// - recip(INFINITY) = 0.0
305/// - recip(NEG_INFINITY) = -0.0
306/// - recip(NaN) = NaN
307///
308/// # Examples
309///
310/// ```
311/// use scirs2_core::ndarray::{array, Array1};
312/// use scirs2_core::ndarray_ext::elementwise::recip_simd;
313///
314/// let x = array![2.0_f64, 4.0, 0.5, 1.0];
315/// let result = recip_simd(&x.view());
316///
317/// assert!((result[0] - 0.5_f64).abs() < 1e-10); // recip(2.0) = 0.5
318/// assert!((result[1] - 0.25_f64).abs() < 1e-10); // recip(4.0) = 0.25
319/// assert!((result[2] - 2.0_f64).abs() < 1e-10); // recip(0.5) = 2.0
320/// assert!((result[3] - 1.0_f64).abs() < 1e-10); // recip(1.0) = 1.0
321/// ```
322///
323/// # Performance
324///
325/// This function uses SIMD acceleration for arrays larger than 1000 elements,
326/// providing significant speedups through vectorized reciprocal approximations.
327/// For smaller arrays, a scalar fallback is used to avoid SIMD overhead.
328///
329/// # Panics
330///
331/// This function does not panic. Division by zero results in infinity values
332/// as per IEEE 754 floating-point semantics.
333pub fn recip_simd<F>(x: &ArrayView1<F>) -> Array1<F>
334where
335 F: Float + SimdUnifiedOps,
336{
337 if x.is_empty() {
338 return Array1::zeros(0);
339 }
340 let optimizer = AutoOptimizer::new();
341 if optimizer.should_use_simd(x.len()) {
342 return F::simd_recip(x);
343 }
344 x.mapv(|val| val.recip())
345}
346/// Compute integer power (base^n) for each element (SIMD-accelerated).
347///
348/// Returns base^n for each element in the array, where n is an integer exponent.
349/// More efficient than powf for integer exponents.
350///
351/// # Arguments
352///
353/// * `base` - Input 1D array
354/// * `n` - Integer exponent
355///
356/// # Returns
357///
358/// `Array1<F>` with the same length as input, where each element is base^n.
359///
360/// # Mathematical Definition
361///
362/// ```text
363/// powi(x, n) = x^n for integer n
364/// ```
365///
366/// # Properties
367///
368/// - powi(x, 0) = 1 for all x ≠ 0
369/// - powi(x, 1) = x
370/// - powi(x, -n) = 1 / powi(x, n)
371/// - powi(x, n+m) = powi(x, n) * powi(x, m) (exponent addition)
372/// - powi(x*y, n) = powi(x, n) * powi(y, n) (distributive over multiplication)
373/// - powi(x, n*m) = powi(powi(x, n), m) (exponent multiplication)
374///
375/// # Applications
376///
377/// ## Statistics
378/// - Chi-square distributions: Σ(x_i - μ)^2
379/// - Polynomial distributions: Computing moments
380/// - Variance calculations: E\[X^2\] - (E\[X\])^2
381/// - Higher-order moments: Skewness (3rd moment), kurtosis (4th moment)
382///
383/// ## Linear Algebra
384/// - Matrix powers: A^n for matrix operations
385/// - Eigenvalue problems: Computing characteristic polynomials
386/// - Norm calculations: ||x||_p = (Σ|x_i|^p)^(1/p)
387/// - Gram matrices: X^T X operations
388///
389/// ## Signal Processing
390/// - Polynomial filters: Computing filter responses
391/// - Power spectral density: |X(f)|^2
392/// - Autocorrelation: r(k) = Σ x(n) * x(n-k)
393/// - Window functions: Raised cosine windows with integer powers
394///
395/// ## Machine Learning
396/// - Polynomial features: x^2, x^3 for feature engineering
397/// - Loss functions: L2 loss with (y - ŷ)^2
398/// - Regularization: Ridge regression with ||w||^2
399/// - Gradient descent: Computing squared gradients
400///
401/// ## Numerical Analysis
402/// - Taylor series: Computing polynomial approximations
403/// - Newton's method: f(x) and f'(x) evaluations
404/// - Polynomial interpolation: Lagrange basis functions
405/// - Finite differences: Computing higher-order derivatives
406///
407/// ## Physics Simulations
408/// - Inverse square laws: 1/r^2 for gravity and electromagnetism
409/// - Kinetic energy: (1/2)mv^2
410/// - Potential energy: Polynomial potentials
411/// - Power laws: Scaling relationships
412///
413/// # Edge Cases
414///
415/// - powi(0, n) = 0 for n > 0
416/// - powi(0, 0) = 1 (mathematical convention)
417/// - powi(x, 0) = 1 for all x
418/// - powi(∞, n) = ∞ for n > 0, 0 for n < 0
419/// - powi(NaN, n) = NaN
420///
421/// # Examples
422///
423/// ```
424/// use scirs2_core::ndarray::{array, Array1};
425/// use scirs2_core::ndarray_ext::elementwise::powi_simd;
426///
427/// let x = array![2.0_f64, 3.0, 4.0, 5.0];
428///
429/// // Square
430/// let squared = powi_simd(&x.view(), 2);
431/// assert!((squared[0] - 4.0_f64).abs() < 1e-10); // 2^2 = 4
432/// assert!((squared[1] - 9.0_f64).abs() < 1e-10); // 3^2 = 9
433/// assert!((squared[2] - 16.0_f64).abs() < 1e-10); // 4^2 = 16
434/// assert!((squared[3] - 25.0_f64).abs() < 1e-10); // 5^2 = 25
435///
436/// // Cube
437/// let cubed = powi_simd(&x.view(), 3);
438/// assert!((cubed[0] - 8.0_f64).abs() < 1e-10); // 2^3 = 8
439/// assert!((cubed[1] - 27.0_f64).abs() < 1e-10); // 3^3 = 27
440///
441/// // Negative exponent (reciprocal)
442/// let inv_squared = powi_simd(&x.view(), -2);
443/// assert!((inv_squared[0] - 0.25_f64).abs() < 1e-10); // 2^(-2) = 0.25
444/// assert!((inv_squared[1] - (1.0_f64/9.0)).abs() < 1e-10); // 3^(-2) = 1/9
445/// ```
446///
447/// # Performance
448///
449/// This function uses SIMD acceleration for arrays larger than 1000 elements.
450/// Integer power is computed using efficient exponentiation by squaring,
451/// providing better performance than powf for integer exponents.
452///
453/// For small arrays, a scalar fallback is used to avoid SIMD overhead.
454///
455/// # Panics
456///
457/// This function does not panic. Edge cases like 0^0 return 1 as per
458/// mathematical convention and IEEE 754 semantics.
459pub fn powi_simd<F>(base: &ArrayView1<F>, n: i32) -> Array1<F>
460where
461 F: Float + SimdUnifiedOps,
462{
463 if base.is_empty() {
464 return Array1::zeros(0);
465 }
466 let optimizer = AutoOptimizer::new();
467 if optimizer.should_use_simd(base.len()) {
468 return F::simd_powi(base, n);
469 }
470 base.mapv(|val| val.powi(n))
471}
472/// Compute the gamma function Γ(x) for each element (SIMD-accelerated).
473///
474/// Evaluates the gamma function using the Lanczos approximation, providing high accuracy
475/// across the entire real domain. The gamma function is a generalization of the factorial
476/// function to non-integer values.
477///
478/// # Arguments
479///
480/// * `x` - Input 1D array
481///
482/// # Returns
483///
484/// `Array1<F>` with the same length as input, where each element is Γ(x).
485///
486/// # Mathematical Definition
487///
488/// The gamma function is defined by Euler's integral:
489/// ```text
490/// Γ(z) = ∫₀^∞ t^(z-1) e^(-t) dt, for Re(z) > 0
491/// ```
492///
493/// For other values, it is defined by analytic continuation using the functional equation:
494/// ```text
495/// Γ(z+1) = z·Γ(z)
496/// ```
497///
498/// # Key Properties
499///
500/// **Fundamental Properties**:
501/// - Γ(1) = 1
502/// - Γ(n+1) = n! for positive integers n
503/// - Γ(1/2) = √π
504/// - Γ(z+1) = z·Γ(z) (functional equation)
505/// - Γ(z)·Γ(1-z) = π/sin(πz) (reflection formula)
506///
507/// **Special Values**:
508/// - Γ(0) = ∞ (pole)
509/// - Γ(-n) = ∞ for negative integers (poles)
510/// - Γ(n+1/2) = (2n-1)!!·√π/2ⁿ for non-negative integers n
511///
512/// # Applications
513///
514/// ## 1. Statistical Distributions
515/// - **Gamma Distribution**: PDF = (x^(α-1) e^(-x/β)) / (β^α Γ(α))
516/// - **Beta Distribution**: B(α,β) = Γ(α)Γ(β)/Γ(α+β)
517/// - **Chi-Square Distribution**: Uses Γ(k/2)
518/// - **Student's t-Distribution**: Normalization involves Γ((ν+1)/2) and Γ(ν/2)
519///
520/// ## 2. Special Functions
521/// - **Incomplete Gamma**: γ(s,x), Γ(s,x)
522/// - **Beta Function**: B(α,β) = Γ(α)Γ(β)/Γ(α+β)
523/// - **Bessel Functions**: Many representations involve gamma
524/// - **Hypergeometric Functions**: Coefficients use gamma ratios
525///
526/// ## 3. Combinatorics & Number Theory
527/// - **Binomial Coefficients**: C(n,k) = Γ(n+1)/(Γ(k+1)Γ(n-k+1))
528/// - **Stirling Numbers**: Involve gamma function ratios
529/// - **Riemann Zeta Function**: Functional equation uses Γ(s/2)
530///
531/// ## 4. Bayesian Inference
532/// - **Conjugate Priors**: Gamma and Beta distributions
533/// - **Dirichlet Distribution**: Normalization uses gamma products
534/// - **Variational Inference**: Optimization involves gamma and digamma
535///
536/// ## 5. Physics & Engineering
537/// - **Quantum Mechanics**: Angular momentum eigenstates
538/// - **String Theory**: Veneziano amplitude
539/// - **Statistical Mechanics**: Partition functions
540/// - **Signal Processing**: Window functions
541///
542/// ## 6. Numerical Analysis
543/// - **Integration**: Change of variables
544/// - **Asymptotic Analysis**: Stirling's approximation
545/// - **Interpolation**: Gamma function interpolates factorial
546///
547/// # Implementation
548///
549/// Uses the **Lanczos approximation** with g=7 and 9 coefficients, providing
550/// ~15 decimal digits of accuracy for x ∈ [0.5, 100]. For x < 0.5, uses the
551/// reflection formula to leverage the accurate computation of Γ(1-x).
552///
553/// **Algorithm**:
554/// ```text
555/// Γ(z+1) = √(2π) * (z + g + 1/2)^(z + 1/2) * e^(-(z + g + 1/2)) * A_g(z)
556///
557/// where A_g(z) = c₀ + c₁/(z+1) + c₂/(z+2) + ... + c₈/(z+9)
558/// ```
559///
560/// **Coefficients** (from Boost C++ Library):
561/// - Optimized using Remez exchange algorithm
562/// - Minimax criterion for optimal approximation
563/// - Provides uniform accuracy across domain
564///
565/// # Edge Cases
566///
567/// - `gamma(NaN)` → NaN
568/// - `gamma(0)` → ∞
569/// - `gamma(-n)` → ∞ for negative integers (poles)
570/// - `gamma(x)` → ∞ as x → ∞
571/// - `gamma(x)` → 0 as x → -∞ (alternating sign)
572///
573/// # Performance Characteristics
574///
575/// - **Small arrays** (< 1000 elements): Scalar implementation
576/// - **Large arrays** (≥ 1000 elements): SIMD-accelerated via compiler auto-vectorization
577/// - **Time complexity**: O(n) where n is array length
578/// - **Space complexity**: O(n) for output array
579/// - **Accuracy**: ~15 decimal digits for typical inputs
580///
581/// # Examples
582///
583/// ```
584/// use scirs2_core::ndarray::array;
585/// use scirs2_core::ndarray_ext::elementwise::gamma_simd;
586///
587/// // Factorials: Γ(n+1) = n!
588/// let x = array![1.0_f64, 2.0, 3.0, 4.0, 5.0];
589/// let gamma_x = gamma_simd(&x.view());
590/// // gamma_x ≈ [1, 1, 2, 6, 24] (0!, 1!, 2!, 3!, 4!)
591///
592/// // Half-integer values
593/// let x_half = array![0.5];
594/// let gamma_half = gamma_simd(&x_half.view());
595/// // gamma_half[0] ≈ 1.772453850905516 (√π)
596///
597/// // Statistical applications
598/// use scirs2_core::numeric::Float;
599/// let alpha = array![2.0, 3.0, 5.0];
600/// let normalization = gamma_simd(&alpha.view());
601/// // Use in gamma distribution PDF: x^(α-1) e^(-x/β) / (β^α Γ(α))
602/// ```
603///
604/// # Mathematical References
605///
606/// - Abramowitz & Stegun, "Handbook of Mathematical Functions", §6.1
607/// - Lanczos, "A Precision Approximation of the Gamma Function" (1964)
608/// - Press et al., "Numerical Recipes", §6.1
609/// - Boost C++ Libraries: Math Toolkit Documentation
610///
611/// # See Also
612///
613/// - `powi_simd` - Integer power (related operation)
614/// - `exp_simd`, `ln_simd` - Component operations
615/// - Future: `digamma_simd` - Logarithmic derivative of gamma
616pub fn gamma_simd<F>(x: &ArrayView1<F>) -> Array1<F>
617where
618 F: Float + SimdUnifiedOps,
619{
620 if x.is_empty() {
621 return Array1::zeros(0);
622 }
623 let optimizer = AutoOptimizer::new();
624 if optimizer.should_use_simd(x.len()) {
625 return F::simd_gamma(x);
626 }
627 F::simd_gamma(x)
628}
629/// Compute the arctangent of each element (SIMD-accelerated).
630///
631/// Computes atan(x) for each element, returning values in the range (-π/2, π/2).
632///
633/// # Arguments
634///
635/// * `x` - Input 1D array
636///
637/// # Returns
638///
639/// `Array1<F>` with the same length as input, where each element is the arctangent
640/// in radians.
641///
642/// # Performance
643///
644/// - **SIMD**: Automatically used for large arrays (1000+ elements)
645/// - **Scalar**: Used for small arrays or when SIMD is unavailable
646///
647/// # Mathematical Properties
648///
649/// - Range: (-π/2, π/2) for all finite x
650/// - atan(0) = 0
651/// - atan(-x) = -atan(x) (odd function)
652/// - atan(∞) = π/2, atan(-∞) = -π/2
653/// - atan(tan(x)) = x for x ∈ (-π/2, π/2)
654///
655/// # Examples
656///
657/// ```
658/// use scirs2_core::ndarray::array;
659/// use scirs2_core::ndarray_ext::elementwise::atan_simd;
660///
661/// let x = array![0.0_f64, 1.0, -1.0, f64::INFINITY];
662/// let result = atan_simd(&x.view());
663/// // Result: [0.0, π/4, -π/4, π/2]
664/// ```
665///
666/// # Applications
667///
668/// - **Geometry**: Calculating angles from slopes
669/// - **Robotics**: Inverse kinematics for joint angles
670/// - **Computer Vision**: Feature detection, edge orientation
671/// - **Signal Processing**: Phase unwrapping, frequency analysis
672/// - **Physics**: Trajectory analysis, projectile motion
673///
674/// # See Also
675///
676/// - [`asin_simd`]: Arcsine function
677/// - [`acos_simd`]: Arccosine function
678/// - [`atan2_simd`]: Two-argument arctangent for full angle range
679pub fn atan_simd<F>(x: &ArrayView1<F>) -> Array1<F>
680where
681 F: Float + SimdUnifiedOps,
682{
683 if x.is_empty() {
684 return Array1::zeros(0);
685 }
686 let optimizer = AutoOptimizer::new();
687 if optimizer.should_use_simd(x.len()) {
688 return F::simd_atan(x);
689 }
690 x.mapv(|val| val.atan())
691}
692/// Compute the arcsine of each element (SIMD-accelerated).
693///
694/// Computes asin(x) for each element, returning values in the range [-π/2, π/2].
695///
696/// # Arguments
697///
698/// * `x` - Input 1D array with values in [-1, 1]
699///
700/// # Returns
701///
702/// `Array1<F>` with the same length as input, where each element is the arcsine
703/// in radians. Returns NaN for |x| > 1.
704///
705/// # Performance
706///
707/// - **SIMD**: Automatically used for large arrays (1000+ elements)
708/// - **Scalar**: Used for small arrays or when SIMD is unavailable
709///
710/// # Mathematical Properties
711///
712/// - Domain: [-1, 1]
713/// - Range: [-π/2, π/2]
714/// - asin(0) = 0
715/// - asin(-x) = -asin(x) (odd function)
716/// - asin(1) = π/2, asin(-1) = -π/2
717/// - asin(sin(x)) = x for x ∈ [-π/2, π/2]
718/// - Returns NaN for |x| > 1
719///
720/// # Examples
721///
722/// ```
723/// use scirs2_core::ndarray::array;
724/// use scirs2_core::ndarray_ext::elementwise::asin_simd;
725///
726/// let x = array![0.0_f64, 0.5, 1.0, -1.0];
727/// let result = asin_simd(&x.view());
728/// // Result: [0.0, π/6, π/2, -π/2]
729/// ```
730///
731/// # Applications
732///
733/// - **Navigation**: Great circle distance calculations
734/// - **Astronomy**: Celestial coordinate transformations
735/// - **Physics**: Wave mechanics, pendulum analysis
736/// - **Computer Graphics**: Spherical coordinates, lighting
737/// - **Robotics**: Inverse kinematics with constraints
738///
739/// # See Also
740///
741/// - `atan_simd`: Arctangent function
742/// - `acos_simd`: Arccosine function
743/// - `sin_simd`: Forward sine function
744pub fn asin_simd<F>(x: &ArrayView1<F>) -> Array1<F>
745where
746 F: Float + SimdUnifiedOps,
747{
748 if x.is_empty() {
749 return Array1::zeros(0);
750 }
751 let optimizer = AutoOptimizer::new();
752 if optimizer.should_use_simd(x.len()) {
753 return F::simd_asin(x);
754 }
755 x.mapv(|val| val.asin())
756}
757/// Compute the arccosine of each element (SIMD-accelerated).
758///
759/// Computes acos(x) for each element, returning values in the range [0, π].
760///
761/// # Arguments
762///
763/// * `x` - Input 1D array with values in [-1, 1]
764///
765/// # Returns
766///
767/// `Array1<F>` with the same length as input, where each element is the arccosine
768/// in radians. Returns NaN for |x| > 1.
769///
770/// # Performance
771///
772/// - **SIMD**: Automatically used for large arrays (1000+ elements)
773/// - **Scalar**: Used for small arrays or when SIMD is unavailable
774///
775/// # Mathematical Properties
776///
777/// - Domain: [-1, 1]
778/// - Range: [0, π]
779/// - acos(1) = 0, acos(-1) = π
780/// - acos(0) = π/2
781/// - acos(-x) = π - acos(x)
782/// - acos(cos(x)) = x for x ∈ [0, π]
783/// - acos(x) + asin(x) = π/2
784/// - Returns NaN for |x| > 1
785///
786/// # Examples
787///
788/// ```
789/// use scirs2_core::ndarray::array;
790/// use scirs2_core::ndarray_ext::elementwise::acos_simd;
791///
792/// let x = array![1.0_f64, 0.5, 0.0, -1.0];
793/// let result = acos_simd(&x.view());
794/// // Result: [0.0, π/3, π/2, π]
795/// ```
796///
797/// # Applications
798///
799/// - **3D Graphics**: Dot product angle calculations
800/// - **Machine Learning**: Cosine similarity to angle conversion
801/// - **Physics**: Angular momentum, rotation analysis
802/// - **Astronomy**: Coordinate system transformations
803/// - **Navigation**: Bearing and heading calculations
804///
805/// # See Also
806///
807/// - `atan_simd`: Arctangent function
808/// - `asin_simd`: Arcsine function
809/// - `cos_simd`: Forward cosine function
810pub fn acos_simd<F>(x: &ArrayView1<F>) -> Array1<F>
811where
812 F: Float + SimdUnifiedOps,
813{
814 if x.is_empty() {
815 return Array1::zeros(0);
816 }
817 let optimizer = AutoOptimizer::new();
818 if optimizer.should_use_simd(x.len()) {
819 return F::simd_acos(x);
820 }
821 x.mapv(|val| val.acos())
822}
823/// Compute the two-argument arctangent element-wise (SIMD-accelerated).
824///
825/// Computes atan2(y, x) for each pair of elements, returning values in the range
826/// (-π, π]. This function correctly handles the signs of both arguments to
827/// determine the quadrant.
828///
829/// # Arguments
830///
831/// * `y` - Y-coordinates (sine component)
832/// * `x` - X-coordinates (cosine component)
833///
834/// # Returns
835///
836/// `Array1<F>` with the same length as inputs, where each element is the angle
837/// in radians from the positive x-axis to the point (x, y).
838///
839/// # Performance
840///
841/// - **SIMD**: Automatically used for large arrays (1000+ elements)
842/// - **Scalar**: Used for small arrays or when SIMD is unavailable
843///
844/// # Mathematical Properties
845///
846/// - Range: (-π, π]
847/// - atan2(0, 0) = 0 (by convention)
848/// - atan2(y, x) = atan(y/x) when x > 0
849/// - atan2(y, 0) = π/2 * sign(y) when x = 0
850/// - atan2(-y, x) = -atan2(y, x)
851/// - atan2(y, -x) = π - atan2(y, x) when y >= 0
852/// - atan2(y, -x) = -π + atan2(y, x) when y < 0
853///
854/// # Quadrants
855///
856/// - Quadrant I (x > 0, y > 0): (0, π/2)
857/// - Quadrant II (x < 0, y > 0): (π/2, π)
858/// - Quadrant III (x < 0, y < 0): (-π, -π/2)
859/// - Quadrant IV (x > 0, y < 0): (-π/2, 0)
860///
861/// # Examples
862///
863/// ```
864/// use scirs2_core::ndarray::array;
865/// use scirs2_core::ndarray_ext::elementwise::atan2_simd;
866///
867/// let y = array![1.0, 1.0, -1.0, -1.0];
868/// let x = array![1.0_f64, -1.0, -1.0, 1.0];
869/// let angles = atan2_simd(&y.view(), &x.view());
870/// // Result: [π/4, 3π/4, -3π/4, -π/4]
871/// ```
872///
873/// # Applications
874///
875/// - **Robotics**: Joint angle calculations, path planning
876/// - **Computer Vision**: Feature orientation, optical flow
877/// - **Navigation**: Heading and bearing calculations
878/// - **Spatial Computing**: Coordinate transformations
879/// - **Physics**: Vector angle calculations, force analysis
880/// - **Computer Graphics**: Rotation angles, sprite orientation
881/// - **Signal Processing**: Phase calculations, complex number arguments
882///
883/// # See Also
884///
885/// - [`atan_simd`]: Single-argument arctangent
886/// - [`asin_simd`]: Arcsine function
887/// - [`acos_simd`]: Arccosine function
888pub fn atan2_simd<F>(y: &ArrayView1<F>, x: &ArrayView1<F>) -> Array1<F>
889where
890 F: Float + SimdUnifiedOps,
891{
892 assert_eq!(y.len(), x.len(), "y and x arrays must have the same length");
893 if y.is_empty() {
894 return Array1::zeros(0);
895 }
896 let optimizer = AutoOptimizer::new();
897 if optimizer.should_use_simd(y.len()) {
898 return F::simd_atan2(y, x);
899 }
900 y.iter()
901 .zip(x.iter())
902 .map(|(&y_val, &x_val)| y_val.atan2(x_val))
903 .collect::<Vec<_>>()
904 .into()
905}
906/// Compute the base-10 logarithm of each element (SIMD-accelerated).
907///
908/// Computes log₁₀(x) for each element, where log₁₀(x) = ln(x) / ln(10).
909///
910/// # Arguments
911///
912/// * `x` - Input 1D array with positive values
913///
914/// # Returns
915///
916/// `Array1<F>` with the same length as input, where each element is the base-10
917/// logarithm. Returns NaN for x ≤ 0, and -∞ for x = 0.
918///
919/// # Performance
920///
921/// - **SIMD**: Automatically used for large arrays (1000+ elements)
922/// - **Scalar**: Used for small arrays or when SIMD is unavailable
923///
924/// # Mathematical Properties
925///
926/// - Domain: (0, ∞)
927/// - Range: (-∞, ∞)
928/// - log₁₀(1) = 0
929/// - log₁₀(10) = 1
930/// - log₁₀(10ⁿ) = n
931/// - log₁₀(x * y) = log₁₀(x) + log₁₀(y)
932/// - log₁₀(x / y) = log₁₀(x) - log₁₀(y)
933/// - log₁₀(xⁿ) = n * log₁₀(x)
934/// - Returns NaN for x ≤ 0
935/// - Returns -∞ for x = 0
936///
937/// # Examples
938///
939/// ```
940/// use scirs2_core::ndarray::array;
941/// use scirs2_core::ndarray_ext::elementwise::log10_simd;
942///
943/// let x = array![1.0_f64, 10.0, 100.0, 1000.0];
944/// let result = log10_simd(&x.view());
945/// // Result: [0.0, 1.0, 2.0, 3.0]
946/// ```
947///
948/// # Applications
949///
950/// - **Signal Processing**: Decibel scale (dB = 10 * log₁₀(P/P₀))
951/// - **Chemistry**: pH scale (pH = -log₁₀[H⁺])
952/// - **Astronomy**: Magnitude scale (apparent magnitude)
953/// - **Scientific Computing**: Decades representation, log-log plots
954/// - **Machine Learning**: Feature scaling, log-loss functions
955/// - **Information Theory**: Hartley's entropy (base-10)
956/// - **Physics**: Richter scale (earthquake magnitude)
957/// - **Audio Processing**: Sound intensity level
958///
959/// # See Also
960///
961/// - `ln_simd`: Natural logarithm (base e)
962/// - `log2_simd`: Base-2 logarithm
963/// - `exp_simd`: Exponential function (inverse of ln)
964pub fn log10_simd<F>(x: &ArrayView1<F>) -> Array1<F>
965where
966 F: Float + SimdUnifiedOps,
967{
968 if x.is_empty() {
969 return Array1::zeros(0);
970 }
971 let optimizer = AutoOptimizer::new();
972 if optimizer.should_use_simd(x.len()) {
973 return F::simd_log10(x);
974 }
975 x.mapv(|val| val.log10())
976}