|
@@ -11,16 +11,20 @@ use crate::{Float, Numeric, Primitive};
|
|
/// let c = Complex { real: 9.0, imag: 0.0 };
|
|
/// let c = Complex { real: 9.0, imag: 0.0 };
|
|
/// assert_eq!(format!("{:?}", c), "Complex { real: 9.0, imag: 0.0 }");
|
|
/// assert_eq!(format!("{:?}", c), "Complex { real: 9.0, imag: 0.0 }");
|
|
///
|
|
///
|
|
-/// let three = c.fsqrt().real;
|
|
|
|
|
|
+/// let three = c.sqrt().real;
|
|
/// assert_eq!(three, 3.0);
|
|
/// assert_eq!(three, 3.0);
|
|
///
|
|
///
|
|
-/// let i: Complex<f32> = (-Complex::whole(1)).fsqrt();
|
|
|
|
|
|
+/// let i: Complex<f32> = Complex::real(-1.0).sqrt();
|
|
/// assert_eq!(i, Complex::i());
|
|
/// assert_eq!(i, Complex::i());
|
|
///
|
|
///
|
|
/// let a = Complex { real: 2.0, imag: 0.5 };
|
|
/// let a = Complex { real: 2.0, imag: 0.5 };
|
|
/// let a_squared = a * a;
|
|
/// let a_squared = a * a;
|
|
/// assert_eq!(a_squared, Complex { real: 3.75, imag: 2.0 });
|
|
/// assert_eq!(a_squared, Complex { real: 3.75, imag: 2.0 });
|
|
-/// assert_eq!(a_squared.fsqrt(), a);
|
|
|
|
|
|
+/// assert_eq!(a_squared.sqrt(), a);
|
|
|
|
+///
|
|
|
|
+/// let x = (16.0).sqrt();
|
|
|
|
+/// let y = Complex::real(16.0).sqrt().real;
|
|
|
|
+/// assert_eq!(x, y);
|
|
/// ```
|
|
/// ```
|
|
#[derive(Debug, Copy, Clone)]
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct Complex<T: Float + Numeric + Primitive> {
|
|
pub struct Complex<T: Float + Numeric + Primitive> {
|
|
@@ -29,11 +33,25 @@ pub struct Complex<T: Float + Numeric + Primitive> {
|
|
}
|
|
}
|
|
|
|
|
|
impl<T: Float + Numeric + Primitive> Complex<T> {
|
|
impl<T: Float + Numeric + Primitive> Complex<T> {
|
|
|
|
+ pub fn real(value: T) -> Self {
|
|
|
|
+ Self {
|
|
|
|
+ real: value,
|
|
|
|
+ imag: unsafe { T::whole(0) },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn imag(value: T) -> Self {
|
|
|
|
+ Self {
|
|
|
|
+ real: unsafe { T::whole(0) },
|
|
|
|
+ imag: value,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
/// The imaginary unit.
|
|
/// The imaginary unit.
|
|
pub fn i() -> Self {
|
|
pub fn i() -> Self {
|
|
Self {
|
|
Self {
|
|
- real: T::whole(0),
|
|
|
|
- imag: T::whole(1),
|
|
|
|
|
|
+ real: unsafe { T::whole(0) },
|
|
|
|
+ imag: unsafe { T::whole(1) },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -131,24 +149,24 @@ impl<T: Float + Numeric + Primitive> PartialEq for Complex<T> {
|
|
}
|
|
}
|
|
|
|
|
|
impl<T: Float + Primitive + Numeric> Float for Complex<T> {
|
|
impl<T: Float + Primitive + Numeric> Float for Complex<T> {
|
|
- fn fabs(self) -> Self {
|
|
|
|
|
|
+ fn abs(self) -> Self {
|
|
Self {
|
|
Self {
|
|
- real: (self.real * self.real + self.imag * self.imag).fsqrt(),
|
|
|
|
- imag: T::whole(0),
|
|
|
|
|
|
+ real: (self.real * self.real + self.imag * self.imag).sqrt(),
|
|
|
|
+ imag: unsafe { T::whole(0) },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn fsqrt(self) -> Self {
|
|
|
|
- let zero = T::whole(0);
|
|
|
|
- let two = T::whole(2);
|
|
|
|
- let abs_z = self.fabs().real;
|
|
|
|
|
|
+ fn sqrt(self) -> Self {
|
|
|
|
+ let zero = unsafe { T::whole(0) };
|
|
|
|
+ let two = unsafe { T::whole(2) };
|
|
|
|
+ let abs_z = self.abs().real;
|
|
|
|
|
|
let base_re = if self.imag == zero { self.real } else { (abs_z + self.real) / two };
|
|
let base_re = if self.imag == zero { self.real } else { (abs_z + self.real) / two };
|
|
- let re = if base_re < zero { zero } else { base_re.fsqrt() };
|
|
|
|
|
|
+ let re = if base_re < zero { zero } else { base_re.sqrt() };
|
|
|
|
|
|
let im = if self.imag == zero { zero } else {
|
|
let im = if self.imag == zero { zero } else {
|
|
- (self.imag / self.imag.fabs()) * ((abs_z - self.real) / two).fsqrt()
|
|
|
|
- } + if base_re < zero { (-base_re).fsqrt() } else { zero };
|
|
|
|
|
|
+ (self.imag / self.imag.abs()) * ((abs_z - self.real) / two).sqrt()
|
|
|
|
+ } + if base_re < zero { (-base_re).sqrt() } else { zero };
|
|
|
|
|
|
Self {
|
|
Self {
|
|
real: re,
|
|
real: re,
|
|
@@ -156,37 +174,37 @@ impl<T: Float + Primitive + Numeric> Float for Complex<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn fsin(self) -> Self {
|
|
|
|
|
|
+ fn sin(self) -> Self {
|
|
Self {
|
|
Self {
|
|
- real: self.real.fsin() * self.imag.fcosh(),
|
|
|
|
- imag: self.real.fcos() * self.imag.fsinh(),
|
|
|
|
|
|
+ real: self.real.sin() * self.imag.cosh(),
|
|
|
|
+ imag: self.real.cos() * self.imag.sinh(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn fcos(self) -> Self {
|
|
|
|
|
|
+ fn cos(self) -> Self {
|
|
Self {
|
|
Self {
|
|
- real: self.real.fcos() * self.imag.fcosh(),
|
|
|
|
- imag: self.real.fsin() * self.imag.fsinh(),
|
|
|
|
|
|
+ real: self.real.cos() * self.imag.cosh(),
|
|
|
|
+ imag: self.real.sin() * self.imag.sinh(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn fsinh(self) -> Self {
|
|
|
|
|
|
+ fn sinh(self) -> Self {
|
|
Self {
|
|
Self {
|
|
- real: self.real.fsinh() * self.imag.fcos(),
|
|
|
|
- imag: self.real.fcosh() * self.imag.fsin(),
|
|
|
|
|
|
+ real: self.real.sinh() * self.imag.cos(),
|
|
|
|
+ imag: self.real.cosh() * self.imag.sin(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn fcosh(self) -> Self {
|
|
|
|
|
|
+ fn cosh(self) -> Self {
|
|
Self {
|
|
Self {
|
|
- real: self.real.fcosh() * self.imag.fcos(),
|
|
|
|
- imag: self.real.fsinh() * self.imag.fsin(),
|
|
|
|
|
|
+ real: self.real.cosh() * self.imag.cos(),
|
|
|
|
+ imag: self.real.sinh() * self.imag.sin(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl<T: Float + Numeric + Primitive> Numeric for Complex<T> {
|
|
impl<T: Float + Numeric + Primitive> Numeric for Complex<T> {
|
|
- fn whole(value: u32) -> Self {
|
|
|
|
|
|
+ unsafe fn whole(value: u32) -> Self {
|
|
Self { real: T::whole(value), imag: T::whole(0) }
|
|
Self { real: T::whole(value), imag: T::whole(0) }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -207,9 +225,9 @@ mod tests {
|
|
#[test]
|
|
#[test]
|
|
fn square_root_with_negatives() {
|
|
fn square_root_with_negatives() {
|
|
let a = Complex { real: -1.0, imag: -1.0 };
|
|
let a = Complex { real: -1.0, imag: -1.0 };
|
|
- let root = a.fsqrt();
|
|
|
|
|
|
+ let root = a.sqrt();
|
|
let expected = Complex { real: 0.45508986, imag: -1.09868411 };
|
|
let expected = Complex { real: 0.45508986, imag: -1.09868411 };
|
|
- assert!((root.real - expected.real).fabs() < 0.00001);
|
|
|
|
- assert!((root.imag - expected.imag).fabs() < 0.00001);
|
|
|
|
|
|
+ assert!((root.real - expected.real).abs() < 0.00001);
|
|
|
|
+ assert!((root.imag - expected.imag).abs() < 0.00001);
|
|
}
|
|
}
|
|
}
|
|
}
|