scirs2_core/ndarray_ext/elementwise/
functions.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 absolute value of each element (SIMD-accelerated).
10///
11/// Computes |x| for each element in the array.
12///
13/// # Arguments
14///
15/// * `x` - Input 1D array
16///
17/// # Returns
18///
19/// `Array1<F>` with the same length as input, with absolute values.
20///
21/// # Performance
22///
23/// - **SIMD**: Automatically used for large arrays (1000+ elements)
24/// - **Scalar**: Used for small arrays or when SIMD unavailable
25/// - **Speedup**: 2-4x for large f32 arrays on AVX2 systems
26///
27/// # Mathematical Definition
28///
29/// ```text
30/// abs(x) = |x| = {
31///     x   if x >= 0
32///     -x  if x < 0
33/// }
34/// ```
35///
36/// # Examples
37///
38/// ```
39/// use scirs2_core::ndarray::array;
40/// use scirs2_core::ndarray_ext::elementwise::abs_simd;
41///
42/// let x = array![-3.0, -1.5, 0.0, 1.5, 3.0];
43/// let result = abs_simd(&x.view());
44///
45/// assert_eq!(result[0], 3.0);
46/// assert_eq!(result[1], 1.5);
47/// assert_eq!(result[2], 0.0);
48/// assert_eq!(result[3], 1.5);
49/// assert_eq!(result[4], 3.0);
50/// ```
51///
52/// # Edge Cases
53///
54/// - **Empty array**: Returns empty array
55/// - **Zero**: Returns zero
56/// - **NaN**: Returns NaN (preserves NaN)
57/// - **Infinity**: Returns positive infinity
58///
59/// # Applications
60///
61/// - **Statistics**: Absolute deviation, MAE (Mean Absolute Error)
62/// - **Signal Processing**: Envelope detection, magnitude calculation
63/// - **Optimization**: L1 norm computation, absolute loss functions
64/// - **Numerical Analysis**: Error analysis, residual computation
65/// - **Image Processing**: Gradient magnitude, difference images
66pub fn abs_simd<F>(x: &ArrayView1<F>) -> Array1<F>
67where
68    F: Float + SimdUnifiedOps,
69{
70    if x.is_empty() {
71        return Array1::zeros(0);
72    }
73    let optimizer = AutoOptimizer::new();
74    if optimizer.should_use_simd(x.len()) {
75        return F::simd_abs(x);
76    }
77    x.mapv(|val| val.abs())
78}
79/// Compute the sign (signum) of each element (SIMD-accelerated).
80///
81/// Returns +1.0 for positive values, -1.0 for negative values, and 0.0 for zero.
82///
83/// # Arguments
84///
85/// * `x` - Input 1D array
86///
87/// # Returns
88///
89/// `Array1<F>` with the same length as input, where each element is the sign of the input.
90///
91/// # Performance
92///
93/// - **SIMD**: Automatically used for large arrays (1000+ elements)
94/// - **Scalar**: Used for small arrays or when SIMD unavailable
95/// - **Speedup**: 2-4x for large arrays on AVX2/NEON systems
96///
97/// # Mathematical Definition
98///
99/// ```text
100/// sign(x) = { +1.0  if x > 0
101///           {  0.0  if x = 0
102///           { -1.0  if x < 0
103/// ```
104///
105/// # Properties
106///
107/// - sign(-x) = -sign(x) (odd function)
108/// - sign(0) = 0
109/// - sign(x) * |x| = x
110/// - sign(x) * sign(y) = sign(x * y)
111/// - |sign(x)| ≤ 1 for all x
112///
113/// # Applications
114///
115/// - **Numerical Analysis**: Gradient descent direction, optimization algorithms
116/// - **Signal Processing**: Phase detection, zero-crossing analysis
117/// - **Physics Simulations**: Force direction, velocity direction
118/// - **Machine Learning**: Feature engineering, binary classification features
119/// - **Control Systems**: Error sign for PID controllers
120/// - **Game Development**: Direction vectors, collision normals
121/// - **Statistics**: Wilcoxon signed-rank test, sign test
122/// - **Finance**: Market trend indicators (bull/bear)
123/// - **Geometry**: Surface normal orientation, vector direction
124/// - **Image Processing**: Edge direction, gradient orientation
125///
126/// # Examples
127///
128/// ```
129/// use scirs2_core::ndarray::array;
130/// use scirs2_core::ndarray_ext::elementwise::sign_simd;
131///
132/// let x = array![-3.0_f64, -1.5, 0.0, 1.5, 3.0];
133/// let result = sign_simd(&x.view());
134/// assert_eq!(result[0], -1.0_f64); // negative → -1
135/// assert_eq!(result[1], -1.0_f64); // negative → -1
136/// assert_eq!(result[2],  0.0_f64); // zero → 0
137/// assert_eq!(result[3],  1.0_f64); // positive → +1
138/// assert_eq!(result[4],  1.0_f64); // positive → +1
139///
140/// // Property: sign(x) * |x| = x
141/// let values = array![-5.0_f64, -2.0, 0.0, 2.0, 5.0];
142/// let signs = sign_simd(&values.view());
143/// let abs_values = values.mapv(|x: f64| x.abs());
144/// let reconstructed = signs * abs_values;
145/// for i in 0..values.len() {
146///     assert!((reconstructed[i] - values[i]).abs() < 1e-10);
147/// }
148/// ```
149///
150/// # See Also
151///
152/// - `abs_simd`: Magnitude without sign
153/// - `clamp_simd`: Constrain values to a range
154pub fn sign_simd<F>(x: &ArrayView1<F>) -> Array1<F>
155where
156    F: Float + SimdUnifiedOps,
157{
158    if x.is_empty() {
159        return Array1::zeros(0);
160    }
161    let optimizer = AutoOptimizer::new();
162    if optimizer.should_use_simd(x.len()) {
163        return F::simd_sign(x);
164    }
165    x.mapv(|val| {
166        if val > F::zero() {
167            F::one()
168        } else if val < F::zero() {
169            -F::one()
170        } else {
171            F::zero()
172        }
173    })
174}
175/// Compute the square root of each element (SIMD-accelerated).
176///
177/// Computes √x for each element in the array.
178///
179/// # Arguments
180///
181/// * `x` - Input 1D array (must contain non-negative values)
182///
183/// # Returns
184///
185/// `Array1<F>` with the same length as input, with square roots.
186///
187/// # Performance
188///
189/// - **SIMD**: Automatically used for large arrays (1000+ elements)
190/// - **Scalar**: Used for small arrays or when SIMD unavailable
191/// - **Speedup**: 2-4x for large f32 arrays on AVX2 systems
192///
193/// # Mathematical Definition
194///
195/// ```text
196/// sqrt(x) = √x = y such that y² = x
197/// ```
198///
199/// # Examples
200///
201/// ```
202/// use scirs2_core::ndarray::array;
203/// use scirs2_core::ndarray_ext::elementwise::sqrt_simd;
204///
205/// let x = array![1.0_f64, 4.0, 9.0, 16.0, 25.0];
206/// let result = sqrt_simd(&x.view());
207///
208/// assert_eq!(result[0], 1.0);
209/// assert_eq!(result[1], 2.0);
210/// assert_eq!(result[2], 3.0);
211/// assert_eq!(result[3], 4.0);
212/// assert_eq!(result[4], 5.0);
213/// ```
214///
215/// # Edge Cases
216///
217/// - **Empty array**: Returns empty array
218/// - **Zero**: Returns zero
219/// - **Negative numbers**: Returns NaN (undefined in real numbers)
220/// - **NaN**: Returns NaN (preserves NaN)
221/// - **Positive infinity**: Returns positive infinity
222///
223/// # Applications
224///
225/// - **Statistics**: Standard deviation, RMS (Root Mean Square)
226/// - **Geometry**: Distance calculations, Euclidean metrics
227/// - **Physics**: Velocity from kinetic energy, magnitude calculations
228/// - **Machine Learning**: Gradient scaling, learning rate schedules
229/// - **Image Processing**: Gaussian blur, distance transforms
230///
231/// # Note on Negative Values
232///
233/// Square root of negative numbers is undefined in real arithmetic.
234/// The function will return NaN for negative inputs, following IEEE 754 standard.
235///
236/// ```
237/// use scirs2_core::ndarray::array;
238/// use scirs2_core::ndarray_ext::elementwise::sqrt_simd;
239///
240/// let x = array![-1.0_f64];
241/// let result = sqrt_simd(&x.view());
242/// assert!(result[0].is_nan());
243/// ```
244pub fn sqrt_simd<F>(x: &ArrayView1<F>) -> Array1<F>
245where
246    F: Float + SimdUnifiedOps,
247{
248    if x.is_empty() {
249        return Array1::zeros(0);
250    }
251    let optimizer = AutoOptimizer::new();
252    if optimizer.should_use_simd(x.len()) {
253        return F::simd_sqrt(x);
254    }
255    x.mapv(|val| val.sqrt())
256}
257/// Compute the exponential (e^x) of each element (SIMD-accelerated).
258///
259/// Computes e^x for each element in the array.
260///
261/// # Arguments
262///
263/// * `x` - Input 1D array
264///
265/// # Returns
266///
267/// `Array1<F>` with the same length as input, with exponential values.
268///
269/// # Performance
270///
271/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
272/// - **Speedup**: 2-4x on large arrays via auto-vectorization
273///
274/// # Mathematical Definition
275///
276/// ```text
277/// exp(x) = e^x where e ≈ 2.71828...
278/// ```
279///
280/// # Examples
281///
282/// ```
283/// use scirs2_core::ndarray::array;
284/// use scirs2_core::ndarray_ext::elementwise::exp_simd;
285///
286/// let x = array![0.0_f64, 1.0, 2.0];
287/// let result = exp_simd(&x.view());
288///
289/// assert!((result[0] - 1.0).abs() < 1e-10);
290/// assert!((result[1] - 2.718281828).abs() < 1e-9);
291/// assert!((result[2] - 7.389056099).abs() < 1e-9);
292/// ```
293///
294/// # Edge Cases
295///
296/// - **Empty array**: Returns empty array
297/// - **Zero**: exp(0) = 1
298/// - **Large positive**: May overflow to infinity
299/// - **Large negative**: Approaches zero
300/// - **NaN**: Returns NaN (preserves NaN)
301///
302/// # Applications
303///
304/// - **Machine Learning**: Softmax, sigmoid activation
305/// - **Optimization**: Exponential decay, learning rate schedules
306/// - **Probability**: Exponential distribution, Gaussian PDF
307/// - **Neural Networks**: Attention mechanisms, transformer models
308/// - **Reinforcement Learning**: Policy gradients, Q-learning
309pub fn exp_simd<F>(x: &ArrayView1<F>) -> Array1<F>
310where
311    F: Float + SimdUnifiedOps,
312{
313    if x.is_empty() {
314        return Array1::zeros(0);
315    }
316    let optimizer = AutoOptimizer::new();
317    if optimizer.should_use_simd(x.len()) {
318        return F::simd_exp(x);
319    }
320    x.mapv(|val| val.exp())
321}
322/// Compute the natural logarithm (ln(x)) of each element (SIMD-accelerated).
323///
324/// Computes ln(x) for each element in the array.
325///
326/// # Arguments
327///
328/// * `x` - Input 1D array (must contain positive values)
329///
330/// # Returns
331///
332/// `Array1<F>` with the same length as input, with natural logarithm values.
333///
334/// # Performance
335///
336/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
337/// - **Speedup**: 2-4x on large arrays via auto-vectorization
338///
339/// # Mathematical Definition
340///
341/// ```text
342/// ln(x) = log_e(x) = y such that e^y = x
343/// ```
344///
345/// # Examples
346///
347/// ```
348/// use scirs2_core::ndarray::array;
349/// use scirs2_core::ndarray_ext::elementwise::ln_simd;
350///
351/// let x = array![1.0_f64, 2.718281828, 7.389056099];
352/// let result = ln_simd(&x.view());
353///
354/// assert!((result[0] - 0.0).abs() < 1e-10);
355/// assert!((result[1] - 1.0).abs() < 1e-9);
356/// assert!((result[2] - 2.0).abs() < 1e-9);
357/// ```
358///
359/// # Edge Cases
360///
361/// - **Empty array**: Returns empty array
362/// - **One**: ln(1) = 0
363/// - **Zero**: Returns negative infinity
364/// - **Negative numbers**: Returns NaN (undefined in reals)
365/// - **NaN**: Returns NaN (preserves NaN)
366/// - **Positive infinity**: Returns positive infinity
367///
368/// # Applications
369///
370/// - **Machine Learning**: Log-likelihood, cross-entropy loss
371/// - **Statistics**: Log-normal distribution, Shannon entropy
372/// - **Optimization**: Log-barrier methods, logarithmic objectives
373/// - **Automatic Differentiation**: Logarithmic derivatives
374/// - **Information Theory**: Mutual information, KL divergence
375///
376/// # Note on Negative Values
377///
378/// Natural logarithm of negative numbers is undefined in real arithmetic.
379/// The function will return NaN for negative inputs, following IEEE 754 standard.
380///
381/// ```
382/// use scirs2_core::ndarray::array;
383/// use scirs2_core::ndarray_ext::elementwise::ln_simd;
384///
385/// let x = array![-1.0_f64];
386/// let result = ln_simd(&x.view());
387/// assert!(result[0].is_nan());
388/// ```
389pub fn ln_simd<F>(x: &ArrayView1<F>) -> Array1<F>
390where
391    F: Float + SimdUnifiedOps,
392{
393    if x.is_empty() {
394        return Array1::zeros(0);
395    }
396    let optimizer = AutoOptimizer::new();
397    if optimizer.should_use_simd(x.len()) {
398        return F::simd_ln(x);
399    }
400    x.mapv(|val| val.ln())
401}
402/// Compute the sine of each element (SIMD-accelerated).
403///
404/// Computes sin(x) for each element in the array.
405///
406/// # Arguments
407///
408/// * `x` - Input 1D array (angles in radians)
409///
410/// # Returns
411///
412/// `Array1<F>` with the same length as input, with sine values.
413///
414/// # Performance
415///
416/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
417/// - **Speedup**: 2-4x on large arrays via auto-vectorization
418///
419/// # Mathematical Definition
420///
421/// ```text
422/// sin(x) = opposite/hypotenuse in a right triangle
423/// Periodic with period 2Ï€: sin(x + 2Ï€) = sin(x)
424/// Range: [-1, 1]
425/// ```
426///
427/// # Examples
428///
429/// ```
430/// use scirs2_core::ndarray::array;
431/// use scirs2_core::ndarray_ext::elementwise::sin_simd;
432/// use std::f64::consts::PI;
433///
434/// let x = array![0.0_f64, PI/6.0, PI/4.0, PI/2.0, PI];
435/// let result = sin_simd(&x.view());
436///
437/// // sin(0) = 0, sin(π/2) = 1, sin(π) ≈ 0
438/// ```
439///
440/// # Edge Cases
441///
442/// - **Empty array**: Returns empty array
443/// - **Zero**: sin(0) = 0
444/// - **NaN**: Returns NaN (preserves NaN)
445/// - **Infinity**: Returns NaN (undefined for infinity)
446///
447/// # Applications
448///
449/// - **Signal Processing**: Wave generation, modulation, Fourier analysis
450/// - **Computer Graphics**: Rotation matrices, smooth animations
451/// - **Physics Simulations**: Oscillations, wave propagation
452/// - **Audio**: Synthesizers, tone generation
453/// - **Robotics**: Trajectory planning, inverse kinematics
454pub fn sin_simd<F>(x: &ArrayView1<F>) -> Array1<F>
455where
456    F: Float + SimdUnifiedOps,
457{
458    if x.is_empty() {
459        return Array1::zeros(0);
460    }
461    let optimizer = AutoOptimizer::new();
462    if optimizer.should_use_simd(x.len()) {
463        return F::simd_sin(x);
464    }
465    x.mapv(|val| val.sin())
466}
467/// Compute the cosine of each element (SIMD-accelerated).
468///
469/// Computes cos(x) for each element in the array.
470///
471/// # Arguments
472///
473/// * `x` - Input 1D array (angles in radians)
474///
475/// # Returns
476///
477/// `Array1<F>` with the same length as input, with cosine values.
478///
479/// # Performance
480///
481/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
482/// - **Speedup**: 2-4x on large arrays via auto-vectorization
483///
484/// # Mathematical Definition
485///
486/// ```text
487/// cos(x) = adjacent/hypotenuse in a right triangle
488/// Periodic with period 2Ï€: cos(x + 2Ï€) = cos(x)
489/// Range: [-1, 1]
490/// ```
491///
492/// # Examples
493///
494/// ```
495/// use scirs2_core::ndarray::array;
496/// use scirs2_core::ndarray_ext::elementwise::cos_simd;
497/// use std::f64::consts::PI;
498///
499/// let x = array![0.0_f64, PI/3.0, PI/2.0, PI];
500/// let result = cos_simd(&x.view());
501///
502/// // cos(0) = 1, cos(π/2) ≈ 0, cos(π) = -1
503/// ```
504///
505/// # Edge Cases
506///
507/// - **Empty array**: Returns empty array
508/// - **Zero**: cos(0) = 1
509/// - **NaN**: Returns NaN (preserves NaN)
510/// - **Infinity**: Returns NaN (undefined for infinity)
511///
512/// # Applications
513///
514/// - **Computer Vision**: Rotation matrices, coordinate transformations
515/// - **Signal Processing**: Fourier transforms, filtering
516/// - **Path Planning**: Dubins curves, trajectory optimization
517/// - **Geometry**: Circle parametrization, spherical coordinates
518/// - **Neural Networks**: Positional encoding (transformers)
519pub fn cos_simd<F>(x: &ArrayView1<F>) -> Array1<F>
520where
521    F: Float + SimdUnifiedOps,
522{
523    if x.is_empty() {
524        return Array1::zeros(0);
525    }
526    let optimizer = AutoOptimizer::new();
527    if optimizer.should_use_simd(x.len()) {
528        return F::simd_cos(x);
529    }
530    x.mapv(|val| val.cos())
531}
532/// Compute the tangent of each element (SIMD-accelerated).
533///
534/// Computes tan(x) for each element in the array.
535///
536/// # Arguments
537///
538/// * `x` - Input 1D array (angles in radians)
539///
540/// # Returns
541///
542/// `Array1<F>` with the same length as input, with tangent values.
543///
544/// # Performance
545///
546/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
547/// - **Speedup**: 2-4x on large arrays via auto-vectorization
548///
549/// # Mathematical Definition
550///
551/// ```text
552/// tan(x) = sin(x) / cos(x)
553/// Periodic with period π: tan(x + π) = tan(x)
554/// Range: (-∞, ∞)
555/// ```
556///
557/// # Examples
558///
559/// ```
560/// use scirs2_core::ndarray::array;
561/// use scirs2_core::ndarray_ext::elementwise::tan_simd;
562/// use std::f64::consts::PI;
563///
564/// let x = array![0.0_f64, PI/4.0, PI/6.0];
565/// let result = tan_simd(&x.view());
566///
567/// // tan(0) = 0, tan(Ï€/4) = 1
568/// ```
569///
570/// # Edge Cases
571///
572/// - **Empty array**: Returns empty array
573/// - **Zero**: tan(0) = 0
574/// - **π/2, 3π/2, ...**: Returns ±infinity (undefined at cos(x)=0)
575/// - **NaN**: Returns NaN (preserves NaN)
576/// - **Infinity**: Returns NaN (undefined for infinity)
577///
578/// # Applications
579///
580/// - **Computer Graphics**: Perspective projection, field of view
581/// - **Navigation**: Bearing calculations, angle determination
582/// - **Physics**: Slope calculations, inclined planes
583/// - **Image Processing**: Gradient direction, edge angles
584/// - **Surveying**: Distance and height measurements
585///
586/// # Note on Singularities
587///
588/// Tangent has singularities at x = π/2 + nπ where n is any integer.
589/// At these points, cos(x) = 0 and tan(x) approaches ±infinity.
590pub fn tan_simd<F>(x: &ArrayView1<F>) -> Array1<F>
591where
592    F: Float + SimdUnifiedOps,
593{
594    if x.is_empty() {
595        return Array1::zeros(0);
596    }
597    let optimizer = AutoOptimizer::new();
598    if optimizer.should_use_simd(x.len()) {
599        return F::simd_tan(x);
600    }
601    x.mapv(|val| val.tan())
602}
603/// Compute the power of each element with a scalar exponent (SIMD-accelerated).
604///
605/// Computes base^exp for each element in the base array.
606///
607/// # Arguments
608///
609/// * `base` - Input 1D array of base values
610/// * `exp` - Scalar exponent value
611///
612/// # Returns
613///
614/// `Array1<F>` with the same length as input, with power values.
615///
616/// # Performance
617///
618/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
619/// - **Speedup**: 2-4x on large arrays via auto-vectorization
620///
621/// # Mathematical Definition
622///
623/// ```text
624/// powf(base, exp) = base^exp
625/// ```
626///
627/// # Examples
628///
629/// ```
630/// use scirs2_core::ndarray::array;
631/// use scirs2_core::ndarray_ext::elementwise::powf_simd;
632///
633/// let base = array![2.0_f64, 3.0, 4.0, 5.0];
634/// let result = powf_simd(&base.view(), 2.0);
635///
636/// // [4.0, 9.0, 16.0, 25.0]
637/// ```
638///
639/// # Edge Cases
640///
641/// - **Empty array**: Returns empty array
642/// - **x^0**: Returns 1 for any x (including 0^0 = 1 by convention)
643/// - **x^1**: Returns x
644/// - **0^negative**: Returns infinity
645/// - **negative^non-integer**: Returns NaN
646/// - **NaN**: Returns NaN (preserves NaN)
647///
648/// # Applications
649///
650/// - **Statistics**: Variance, standard deviation, moment calculations
651/// - **Machine Learning**: Polynomial features, L2 regularization
652/// - **Signal Processing**: Power spectral density, energy calculations
653/// - **Physics**: Kinetic energy, gravitational potential
654/// - **Finance**: Compound interest, exponential growth models
655pub fn powf_simd<F>(base: &ArrayView1<F>, exp: F) -> Array1<F>
656where
657    F: Float + SimdUnifiedOps,
658{
659    if base.is_empty() {
660        return Array1::zeros(0);
661    }
662    let optimizer = AutoOptimizer::new();
663    if optimizer.should_use_simd(base.len()) {
664        return F::simd_powf(base, exp);
665    }
666    base.mapv(|val| val.powf(exp))
667}
668/// Compute the element-wise power with array exponents (SIMD-accelerated).
669///
670/// Computes `base[i]^exp[i]` for each pair of elements.
671///
672/// # Arguments
673///
674/// * `base` - Input 1D array of base values
675/// * `exp` - Input 1D array of exponent values (must match base length)
676///
677/// # Returns
678///
679/// `Array1<F>` with the same length as inputs, with power values.
680///
681/// # Performance
682///
683/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
684/// - **Speedup**: 2-4x on large arrays via auto-vectorization
685///
686/// # Mathematical Definition
687///
688/// ```text
689/// pow(base, exp)[i] = base[i]^exp[i]
690/// ```
691///
692/// # Examples
693///
694/// ```
695/// use scirs2_core::ndarray::array;
696/// use scirs2_core::ndarray_ext::elementwise::pow_simd;
697///
698/// let base = array![2.0_f64, 3.0, 4.0, 5.0];
699/// let exp = array![2.0, 3.0, 2.0, 1.0];
700/// let result = pow_simd(&base.view(), &exp.view());
701///
702/// // [4.0, 27.0, 16.0, 5.0]
703/// ```
704///
705/// # Edge Cases
706///
707/// - **Empty arrays**: Returns empty array
708/// - **Mismatched lengths**: Panics (arrays must have same length)
709/// - **x^0**: Returns 1 for any x
710/// - **0^0**: Returns 1 by convention
711/// - **0^negative**: Returns infinity
712/// - **negative^non-integer**: Returns NaN
713/// - **NaN**: Returns NaN (preserves NaN)
714///
715/// # Applications
716///
717/// - **Machine Learning**: Custom activation functions, attention mechanisms
718/// - **Statistics**: Generalized power transformations
719/// - **Optimization**: Power-law scaling, Pareto distributions
720/// - **Signal Processing**: Non-linear transformations, compression
721/// - **Physics**: Variable exponent models, fractal dimensions
722pub fn pow_simd<F>(base: &ArrayView1<F>, exp: &ArrayView1<F>) -> Array1<F>
723where
724    F: Float + SimdUnifiedOps,
725{
726    assert_eq!(
727        base.len(),
728        exp.len(),
729        "Base and exponent arrays must have the same length"
730    );
731    if base.is_empty() {
732        return Array1::zeros(0);
733    }
734    let optimizer = AutoOptimizer::new();
735    if optimizer.should_use_simd(base.len()) {
736        return F::simd_pow(base, exp);
737    }
738    base.iter()
739        .zip(exp.iter())
740        .map(|(&b, &e)| b.powf(e))
741        .collect::<Vec<_>>()
742        .into()
743}
744/// Compute the hyperbolic sine of each element (SIMD-accelerated).
745///
746/// Computes sinh(x) for each element in the array.
747///
748/// # Arguments
749///
750/// * `x` - Input 1D array
751///
752/// # Returns
753///
754/// `Array1<F>` with the same length as input, with hyperbolic sine values.
755///
756/// # Performance
757///
758/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
759/// - **Speedup**: 2-4x on large arrays via auto-vectorization
760///
761/// # Mathematical Definition
762///
763/// ```text
764/// sinh(x) = (e^x - e^(-x)) / 2
765/// Range: (-∞, ∞)
766/// ```
767///
768/// # Examples
769///
770/// ```
771/// use scirs2_core::ndarray::array;
772/// use scirs2_core::ndarray_ext::elementwise::sinh_simd;
773///
774/// let x = array![0.0_f64, 1.0, -1.0];
775/// let result = sinh_simd(&x.view());
776///
777/// // sinh(0) = 0, sinh(1) ≈ 1.175, sinh(-1) ≈ -1.175
778/// assert!((result[0] - 0.0).abs() < 1e-10);
779/// assert!((result[1] - 1.1752011936).abs() < 1e-9);
780/// assert!((result[2] + 1.1752011936).abs() < 1e-9);
781/// ```
782///
783/// # Edge Cases
784///
785/// - **Empty array**: Returns empty array
786/// - **Zero**: sinh(0) = 0
787/// - **Large positive**: May overflow to infinity
788/// - **Large negative**: May overflow to negative infinity
789/// - **NaN**: Returns NaN (preserves NaN)
790///
791/// # Applications
792///
793/// - **Neural Networks**: Tanh activation (related via tanh = sinh/cosh)
794/// - **Numerical Integration**: Tanh-sinh quadrature
795/// - **Physics**: Catenary curves, special relativity
796/// - **Engineering**: Transmission line theory, heat transfer
797/// - **Mathematics**: Hyperbolic geometry, complex analysis
798pub fn sinh_simd<F>(x: &ArrayView1<F>) -> Array1<F>
799where
800    F: Float + SimdUnifiedOps,
801{
802    if x.is_empty() {
803        return Array1::zeros(0);
804    }
805    let optimizer = AutoOptimizer::new();
806    if optimizer.should_use_simd(x.len()) {
807        return F::simd_sinh(x);
808    }
809    x.mapv(|val| val.sinh())
810}
811/// Compute the hyperbolic cosine of each element (SIMD-accelerated).
812///
813/// Computes cosh(x) for each element in the array.
814///
815/// # Arguments
816///
817/// * `x` - Input 1D array
818///
819/// # Returns
820///
821/// `Array1<F>` with the same length as input, with hyperbolic cosine values.
822///
823/// # Performance
824///
825/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
826/// - **Speedup**: 2-4x on large arrays via auto-vectorization
827///
828/// # Mathematical Definition
829///
830/// ```text
831/// cosh(x) = (e^x + e^(-x)) / 2
832/// Range: [1, ∞) (always >= 1)
833/// ```
834///
835/// # Examples
836///
837/// ```
838/// use scirs2_core::ndarray::array;
839/// use scirs2_core::ndarray_ext::elementwise::cosh_simd;
840///
841/// let x = array![0.0_f64, 1.0, -1.0];
842/// let result = cosh_simd(&x.view());
843///
844/// // cosh(0) = 1, cosh(1) ≈ 1.543, cosh(-1) ≈ 1.543
845/// assert!((result[0] - 1.0).abs() < 1e-10);
846/// assert!((result[1] - 1.5430806348).abs() < 1e-9);
847/// assert!((result[2] - 1.5430806348).abs() < 1e-9);
848/// ```
849///
850/// # Edge Cases
851///
852/// - **Empty array**: Returns empty array
853/// - **Zero**: cosh(0) = 1
854/// - **Symmetric**: cosh(-x) = cosh(x)
855/// - **Large values**: May overflow to infinity
856/// - **NaN**: Returns NaN (preserves NaN)
857///
858/// # Applications
859///
860/// - **Neural Networks**: Activation functions, normalization
861/// - **Physics**: Wave propagation, special relativity
862/// - **Engineering**: Cable suspension, arch design
863/// - **Mathematics**: Hyperbolic identities (cosh² - sinh² = 1)
864/// - **Numerical Methods**: Stability analysis
865pub fn cosh_simd<F>(x: &ArrayView1<F>) -> Array1<F>
866where
867    F: Float + SimdUnifiedOps,
868{
869    if x.is_empty() {
870        return Array1::zeros(0);
871    }
872    let optimizer = AutoOptimizer::new();
873    if optimizer.should_use_simd(x.len()) {
874        return F::simd_cosh(x);
875    }
876    x.mapv(|val| val.cosh())
877}
878/// Compute the hyperbolic tangent of each element (SIMD-accelerated).
879///
880/// Computes tanh(x) for each element in the array.
881///
882/// # Arguments
883///
884/// * `x` - Input 1D array
885///
886/// # Returns
887///
888/// `Array1<F>` with the same length as input, with hyperbolic tangent values.
889///
890/// # Performance
891///
892/// - **Auto-vectorization**: Compiler optimizations provide excellent performance
893/// - **Speedup**: 2-4x on large arrays via auto-vectorization
894///
895/// # Mathematical Definition
896///
897/// ```text
898/// tanh(x) = sinh(x) / cosh(x) = (e^x - e^(-x)) / (e^x + e^(-x))
899/// Range: (-1, 1)
900/// ```
901///
902/// # Examples
903///
904/// ```ignore
905/// use scirs2_core::ndarray::array;
906/// use scirs2_core::ndarray_ext::elementwise::tanh_simd;
907///
908/// let x = array![0.0_f64, 1.0, -1.0, 10.0];
909/// let result = tanh_simd(&x.view());
910///
911/// // tanh(0) = 0, tanh(1) ≈ 0.762, tanh(-1) ≈ -0.762, tanh(∞) → 1
912/// assert!((result[0] - 0.0_f64).abs() < 1e-10);
913/// assert!((result[1] - 0.7615941559_f64).abs() < 1e-9);
914/// assert!((result[2] + 0.7615941559_f64).abs() < 1e-9);
915/// assert!((result[3] - 1.0_f64).abs() < 1e-9); // tanh(10) ≈ 1
916/// ```
917///
918/// # Edge Cases
919///
920/// - **Empty array**: Returns empty array
921/// - **Zero**: tanh(0) = 0
922/// - **Asymptotic**: tanh(x) → ±1 as x → ±∞
923/// - **Anti-symmetric**: tanh(-x) = -tanh(x)
924/// - **NaN**: Returns NaN (preserves NaN)
925///
926/// # Applications
927///
928/// - **Neural Networks**: Tanh activation function (classic activation)
929/// - **Machine Learning**: Gradient clipping, normalization layers
930/// - **Reinforcement Learning**: Policy networks, value functions
931/// - **Signal Processing**: Soft limiting, saturation
932/// - **Optimization**: Smooth approximation to sign function
933/// - **Physics**: Relativistic velocity addition
934///
935/// # Note on Neural Networks
936///
937/// Tanh was historically the most popular activation function before ReLU.
938/// It's still widely used in RNNs, LSTMs, and GRUs for gating mechanisms.
939/// Gradient: d/dx tanh(x) = 1 - tanh²(x) = sech²(x)
940pub fn tanh_simd<F>(x: &ArrayView1<F>) -> Array1<F>
941where
942    F: Float + SimdUnifiedOps,
943{
944    if x.is_empty() {
945        return Array1::zeros(0);
946    }
947    let optimizer = AutoOptimizer::new();
948    if optimizer.should_use_simd(x.len()) {
949        return F::simd_tanh(x);
950    }
951    x.mapv(|val| val.tanh())
952}
953/// Compute the floor (round down) of each element (SIMD-accelerated).
954///
955/// Computes the largest integer less than or equal to x for each element.
956///
957/// # Arguments
958///
959/// * `x` - Input 1D array
960///
961/// # Returns
962///
963/// `Array1<F>` with the same length as input, where each element is rounded down
964/// to the nearest integer.
965///
966/// # Performance
967///
968/// - **SIMD**: Automatically used for large arrays (1000+ elements)
969/// - **Scalar**: Used for small arrays or when SIMD is unavailable
970///
971/// # Mathematical Properties
972///
973/// - For any x: floor(x) <= x
974/// - floor(x) is the largest integer <= x
975/// - floor(-x) = -ceil(x)
976/// - floor(x) = x if x is already an integer
977///
978/// # Examples
979///
980/// ```
981/// use scirs2_core::ndarray::array;
982/// use scirs2_core::ndarray_ext::elementwise::floor_simd;
983///
984/// let x = array![1.2, 2.7, -1.3, -2.9, 3.0];
985/// let result = floor_simd(&x.view());
986/// // Result: [1.0, 2.0, -2.0, -3.0, 3.0]
987/// ```
988///
989/// # Applications
990///
991/// - **Binning**: Discretizing continuous values into bins
992/// - **Indexing**: Converting continuous coordinates to discrete indices
993/// - **Quantization**: Reducing precision for data compression
994/// - **Digital Signal Processing**: Sample rate conversion, downsampling
995/// - **Computer Graphics**: Pixel coordinate calculations
996/// - **Financial**: Rounding down monetary amounts
997///
998/// # See Also
999///
1000/// - `ceil_simd`: Round up to smallest integer >= x
1001/// - `round_simd`: Round to nearest integer
1002pub fn floor_simd<F>(x: &ArrayView1<F>) -> Array1<F>
1003where
1004    F: Float + SimdUnifiedOps,
1005{
1006    if x.is_empty() {
1007        return Array1::zeros(0);
1008    }
1009    let optimizer = AutoOptimizer::new();
1010    if optimizer.should_use_simd(x.len()) {
1011        return F::simd_floor(x);
1012    }
1013    x.mapv(|val| val.floor())
1014}