Info
Implementing an operator:
use std::ops::Add;
struct S(u32);
impl Add<S> for S {
type Output = S;
fn add(self, rhs: S) -> Self::Output {
S(self.0 + rhs.0)
}
}
Taking a generic:
use std::{fmt::Debug, ops::Add};
fn f<T: Debug + Add<Output = u32>>(x: T, y: T) {
println!("{}", x + y);
}
Assert:
fn main() {
assert!(true);
assert_eq!(5, 5);
assert_ne!(10, 11);
}
Problem
Define and implement code for a datatype Complex that represents a complex number. The type will keep its data as f64. The type has to implement the following:
- associated function
newthat takes 2 arguments, each with a generic type, that will be used to convert and initialize the type; - associated function
conjugatethat returns the conjugate of the number; - implement From for
i32andf64for the type; the number will be the real part, and the imaginary part will be 0; - implement Add, Sub, Mul that is generic over any type that can be converted to
Complex; - implement Neg;
- implement Display that respects the rules shown below;
The following code must compile and print ok! when run. Do not modify it.
fn eq_rel(x: f64, y: f64) -> bool {
(x - y).abs() < 0.001
}
// This is a macro that panics if 2 floats are not equal using an epsilon.
// You are not required to understand it yet, just to use it.
macro_rules! assert_eq_rel {
($x:expr, $y: expr) => {
let x = $x as f64;
let y = $y as f64;
let r = eq_rel(x, y);
assert!(r, "{} != {}", x, y);
};
}
fn main() {
let a = Complex::new(1.0, 2.0);
assert_eq_rel!(a.real, 1);
assert_eq_rel!(a.imag, 2);
let b = Complex::new(2.0, 3);
let c = a + b;
assert_eq_rel!(c.real, 3);
assert_eq_rel!(c.imag, 5);
let d = c - a;
assert_eq!(b, d);
let e = (a * d).conjugate();
assert_eq_rel!(e.imag, -7);
let f = (a + b - d) * c;
assert_eq!(f, Complex::new(-7, 11));
// Note: .to_string() uses Display to format the type
assert_eq!(Complex::new(1, 2).to_string(), "1+2i");
assert_eq!(Complex::new(1, -2).to_string(), "1-2i");
assert_eq!(Complex::new(0, 5).to_string(), "5i");
assert_eq!(Complex::new(7, 0).to_string(), "7");
assert_eq!(Complex::new(0, 0).to_string(), "0");
let h = Complex::new(-4, -5);
let i = h - (h + 5) * 2.0;
assert_eq_rel!(i.real, -6);
let j = -i + i;
assert_eq_rel!(j.real, 0);
assert_eq_rel!(j.imag, 0);
println!("ok!");
}
Math help: link.
Bonus
Also implement AddAssign, SubAssign, MulAssign, and any other operator or special trait that makes sense for the type.