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}