integer_array/utility.rs
1use fixed::traits::Fixed;
2
3/// Rase integer to an integer-valued power.
4/// base^power.
5pub fn powi( base:i32, power:usize ) -> i32 {
6 let mut temp:i32 = base;
7 for _i in 0..power-1 {
8 temp = temp*base;
9 }
10 return temp;
11}
12
13/// Rase float number to an integer-valued power.
14/// - `base^power`.
15pub fn fpowi<T>( base:T, power:usize ) -> T
16 where T: num::traits::float::FloatCore
17{
18 let mut temp:T = base;
19 for _i in 0..power-1 {
20 temp = temp*base;
21 }
22 return temp;
23}
24
25/// Rase fixed number to an integer-valued power.
26/// - `base^power`.
27pub fn fixed_powi<T>( base:T, power:usize ) -> T
28 where T: fixed::traits::Fixed
29{
30 let mut temp:T = base;
31 for _i in 0..power-1 {
32 temp = temp*base;
33 }
34 return temp;
35}
36
37/// Numerical square root of a fixed point scalar.
38/// Slow but acurate method.
39///
40/// ## Argument
41/// * `error` - The gratest allowed error in the result.
42///
43/// # Example
44///
45/// ```
46/// use fixed::{types::extra::U20, FixedI32};
47/// use integer_array::utility as util;
48/// let x = util::sqrt( FixedI32::<U20>::from_num(110), FixedI32::<U20>::from_num(0.025) );
49/// assert_eq!{ x.to_num::<f32>(), 10.488159f32 };
50/// ```
51pub fn sqrt<T>( item:T, error:T ) -> T
52 where T: fixed::traits::Fixed
53{
54 // Initial approximation
55 let mut root: T = item/T::from_num(2);
56 let mut y:T = T::from_num(1);
57 // Accuracy level
58 while error <= root - y
59 {
60 root = (root + y) / T::from_num(2);
61 y = item / root;
62 }
63 return root;
64}
65
66/// Calculate atan(y/x) using a polynomial approximation.
67/// Utilizes the following polynomial to estimate the angle θ \[radians\].
68///
69/// `atan(y,x) = ((y,x)+0.372003(y,x)^3) / (1+0.703384(y/x)^2 + 0.043562(y/x)^4)`
70///
71/// The method is accurat within 0.003 degrees when |θ|<=π/4.
72///
73/// \[1\] R. G. Lyons, Streamlining Digital Signal Processing, Second Etition, IEEE Press, 2012.
74///
75/// # Arguments
76///
77/// * `y` - Is the argument along the y or imaginary axis.
78/// * `x` - Is the argument along the x or real axis.
79///
80/// # Example
81///
82/// ```
83/// use integer_array::utility as util;
84/// let arg = util::atan2_precise_float( 0.6f32, 0.4f32 );
85/// assert_eq!{ arg, 0.98300606 };
86/// ```
87pub fn atan2_precise_float<T>( y:T, x:T ) -> T
88 where T: num::traits::float::FloatCore
89{
90 let division:T = y/x;
91 return ( (division) + T::from( 0.372003 ).unwrap()*fpowi(division, 3) )
92 / ( T::from( 1 ).unwrap() + T::from( 0.703384 ).unwrap()*fpowi(division, 2) + T::from(0.043562).unwrap()*fpowi( division , 4) );
93}
94
95
96/// Calculate atan(y/x) using a polynomial approximation.
97/// Utilizes the following polynomial to estimate the angle θ \[radians\].
98///
99/// `atan(y,x) = ((y,x)+0.372003(y,x)^3) / (1+0.703384(y/x)^2 + 0.043562(y/x)^4)`
100///
101/// The method is accurat within 0.003 degrees when |θ|<=π/4.
102///
103/// \[1\] R. G. Lyons, Streamlining Digital Signal Processing, Second Etition, IEEE Press, 2012.
104///
105/// # Arguments
106///
107/// * `y` - Is the argument along the y or imaginary axis.
108/// * `x` - Is the argument along the x or real axis.
109///
110/// # Example
111///
112/// ```
113/// use fixed::{types::extra::U28, FixedI32};
114/// use integer_array::utility as util;
115/// let arg = util::atan2_precise_fixed( FixedI32::<U28>::from_num(0.6), FixedI32::<U28>::from_num(0.4) );
116/// assert_eq!{ arg.to_num::<f32>(), 0.983006064 };
117/// ```
118pub fn atan2_precise_fixed<T>( y: T, x: T ) -> T
119 where T: Fixed
120{
121 let division: T = y/x;
122 return ( (division) + T::from_num(0.372003f32)*fixed_powi(division,3) )
123 / (T::from_num(1) + T::from_num(0.703384f32)*fixed_powi(division,2) + T::from_num(0.043562f32)*fixed_powi(division,4) );
124}
125
126/// Calculate atan(x) using a polynomial approximation.
127/// Utilizes the following polynomial to estimate the angle θ \[radians\].
128///
129/// `atan(x) = ((x)+0.372003(x)^3) / (1+0.703384(x)^2 + 0.043562(x)^4)`
130///
131/// The method is accurat within 0.003 degrees when |θ|<=π/4.
132///
133/// \[1\] R. G. Lyons, Streamlining Digital Signal Processing, Second Etition, IEEE Press, 2012.
134///
135/// # Arguments
136///
137/// * `y` - Is the argument along the y or imaginary axis.
138/// * `x` - Is the argument along the x or real axis.
139///
140/// # Example
141///
142/// ```
143/// use fixed::{types::extra::U28, FixedI32};
144/// use integer_array::utility as util;
145/// let arg = util::atan_precise_fixed( FixedI32::<U28>::from_num(0.6)/FixedI32::<U28>::from_num(0.4) );
146/// assert_eq!{ arg.to_num::<f32>(), 0.983006064 };
147/// ```
148pub fn atan_precise_fixed<T>( x: T ) -> T
149 where T: Fixed
150{
151 return ( (x) + T::from_num(0.372003f32)*fixed_powi(x,3) )
152 / (T::from_num(1) + T::from_num(0.703384f32)*fixed_powi(x,2) + T::from_num(0.043562f32)*fixed_powi(x,4) );
153}
154
155/*
156pub fn test_complex<T>( y: T, x: T ) -> num::complex::Complex<T>
157 where T: Fixed
158{
159 return num::complex::Complex::new(x, y);
160}
161*/
162
163#[cfg(test)]
164mod tests {
165 #[test]
166 fn powi() {
167 assert_eq!{super::powi(3,2), 9};
168 }
169 #[test]
170 fn fpowi() {
171 assert_eq!{super::fpowi(3.0,2), 9.0};
172 }
173}