arr_rs/math/operations/
floating.rs

1use crate::{
2    core::prelude::*,
3    errors::prelude::*,
4    extensions::prelude::*,
5    numeric::prelude::*,
6};
7
8/// `ArrayTrait` - Array Floating functions
9pub trait ArrayFloating<N: Floating> where Self: Sized + Clone {
10
11    /// Returns element-wise True where signbit is set (less than zero)
12    ///
13    /// # Examples
14    ///
15    /// ```
16    /// use arr_rs::prelude::*;
17    ///
18    /// let arr = Array::flat(vec![1., -2., -3., 4.]);
19    /// assert_eq!(Array::flat(vec![false, true, true, false]), arr.signbit());
20    /// ```
21    ///
22    /// # Errors
23    ///
24    /// may returns `ArrayError`
25    fn signbit(&self) -> Result<Array<bool>, ArrayError>;
26
27    /// Change the sign of x1 to that of x2, element-wise
28    ///
29    /// # Arguments
30    ///
31    /// * `other` - array to copy sign from
32    ///
33    /// # Examples
34    ///
35    /// ```
36    /// use arr_rs::prelude::*;
37    ///
38    /// let arr = Array::flat(vec![1., -2., -3., 4.]);
39    /// let other = Array::flat(vec![-1., 2., -3., 4.]);
40    /// assert_eq!(Array::flat(vec![-1., 2., -3., 4.]), arr.copysign(&other.unwrap()));
41    /// ```
42    ///
43    /// # Errors
44    ///
45    /// may returns `ArrayError`
46    fn copysign(&self, other: &Array<N>) -> Result<Array<N>, ArrayError>;
47
48    /// Decompose the elements of x into man and twos exp
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// use arr_rs::prelude::*;
54    ///
55    /// let arr = Array::arange(0., 8., None);
56    /// let result = arr.frexp().unwrap();
57    /// assert_eq!(Array::flat(vec![0., 0.5, 0.5, 0.75, 0.5, 0.625, 0.75, 0.875, 0.5]).unwrap(), result.0);
58    /// assert_eq!(Array::flat(vec![0, 1, 2, 2, 3, 3, 3, 3, 4]).unwrap(), result.1);
59    /// ```
60    ///
61    /// # Errors
62    ///
63    /// may returns `ArrayError`
64    fn frexp(&self) -> Result<(Array<N>, Array<i32>), ArrayError>;
65
66    /// Returns x1 * 2**x2, element-wise. Inverse of frexp
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use arr_rs::prelude::*;
72    ///
73    /// let arr = Array::flat(vec![0., 0.5, 0.5, 0.75, 0.5, 0.625, 0.75, 0.875, 0.5]);
74    /// let other = Array::flat(vec![0, 1, 2, 2, 3, 3, 3, 3, 4]);
75    /// assert_eq!(Array::arange(0., 8., None), arr.ldexp(&other.unwrap()));
76    /// ```
77    ///
78    /// # Errors
79    ///
80    /// may returns `ArrayError`
81    fn ldexp(&self, other: &Array<i32>) -> Result<Array<N>, ArrayError>;
82
83    /// Return the next floating-point value after x1 towards x2, element-wise
84    ///
85    /// # Examples
86    ///
87    /// ```
88    /// use arr_rs::prelude::*;
89    ///
90    /// let expected = Array::flat(vec![1. + f64::EPSILON, 2. - f64::EPSILON]);
91    /// assert_eq!(expected, Array::flat(vec![1., 2.]).nextafter(&Array::flat(vec![2., 1.]).unwrap()));
92    /// ```
93    ///
94    /// # Errors
95    ///
96    /// may returns `ArrayError`
97    fn nextafter(&self, other: &Array<N>) -> Result<Array<N>, ArrayError>;
98
99    /// Return the distance between x and the nearest adjacent number
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use arr_rs::prelude::*;
105    ///
106    /// assert_eq!(Array::flat(vec![f64::EPSILON, f64::EPSILON * 2.]), Array::flat(vec![1., 2.]).spacing());
107    /// ```
108    ///
109    /// # Errors
110    ///
111    /// may returns `ArrayError`
112    fn spacing(&self) -> Result<Array<N>, ArrayError>;
113}
114
115impl <N: Floating> ArrayFloating<N> for Array<N> {
116
117    fn signbit(&self) -> Result<Array<bool>, ArrayError> {
118        self.map(|e| e.to_f64().is_sign_negative())
119    }
120
121    fn copysign(&self, other: &Self) -> Result<Self, ArrayError> {
122        self.zip(other)?
123            .map(|item| N::from(item.0.to_f64().copysign(item.1.to_f64())))
124    }
125
126    fn frexp(&self) -> Result<(Self, Array<i32>), ArrayError> {
127
128        fn _frexp(x: f64) -> (f64, i32) {
129            let sign = x.signum();
130            let mut x = x.abs();
131            let mut sig: f64 = 0.0;
132            let mut exp: i32 = 0;
133            if x == 0.0 { return (sig, exp); }
134
135            while x >= 1.0 { x /= 2.0; exp += 1; }
136            while x < 0.5 { x *= 2.0; exp -= 1; }
137
138            sig = x;
139            (sig * sign, exp)
140        }
141
142        let mut man = vec![];
143        let mut exp = vec![];
144
145        self.for_each(|item| {
146            let result = _frexp(item.to_f64());
147            man.push(N::from(result.0));
148            exp.push(result.1);
149        })?;
150
151        Ok((
152            man.to_array().reshape(&self.get_shape()?)?,
153            exp.to_array().reshape(&self.get_shape()?)?,
154        ))
155    }
156
157    fn ldexp(&self, other: &Array<i32>) -> Result<Self, ArrayError> {
158
159        fn _ldexp(x: f64, exp: i32) -> f64 {
160            if x == 0. { return x }
161            let mut exp = exp;
162            let mut sig = x;
163
164            while exp > 0 { sig *= 2.; exp -= 1; }
165            while exp < 0 { sig /= 2.; exp += 1; }
166
167            sig
168        }
169
170        self.zip(other)?
171            .map(|item| N::from(_ldexp(item.0.to_f64(), item.1)))
172    }
173
174    fn nextafter(&self, other: &Self) -> Result<Self, ArrayError> {
175
176        fn _nextafter(x: f64, y: f64) -> f64 {
177            if (x - y).abs() < 1e-24 { x }
178            else if x < y { x + f64::EPSILON }
179            else { x - f64::EPSILON }
180        }
181
182        self.zip(other)?
183            .map(|item| N::from(_nextafter(item.0.to_f64(), item.1.to_f64())))
184    }
185
186    fn spacing(&self) -> Result<Self, ArrayError> {
187
188        fn _spacing(x: f64) -> f64 {
189            let bits = x.to_bits();
190            let next =
191                if x.is_sign_negative() { bits - 1 }
192                else { bits + 1 };
193            f64::from_bits(next) - x
194        }
195
196        self.map(|item| N::from(_spacing(item.to_f64())))
197    }
198}
199
200impl <N: Floating> ArrayFloating<N> for Result<Array<N>, ArrayError> {
201
202    fn signbit(&self) -> Result<Array<bool>, ArrayError> {
203        self.clone()?.signbit()
204    }
205
206    fn copysign(&self, other: &Array<N>) -> Self {
207        self.clone()?.copysign(other)
208    }
209
210    fn frexp(&self) -> Result<(Array<N>, Array<i32>), ArrayError> {
211        self.clone()?.frexp()
212    }
213
214    fn ldexp(&self, other: &Array<i32>) -> Self {
215        self.clone()?.ldexp(other)
216    }
217
218    fn nextafter(&self, other: &Array<N>) -> Self {
219        self.clone()?.nextafter(other)
220    }
221
222    fn spacing(&self) -> Self {
223        self.clone()?.spacing()
224    }
225}