numeric_array/
impls.rs

1//! Implementation notes
2//!
3//! For any method that returns a single element, like `ToPrimitive` methods and `Float::integer_decode`,
4//! the first element of the array will be used. If the array length is zero, `None` or zero is returned.
5//!
6//! For any method that accepts a single value, the same value is used across the entire operation. For example,
7//! `powi` will raise the power of every element by the given value.
8//!
9//! All floating point classification functions such as `is_finite`, `is_nan`, and `classify`, among others,
10//! follow a rule of highest importance. `NaN`s take precedence over `Infinite`, `Infinite` takes precedence over
11//! `Subnormal`, `Subnormal` takes precedence over `Normal`, `Normal` takes precedence over `Zero`
12//!
13//! This means that `classify` and `is_nan` will return `NaN`/true if any values are `NaN`,
14//! and `is_normal` will only return true when ALL values are normal.
15//!
16//! Additionally, similar rules are implemented for `is_sign_positive`/`is_positive` and `is_sign_negative`/`is_negative`, where `is_sign_positive` is
17//! true if all values are positive, but `is_sign_negative` is true when any value is negative.
18
19use super::*;
20
21use core::mem::{self, ManuallyDrop};
22use core::num::FpCategory;
23use core::ops::*;
24
25use num_traits::{float::FloatCore, *};
26
27use generic_array::internals::{ArrayConsumer, IntrusiveArrayBuilder};
28
29macro_rules! impl_unary_ops {
30    ($($op_trait:ident::$op:ident),*) => {
31        $(
32            impl<T, N: ArrayLength> $op_trait for NumericArray<T, N>
33            where
34                T: $op_trait,
35            {
36                type Output = NumericArray<<T as $op_trait>::Output, N>;
37
38                #[inline(always)]
39                fn $op(self) -> Self::Output {
40                    NumericArray(self.0.map($op_trait::$op))
41                }
42            }
43
44            impl<'a, T: Clone, N: ArrayLength> $op_trait for &'a NumericArray<T, N>
45            where
46                T: $op_trait,
47            {
48                type Output = NumericArray<<T as $op_trait>::Output, N>;
49
50                #[inline(always)]
51                fn $op(self) -> Self::Output {
52                    NumericArray((&self.0).map(|x| $op_trait::$op(x.clone())))
53                }
54            }
55        )*
56    }
57}
58
59macro_rules! impl_binary_ops {
60    ($($op_trait:ident::$op:ident),*) => {
61        $(
62            impl<T, U, N: ArrayLength> $op_trait<NumericArray<U, N>> for NumericArray<T, N>
63            where
64                T: $op_trait<U>,
65            {
66                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
67
68                #[inline(always)]
69                fn $op(self, rhs: NumericArray<U, N>) -> Self::Output {
70                    NumericArray(self.0.zip(rhs.0, $op_trait::$op))
71                }
72            }
73
74            impl<'a, T, U: Clone, N: ArrayLength> $op_trait<&'a NumericArray<U, N>> for NumericArray<T, N>
75            where
76                T: $op_trait<U>,
77            {
78                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
79
80                #[inline(always)]
81                fn $op(self, rhs: &'a NumericArray<U, N>) -> Self::Output {
82                    NumericArray(self.0.zip(&rhs.0, |l, r| $op_trait::$op(l, r.clone())))
83                }
84            }
85
86            impl<'a, T: Clone, U, N: ArrayLength> $op_trait<NumericArray<U, N>> for &'a NumericArray<T, N>
87            where
88                T: $op_trait<U>,
89            {
90                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
91
92                #[inline(always)]
93                fn $op(self, rhs: NumericArray<U, N>) -> Self::Output {
94                    NumericArray((&self.0).zip(rhs.0, |l, r| $op_trait::$op(l.clone(), r)))
95                }
96            }
97
98            impl<'a, 'b, T: Clone, U: Clone, N: ArrayLength> $op_trait<&'b NumericArray<U, N>> for &'a NumericArray<T, N>
99            where
100                T: $op_trait<U>,
101            {
102                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
103
104                #[inline(always)]
105                fn $op(self, rhs: &'b NumericArray<U, N>) -> Self::Output {
106                    NumericArray((&self.0).zip(&rhs.0, |l, r| $op_trait::$op(l.clone(), r.clone())))
107                }
108            }
109
110            impl<T, U: Clone, N: ArrayLength> $op_trait<NumericConstant<U>> for NumericArray<T, N>
111            where
112                T: $op_trait<U>,
113            {
114                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
115
116                #[inline(always)]
117                fn $op(self, rhs: NumericConstant<U>) -> Self::Output {
118                    NumericArray(self.0.map(|l| $op_trait::$op(l, rhs.0.clone())))
119                }
120            }
121
122            impl<'a, T: Clone, U: Clone, N: ArrayLength> $op_trait<NumericConstant<U>> for &'a NumericArray<T, N>
123            where
124                T: $op_trait<U>,
125            {
126                type Output = NumericArray<<T as $op_trait<U>>::Output, N>;
127
128                #[inline(always)]
129                fn $op(self, rhs: NumericConstant<U>) -> Self::Output {
130                    NumericArray((&self.0).map(|l| $op_trait::$op(l.clone(), rhs.0.clone())))
131                }
132            }
133
134            impl<T, U: Clone, N: ArrayLength> $op_trait<NumericArray<T, N>> for NumericConstant<U>
135            where
136                U: $op_trait<T>,
137            {
138                type Output = NumericArray<<U as $op_trait<T>>::Output, N>;
139
140                #[inline(always)]
141                fn $op(self, rhs: NumericArray<T, N>) -> Self::Output {
142                    NumericArray(rhs.0.map(|r| $op_trait::$op(self.0.clone(), r)))
143                }
144            }
145
146            impl<'a, T: Clone, U: Clone, N: ArrayLength> $op_trait<&'a NumericArray<T, N>> for NumericConstant<U>
147            where
148                U: $op_trait<T>,
149            {
150                type Output = NumericArray<<U as $op_trait<T>>::Output, N>;
151
152                #[inline(always)]
153                fn $op(self, rhs: &'a NumericArray<T, N>) -> Self::Output {
154                    NumericArray((&rhs.0).map(|r| $op_trait::$op(self.0.clone(), r.clone())))
155                }
156            }
157        )*
158    }
159}
160
161macro_rules! impl_assign_ops {
162    ($($op_trait:ident::$op:ident),*) => {
163        $(
164            impl<T, U, N: ArrayLength> $op_trait<NumericArray<U, N>> for NumericArray<T, N>
165            where
166                T: $op_trait<U>,
167            {
168                fn $op(&mut self, rhs: NumericArray<U, N>) {
169                    if mem::needs_drop::<U>() {
170                        unsafe {
171                            let mut right = ArrayConsumer::new(rhs.0);
172
173                            let (right_iter, right_position) = right.iter_position();
174
175                            self.iter_mut().zip(right_iter).for_each(|(lhs, rhs)| {
176                                $op_trait::$op(lhs, ptr::read(rhs));
177
178                                *right_position += 1;
179                            });
180                        }
181                    } else {
182                        let right = ManuallyDrop::new(rhs);
183
184                        self.iter_mut().zip(right.iter()).for_each(|(lhs, rhs)| unsafe {
185                            $op_trait::$op(lhs, ptr::read(rhs));
186                        });
187                    }
188                }
189            }
190
191            impl<'a, T, U: Clone, N: ArrayLength> $op_trait<&'a NumericArray<U, N>> for NumericArray<T, N>
192            where
193                T: $op_trait<U>,
194            {
195                fn $op(&mut self, rhs: &'a NumericArray<U, N>) {
196                    self.iter_mut().zip(rhs.iter()).for_each(|(lhs, rhs)| {
197                        $op_trait::$op(lhs, rhs.clone());
198                    });
199                }
200            }
201
202            impl<T, U: Clone, N: ArrayLength> $op_trait<NumericConstant<U>> for NumericArray<T, N>
203            where
204                T: $op_trait<U>,
205            {
206                fn $op(&mut self, rhs: NumericConstant<U>) {
207                    self.iter_mut().for_each(|lhs| {
208                        $op_trait::$op(lhs, rhs.0.clone());
209                    });
210                }
211            }
212        )*
213    }
214}
215
216macro_rules! impl_wrapping_ops {
217    ($($op_trait:ident::$op:ident),*) => {
218        $(
219            impl<T, N: ArrayLength> num_traits::$op_trait for NumericArray<T, N>
220            where
221                T: num_traits::$op_trait,
222            {
223                fn $op(&self, rhs: &Self) -> Self {
224                    NumericArray((&self.0).zip(&rhs.0, num_traits::$op_trait::$op))
225                }
226            }
227        )*
228    }
229}
230
231macro_rules! impl_checked_ops {
232    ($($op_trait:ident::$op:ident),*) => {
233        $(
234            impl<T, N: ArrayLength> $op_trait for NumericArray<T, N>
235            where
236                T: $op_trait,
237            {
238                fn $op(&self, rhs: &Self) -> Option<Self> {
239                    unsafe {
240                        let mut array = GenericArray::uninit();
241                        let mut builder = IntrusiveArrayBuilder::new(&mut array);
242
243                        {
244                            let (array_iter, position) = builder.iter_position();
245
246                            for (dst, (lhs, rhs)) in array_iter.zip(self.iter().zip(rhs.iter())) {
247                                if let Some(value) = $op_trait::$op(lhs, rhs) {
248                                    dst.write(value);
249                                    *position += 1;
250                                } else {
251                                    return None;
252                                }
253                            }
254                        }
255
256                        Some(NumericArray({
257                            builder.finish();
258                            IntrusiveArrayBuilder::array_assume_init(array)
259                        }))
260                    }
261                }
262            }
263        )*
264    }
265}
266
267macro_rules! impl_float_const {
268    ($($f:ident),*) => {
269        impl<T, N: ArrayLength> FloatConst for NumericArray<T, N>
270        where
271            T: FloatConst,
272        {
273            $(
274                fn $f() -> Self {
275                    NumericArray(GenericArray::generate(|_| <T as FloatConst>::$f()))
276                }
277            )*
278        }
279    }
280}
281
282impl_unary_ops! {
283    Inv::inv, // num_traits
284    Neg::neg,
285    Not::not
286}
287
288impl_binary_ops! {
289    Pow::pow, // num_traits
290    Add::add,
291    Sub::sub,
292    Mul::mul,
293    Div::div,
294    Rem::rem,
295    BitAnd::bitand,
296    BitOr::bitor,
297    BitXor::bitxor,
298    Shr::shr,
299    Shl::shl
300}
301
302impl_assign_ops! {
303    AddAssign::add_assign,
304    SubAssign::sub_assign,
305    MulAssign::mul_assign,
306    DivAssign::div_assign,
307    RemAssign::rem_assign,
308    BitAndAssign::bitand_assign,
309    BitOrAssign::bitor_assign,
310    BitXorAssign::bitxor_assign,
311    ShrAssign::shr_assign,
312    ShlAssign::shl_assign
313}
314
315impl_wrapping_ops! {
316    WrappingAdd::wrapping_add,
317    WrappingSub::wrapping_sub,
318    WrappingMul::wrapping_mul
319}
320
321impl_checked_ops! {
322    CheckedAdd::checked_add,
323    CheckedSub::checked_sub,
324    CheckedMul::checked_mul,
325    CheckedDiv::checked_div
326}
327
328impl<T, N: ArrayLength> CheckedShl for NumericArray<T, N>
329where
330    T: CheckedShl,
331    Self: Shl<u32, Output = Self>,
332{
333    fn checked_shl(&self, rhs: u32) -> Option<Self> {
334        unsafe {
335            let mut array = GenericArray::uninit();
336            let mut builder = IntrusiveArrayBuilder::new(&mut array);
337
338            {
339                let (builder_iter, builder_position) = builder.iter_position();
340
341                for (dst, lhs) in builder_iter.zip(self.iter()) {
342                    if let Some(value) = CheckedShl::checked_shl(lhs, rhs) {
343                        dst.write(value);
344                        *builder_position += 1;
345                    } else {
346                        return None;
347                    }
348                }
349            }
350
351            Some(NumericArray({
352                builder.finish();
353                IntrusiveArrayBuilder::array_assume_init(array)
354            }))
355        }
356    }
357}
358
359impl<T, N: ArrayLength> CheckedShr for NumericArray<T, N>
360where
361    T: CheckedShr,
362    Self: Shr<u32, Output = Self>,
363{
364    fn checked_shr(&self, rhs: u32) -> Option<Self> {
365        unsafe {
366            let mut array = GenericArray::uninit();
367            let mut builder = IntrusiveArrayBuilder::new(&mut array);
368
369            {
370                let (builder_iter, builder_position) = builder.iter_position();
371
372                for (dst, lhs) in builder_iter.zip(self.iter()) {
373                    if let Some(value) = CheckedShr::checked_shr(lhs, rhs) {
374                        dst.write(value);
375                        *builder_position += 1;
376                    } else {
377                        return None;
378                    }
379                }
380            }
381
382            Some(NumericArray({
383                builder.finish();
384                IntrusiveArrayBuilder::array_assume_init(array)
385            }))
386        }
387    }
388}
389
390impl_float_const!(
391    E,
392    FRAC_1_PI,
393    FRAC_1_SQRT_2,
394    FRAC_2_PI,
395    FRAC_2_SQRT_PI,
396    FRAC_PI_2,
397    FRAC_PI_3,
398    FRAC_PI_4,
399    FRAC_PI_6,
400    FRAC_PI_8,
401    LN_10,
402    LN_2,
403    LOG10_E,
404    LOG2_E,
405    PI,
406    SQRT_2
407);
408
409impl<T, N: ArrayLength> Zero for NumericArray<T, N>
410where
411    T: Zero,
412{
413    fn zero() -> Self {
414        NumericArray(GenericArray::generate(|_| <T as Zero>::zero()))
415    }
416
417    fn is_zero(&self) -> bool {
418        self.iter().all(|x| x.is_zero())
419    }
420}
421
422impl<T, N: ArrayLength> One for NumericArray<T, N>
423where
424    T: One,
425{
426    fn one() -> Self {
427        NumericArray(GenericArray::generate(|_| <T as One>::one()))
428    }
429}
430
431impl<T, N: ArrayLength> Saturating for NumericArray<T, N>
432where
433    T: Saturating,
434{
435    fn saturating_add(self, rhs: Self) -> Self {
436        NumericArray(self.0.zip(rhs.0, Saturating::saturating_add))
437    }
438
439    fn saturating_sub(self, rhs: Self) -> Self {
440        NumericArray(self.0.zip(rhs.0, Saturating::saturating_sub))
441    }
442}
443
444impl<T: Clone, N: ArrayLength> Num for NumericArray<T, N>
445where
446    T: Num,
447{
448    type FromStrRadixErr = <T as Num>::FromStrRadixErr;
449
450    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
451        <T as Num>::from_str_radix(str, radix).map(Self::splat)
452    }
453}
454
455impl<T: Clone, N: ArrayLength> Signed for NumericArray<T, N>
456where
457    T: Signed,
458{
459    fn abs(&self) -> Self {
460        NumericArray((&self.0).map(Signed::abs))
461    }
462
463    fn abs_sub(&self, rhs: &Self) -> Self {
464        NumericArray((&self.0).zip(&rhs.0, Signed::abs_sub))
465    }
466
467    fn signum(&self) -> Self {
468        NumericArray((&self.0).map(Signed::signum))
469    }
470
471    fn is_positive(&self) -> bool {
472        self.iter().all(Signed::is_positive)
473    }
474
475    fn is_negative(&self) -> bool {
476        self.iter().any(Signed::is_negative)
477    }
478}
479
480impl<T: Clone, N: ArrayLength> Unsigned for NumericArray<T, N> where T: Unsigned {}
481
482impl<T, N: ArrayLength> Bounded for NumericArray<T, N>
483where
484    T: Bounded,
485{
486    fn min_value() -> Self {
487        NumericArray(GenericArray::generate(|_| <T as Bounded>::min_value()))
488    }
489
490    fn max_value() -> Self {
491        NumericArray(GenericArray::generate(|_| <T as Bounded>::max_value()))
492    }
493}
494
495macro_rules! impl_to_primitive {
496    ($($to:ident => $prim:ty),*) => {
497        impl<T, N: ArrayLength> ToPrimitive for NumericArray<T, N>
498        where
499            T: ToPrimitive,
500        {
501            $(
502                #[inline]
503                fn $to(&self) -> Option<$prim> {
504                    if N::to_usize() == 0 { None } else {
505                        self.first().and_then(ToPrimitive::$to)
506                    }
507                }
508            )*
509        }
510    }
511}
512
513impl_to_primitive! {
514    to_i8       => i8,
515    to_i16      => i16,
516    to_i32      => i32,
517    to_i64      => i64,
518    to_i128     => i128,
519    to_isize    => isize,
520
521    to_u8       => u8,
522    to_u16      => u16,
523    to_u32      => u32,
524    to_u64      => u64,
525    to_u128     => u128,
526    to_usize    => usize,
527
528    to_f32      => f32,
529    to_f64      => f64
530}
531
532impl<T, N: ArrayLength> NumCast for NumericArray<T, N>
533where
534    T: NumCast + Clone,
535{
536    fn from<P: ToPrimitive>(n: P) -> Option<Self> {
537        T::from(n).map(Self::splat)
538    }
539}
540
541macro_rules! impl_float {
542    ($float:ident { $($extra:tt)* }) => {
543        impl<T, N: ArrayLength> $float for NumericArray<T, N>
544        where
545            T: $float,
546            Self: Copy,
547        {
548            $($extra)*
549
550            #[inline]
551            fn nan() -> Self {
552                Self::splat($float::nan())
553            }
554
555            #[inline]
556            fn infinity() -> Self {
557                Self::splat($float::infinity())
558            }
559
560            #[inline]
561            fn neg_infinity() -> Self {
562                Self::splat($float::neg_infinity())
563            }
564
565            #[inline]
566            fn neg_zero() -> Self {
567                Self::splat($float::neg_zero())
568            }
569
570            #[inline]
571            fn min_value() -> Self {
572                Self::splat($float::min_value())
573            }
574
575            #[inline]
576            fn min_positive_value() -> Self {
577                Self::splat($float::min_positive_value())
578            }
579
580            #[inline]
581            fn max_value() -> Self {
582                Self::splat($float::max_value())
583            }
584
585            #[inline]
586            fn is_nan(self) -> bool {
587                self.iter().any(|x| $float::is_nan(*x))
588            }
589
590            #[inline]
591            fn is_infinite(self) -> bool {
592                self.iter().any(|x| $float::is_infinite(*x))
593            }
594
595            #[inline]
596            fn is_finite(self) -> bool {
597                self.iter().all(|x| $float::is_finite(*x))
598            }
599
600            #[inline]
601            fn is_normal(self) -> bool {
602                self.iter().all(|x| $float::is_normal(*x))
603            }
604
605            #[inline]
606            fn epsilon() -> Self {
607                Self::splat($float::epsilon())
608            }
609
610            #[inline]
611            fn to_degrees(self) -> Self {
612                self.0.map($float::to_degrees).into()
613            }
614
615            #[inline]
616            fn to_radians(self) -> Self {
617                self.0.map($float::to_radians).into()
618            }
619
620            #[inline]
621            fn integer_decode(self) -> (u64, i16, i8) {
622                if N::to_usize() == 0 {
623                    (0, 0, 0)
624                } else {
625                    self.first().unwrap().integer_decode()
626                }
627            }
628
629            fn classify(self) -> FpCategory {
630                let mut ret = FpCategory::Zero;
631
632                for x in self.iter() {
633                    match $float::classify(*x) {
634                        // If NaN is found, return NaN immediately
635                        FpCategory::Nan => return FpCategory::Nan,
636                        // If infinite, set infinite
637                        FpCategory::Infinite => ret = FpCategory::Infinite,
638                        // If Subnormal and not infinite, set subnormal
639                        FpCategory::Subnormal if ret != FpCategory::Infinite => {
640                            ret = FpCategory::Subnormal;
641                        }
642                        // If normal and zero, upgrade to normal
643                        FpCategory::Normal if ret == FpCategory::Zero => {
644                            ret = FpCategory::Normal;
645                        }
646                        _ => {}
647                    }
648                }
649
650                ret
651            }
652
653            #[inline]
654            fn floor(self) -> Self {
655                self.0.map($float::floor).into()
656            }
657
658            #[inline]
659            fn ceil(self) -> Self {
660                self.0.map($float::ceil).into()
661            }
662
663            #[inline]
664            fn round(self) -> Self {
665                self.0.map($float::round).into()
666            }
667
668            #[inline]
669            fn trunc(self) -> Self {
670                self.0.map($float::trunc).into()
671            }
672
673            #[inline]
674            fn fract(self) -> Self {
675                self.0.map($float::fract).into()
676            }
677
678            #[inline]
679            fn abs(self) -> Self {
680                self.0.map($float::abs).into()
681            }
682
683            #[inline]
684            fn signum(self) -> Self {
685                self.0.map($float::signum).into()
686            }
687
688            #[inline]
689            fn is_sign_positive(self) -> bool {
690                self.iter().all(|x| $float::is_sign_positive(*x))
691            }
692
693            #[inline]
694            fn is_sign_negative(self) -> bool {
695                self.iter().any(|x| $float::is_sign_negative(*x))
696            }
697
698            #[inline]
699            fn max(self, other: Self) -> Self {
700                self.0.zip(other.0, $float::max).into()
701            }
702
703            #[inline]
704            fn min(self, other: Self) -> Self {
705                self.0.zip(other.0, $float::min).into()
706            }
707
708            #[inline]
709            fn recip(self) -> Self {
710                self.0.map($float::recip).into()
711            }
712
713            #[inline]
714            fn powi(self, n: i32) -> Self {
715                self.0.map(|x| $float::powi(x, n)).into()
716
717                // This was a prototype with the best performance that
718                // still fell short of whatever the compiler does, sadly.
719                //
720                // let mut e = n as i64;
721                // let mut x = self;
722                // let mut res = Self::one();
723                // if e < 0 {
724                //     x = x.recip();
725                //     e = -e;
726                // }
727                // while e != 0 {
728                //     if e & 1 != 0 {
729                //         res *= x;
730                //     }
731                //     e >>= 1;
732                //     x *= x;
733                // }
734                // res
735            }
736        }
737    };
738}
739
740impl_float!(FloatCore {});
741
742#[cfg(feature = "std")]
743impl_float!(Float {
744    #[inline]
745    fn mul_add(self, a: Self, b: Self) -> Self {
746        if mem::needs_drop::<T>() {
747            unsafe {
748                let mut left = ArrayConsumer::new(self.0);
749                let mut a_arr = ArrayConsumer::new(a.0);
750                let mut b_arr = ArrayConsumer::new(b.0);
751
752                let (left_iter, left_position) = left.iter_position();
753                let (a_arr_iter, a_arr_position) = a_arr.iter_position();
754                let (b_arr_iter, b_arr_position) = b_arr.iter_position();
755
756                NumericArray::from_iter(left_iter.zip(a_arr_iter.zip(b_arr_iter)).map(|(l, (a, b))| {
757                    let l = ptr::read(l);
758                    let a = ptr::read(a);
759                    let b = ptr::read(b);
760
761                    *left_position += 1;
762                    *a_arr_position = *left_position;
763                    *b_arr_position = *left_position;
764
765                    Float::mul_add(l, a, b)
766                }))
767            }
768        } else {
769            let left = ManuallyDrop::new(self);
770            let a = ManuallyDrop::new(a);
771            let b = ManuallyDrop::new(b);
772
773            NumericArray::from_iter(left.iter().zip(a.iter()).zip(b.iter()).map(|((l, a), b)| unsafe {
774                Float::mul_add(ptr::read(l), ptr::read(a), ptr::read(b)) //
775            }))
776        }
777    }
778
779    #[inline]
780    fn powf(self, n: Self) -> Self {
781        self.0.zip(n.0, Float::powf).into()
782    }
783
784    #[inline]
785    fn sqrt(self) -> Self {
786        self.0.map(Float::sqrt).into()
787    }
788
789    #[inline]
790    fn exp(self) -> Self {
791        self.0.map(Float::exp).into()
792    }
793
794    #[inline]
795    fn exp2(self) -> Self {
796        self.0.map(Float::exp2).into()
797    }
798
799    #[inline]
800    fn ln(self) -> Self {
801        self.0.map(Float::ln).into()
802    }
803
804    #[inline]
805    fn log(self, base: Self) -> Self {
806        self.0.zip(base.0, Float::log).into()
807    }
808
809    #[inline]
810    fn log2(self) -> Self {
811        self.0.map(Float::log2).into()
812    }
813
814    #[inline]
815    fn log10(self) -> Self {
816        self.0.map(Float::log10).into()
817    }
818
819    #[inline]
820    fn abs_sub(self, other: Self) -> Self {
821        self.0.zip(other.0, Float::abs_sub).into()
822    }
823
824    #[inline]
825    fn cbrt(self) -> Self {
826        self.0.map(Float::cbrt).into()
827    }
828
829    #[inline]
830    fn hypot(self, other: Self) -> Self {
831        self.0.zip(other.0, Float::hypot).into()
832    }
833
834    #[inline]
835    fn sin(self) -> Self {
836        self.0.map(Float::sin).into()
837    }
838
839    #[inline]
840    fn cos(self) -> Self {
841        self.0.map(Float::cos).into()
842    }
843
844    #[inline]
845    fn tan(self) -> Self {
846        self.0.map(Float::tan).into()
847    }
848
849    #[inline]
850    fn asin(self) -> Self {
851        self.0.map(Float::asin).into()
852    }
853
854    #[inline]
855    fn acos(self) -> Self {
856        self.0.map(Float::acos).into()
857    }
858
859    #[inline]
860    fn atan(self) -> Self {
861        self.0.map(Float::atan).into()
862    }
863
864    #[inline]
865    fn atan2(self, other: Self) -> Self {
866        self.0.zip(other.0, Float::atan2).into()
867    }
868
869    #[inline]
870    fn sin_cos(self) -> (Self, Self) {
871        let mut sin_array = GenericArray::uninit();
872        let mut cos_array = GenericArray::uninit();
873
874        let mut sin_destination = IntrusiveArrayBuilder::new(&mut sin_array);
875        let mut cos_destination = IntrusiveArrayBuilder::new(&mut cos_array);
876
877        if mem::needs_drop::<T>() {
878            unsafe {
879                let mut source = ArrayConsumer::new(self.0);
880
881                let (source_iter, source_position) = source.iter_position();
882
883                {
884                    let (sin_destination_iter, sin_destination_position) = sin_destination.iter_position();
885                    let (cos_destination_iter, cos_destination_position) = cos_destination.iter_position();
886
887                    sin_destination_iter
888                        .zip(cos_destination_iter)
889                        .zip(source_iter)
890                        .for_each(|((sin, cos), src)| {
891                            let x = ptr::read(src);
892
893                            *source_position += 1;
894
895                            let (s, c) = Float::sin_cos(x);
896
897                            sin.write(s);
898                            cos.write(c);
899
900                            *sin_destination_position = *source_position;
901                            *cos_destination_position = *source_position;
902                        });
903                }
904            }
905        } else {
906            unsafe {
907                let (sin_destination_iter, _) = sin_destination.iter_position();
908                let (cos_destination_iter, _) = cos_destination.iter_position();
909
910                sin_destination_iter
911                    .zip(cos_destination_iter)
912                    .zip(self.iter())
913                    .for_each(|((sin, cos), src)| {
914                        let (s, c) = Float::sin_cos(ptr::read(src));
915
916                        sin.write(s);
917                        cos.write(c);
918                    });
919            }
920        }
921
922        (
923            NumericArray::new(unsafe { sin_destination.finish(); IntrusiveArrayBuilder::array_assume_init(sin_array) }),
924            NumericArray::new(unsafe { cos_destination.finish(); IntrusiveArrayBuilder::array_assume_init(cos_array) }),
925        )
926    }
927
928    #[inline]
929    fn exp_m1(self) -> Self {
930        self.0.map(Float::exp_m1).into()
931    }
932
933    #[inline]
934    fn ln_1p(self) -> Self {
935        self.0.map(Float::ln_1p).into()
936    }
937
938    #[inline]
939    fn sinh(self) -> Self {
940        self.0.map(Float::sinh).into()
941    }
942
943    #[inline]
944    fn cosh(self) -> Self {
945        self.0.map(Float::cosh).into()
946    }
947
948    #[inline]
949    fn tanh(self) -> Self {
950        self.0.map(Float::tanh).into()
951    }
952
953    #[inline]
954    fn asinh(self) -> Self {
955        self.0.map(Float::asinh).into()
956    }
957
958    #[inline]
959    fn acosh(self) -> Self {
960        self.0.map(Float::acosh).into()
961    }
962
963    #[inline]
964    fn atanh(self) -> Self {
965        self.0.map(Float::atanh).into()
966    }
967});