mixed_num/complex/
ops.rs

1use super::*;
2
3/// Cast cartesian complex fixed point number to polar form.
4/// 
5/// ## Arguments
6/// 
7/// * `x` - The number transform.
8///
9pub fn to_polar<T>( x: Cartesian<T> ) -> Polar<T>
10    where T:  MixedNum + MixedNumSigned + MixedSqrt + MixedAtan + MixedPowi + MixedAbs + MixedOps
11{
12    let c_polar = Polar::<T>{
13        mag:     abs(x),
14        ang: x.im.mixed_atan2(x.re)
15    };
16    return c_polar;
17}
18
19/// Calculate the absolute value of the argument.
20/// 
21/// ## Arguments
22/// 
23/// * `a` - The argument to apply the function to.
24/// 
25/// ## Example
26/// 
27/// ```
28/// use mixed_num::Polar;
29/// use mixed_num::complex::*;
30/// 
31/// let mut x = Cartesian{re:1f32, im:0f32};
32/// assert_eq!{ abs(x), 1f32 };
33/// ``` 
34/// 
35pub fn abs<T>( a: Cartesian<T> ) -> T
36where T: MixedNum + MixedNumSigned + MixedSqrt + MixedPowi + MixedOps
37{
38    let r_sqr = a.re.mixed_powi(2) + a.im.mixed_powi(2);
39    return r_sqr.mixed_sqrt();
40}
41
42/// Cast cartesian complex fixed point number to polar form.
43/// 
44/// ## Arguments
45/// 
46/// * `a` - The number transform.
47/// 
48/// ## Example
49/// 
50/// ```
51/// use mixed_num::Polar;
52/// use mixed_num::complex::*;
53/// 
54/// let mut x = Polar::new(1f32, 0f32);
55/// assert_eq!{ to_cartesian(x).to_string(), "1+0i" };
56/// ``` 
57/// 
58pub fn to_cartesian<T>( a: Polar<T> ) -> Cartesian<T>
59    where T: MixedNum + MixedNumSigned + MixedTrigonometry + MixedWrapPhase + MixedOps
60{
61    let theta = a.ang.mixed_wrap_phase();
62    let (imag_s, real_s) = theta.mixed_sincos();
63
64    let c_cartesian = Cartesian::<T>{
65        re: a.mag*real_s,
66        im: a.mag*imag_s
67    };
68    return c_cartesian;
69}
70
71/// Add two complex fixed-point numbers in cartesian form.
72/// 
73pub fn add<T>( a: Cartesian<T>, b: Cartesian<T> ) -> Cartesian<T>
74    where T: MixedNum + MixedOps
75{
76    let c_cartesian = Cartesian::<T>{
77        re: a.re + b.re,
78        im: a.im + b.im
79    };
80    return c_cartesian;
81}
82
83/// Subtract b from a.
84/// c = a-b
85/// 
86pub fn sub<T>( a: Cartesian<T>, b: Cartesian<T> ) -> Cartesian<T>
87    where T: MixedNum + MixedNumSigned +  core::ops::Sub<Output = T>
88{
89    let c_cartesian = Cartesian::<T>{
90        re: a.re - b.re,
91        im: a.im - b.im
92    };
93    return c_cartesian;
94}
95
96/// Multiply fixed-point complex numbers in polar form.
97/// 
98pub fn mul_polar<T>( a: Polar<T>, b: Polar<T> ) -> Polar<T>
99    where T: MixedNum + MixedNumSigned + MixedOps
100{
101    if a.mag==T::mixed_from_num(0) || b.mag==T::mixed_from_num(0)
102    {
103        let c = Polar::<T>{
104            mag:     T::mixed_from_num(0),
105            ang: T::mixed_from_num(0)
106        };
107        return c;
108    }
109    else
110    {
111        let c = Polar::<T>{
112            mag: a.mag*b.mag,
113            ang: a.ang+b.ang
114        };
115        return c;
116    }
117}
118
119/// Multiply two cartesian complex numbers.
120/// 
121pub fn mul_cartesian<T>( ab: Cartesian<T>, bc: Cartesian<T> ) -> Cartesian<T>
122    where T:  MixedNum + MixedNumSigned + MixedOps 
123{   
124    let a = ab.re;
125    let b = ab.im;
126    let c = bc.re;
127    let d = bc.im;
128
129    let re = (a*c) - (b*d);
130    let im = (a*d) + (b*c);
131    return Cartesian{re:re, im:im}
132}
133
134/// Rase a complex fixed-point number to an real-valued integer power.
135/// `base^power`.
136/// 
137/// ## Arguments
138/// 
139/// * `base`  - The complex, fixed-point base number.
140/// * `power` - The power to raise 'base' to.
141/// 
142/// ## Example
143/// 
144/// ```
145/// use mixed_num::Polar;
146/// use mixed_num::complex::*;
147/// 
148/// use fixed::{types::extra::U22, FixedI32};
149/// 
150/// let x = Cartesian::new( FixedI32::<U22>::from_num(1f32), FixedI32::<U22>::from_num(1f32) );
151/// let y = powi( x, 2 );
152/// 
153/// let result = Cartesian::new( FixedI32::<U22>::from_num( -0.0000038f32, ), FixedI32::<U22>::from_num( 1.996035f32 ));
154/// assert_eq!{ y, result };
155/// ```
156/// 
157pub fn powi<T>( base: Cartesian<T>, power:usize ) -> Cartesian<T>
158    where T: fixed::traits::FixedSigned + MixedNum + MixedNumSigned + MixedAtan + MixedSin + MixedSqrt + MixedPowi
159{   
160    // Calculate raised magnitude.
161    let temp:T = base.re.mixed_powi(2) + base.im.mixed_powi(2);
162    let mag:T  = temp.mixed_sqrt().mixed_powi(power as i32);
163
164    let phi:T  = base.im.mixed_atan2(base.re) *<T>::from_num(power);
165
166    let (imag_s, real_s) = phi.mixed_sincos();
167
168    let real   = mag*real_s;
169    let imag   = mag*imag_s;
170
171    return Cartesian::new_from_cartesian( real, imag);
172}
173
174/// Divide a cartesian complex by a real scalar.
175/// c = a/b
176/// 
177pub fn div_scalar_cartesian<T>( a: Cartesian<T>, b: T  ) -> Cartesian<T>
178    where T: MixedReal + MixedNumSigned + MixedOps
179{
180    let mut c = a;
181
182    if b == T::mixed_from_num(0)
183    {
184        c.re = T::mixed_max_value();
185        c.im = T::mixed_max_value();
186    }
187    else
188    {
189        c.re = a.re / b;
190        c.im = a.im / b;
191    }
192    return c;
193}
194
195/// Divide a cartesian complex by a real scalar.
196/// c = a/b
197/// 
198pub fn div_cartesian<T>( numerator: Cartesian<T>, denominator: Cartesian<T>  ) -> Cartesian<T>
199    where T: MixedNum + MixedNumSigned + MixedOps + MixedPowi
200{
201    //  ((a,bi))/((c,di))=((ac+bd)/(c^2+d^2),(bc-ad)/(c^2+d^2) i)
202
203    let a = numerator.re;
204    let b = numerator.im;
205    let c = denominator.re;
206    let d = denominator.re;
207
208    let re = (a*c+b*d)/(c.mixed_powi(2)+d.mixed_powi(2));
209    let im = (b*c-a*d)/(c.mixed_powi(2)+d.mixed_powi(2));
210    return Cartesian::new(re, im);
211}