// Program: complex.cpp // Note: It would make sense to separate header, implementation, and // test-main-function into separate files (complex.h, complex.cpp, main.cpp). // This way it would be far easier to reuse our complex class in other // projects. #include #include #include namespace ifmp { class complex { public: // default constructor // POST: constructed as 0 + i0 complex () : real (0), imag (0) {} // POST: constructed as real + i0 complex (const float real) : real (real), imag (0) {} // POST: constructed as real + i*imag complex (const float real, const float imag) : real (real), imag (imag) {} // POST: returns real part float get_real () const {return real;} // POST: returns imaginary part float get_imag () const {return imag;} // POST: adds b to *this and returns a reference to *this complex& operator+= (const complex& b); // POST: subtracts b from *this and returns a reference to *this complex& operator-= (const complex& b); // POST: multiplies b to *this and returns a reference to *this complex& operator*= (const complex& b); // PRE: b != 0 // POST: divides *this by b and returns a reference to *this complex& operator/= (const complex& b); private: float real; float imag; }; complex& complex::operator+= (const complex& b) { real += b.real; imag += b.imag; return *this; } complex& complex::operator-= (const complex& b) { real -= b.real; imag -= b.imag; return *this; } complex& complex::operator*= (const complex& b) { float tempreal = real*b.real - imag*b.imag; imag = real*b.imag + imag*b.real; real = tempreal; return *this; } complex& complex::operator/= (const complex& b) { assert(b.get_real() != 0 || b.get_imag() != 0); float denom = b.real*b.real + b.imag*b.imag; float tempreal = (real*b.real + imag*b.imag)/denom; imag = (-real*b.imag + imag*b.real)/denom; real = tempreal; return *this; } // POST: returns a + b complex operator+ (complex a, const complex& b) { return a+=b; } // POST: returns a - b complex operator- (complex a, const complex& b) { return a-=b; } // POST: returns a * b complex operator* (complex a, const complex& b) { return a*=b; } // PRE: b != 0 // POST: returns a / b complex operator/ (complex a, const complex& b) { return a/=b; } // POST: returns true if and only if a and b are equal bool operator== (const complex& a, const complex& b) { return a.get_real() == b.get_real() && a.get_imag() == b.get_imag(); } // POST: returns true if and only if a and b are different bool operator!= (const complex& a, const complex& b) { return !(a==b); } // POST: z is written to o according to the format (re,im), and a reference // to o is returned std::ostream& operator<< (std::ostream& o, const complex& z) { o << "(" << z.get_real() << "," << z.get_imag() << ")"; return o; } // POST: returns the complex conjugate (re,-im) complex conj (const complex& z) { complex temp (z.get_real(), -z.get_imag()); return temp; } // POST: returns absolute value |z| float abs (const complex& z) { return std::sqrt(z.get_real()*z.get_real() + z.get_imag()*z.get_imag()); } // PRE: z != 0 + i0 // POST: returns argument of z float arg_ugly (const complex& z) { assert(z.get_real() != 0 || z.get_imag() != 0); if (z.get_real() > 0 && z.get_imag() >= 0) return std::atan (z.get_imag()/z.get_real()); else if (z.get_real() < 0 && z.get_imag() >= 0) return std::atan (z.get_imag()/z.get_real()) + 3.14159; else if (z.get_real() > 0 && z.get_imag() < 0) return std::atan (z.get_imag()/z.get_real()); else return std::atan (z.get_imag()/z.get_real()) - 3.14159; } // PRE: z != 0 + i0 // POST: returns argument of z float arg (const complex& z) { assert(z.get_real() != 0 || z.get_imag() != 0); // this is nicer than arg_ugly return std::atan2 (z.get_imag(), z.get_real()); } } // end of namespace ifmp int main () { std::cout << "\n"; std::cout << "=================================================================\n"; std::cout << "The goal is to make our complex class match the expected results:\n"; std::cout << "(The expected results were computed using the standard library.) \n"; std::cout << "=================================================================\n"; std::cout << "\n\n"; // Test basic computations ifmp::complex x; ifmp::complex y(4); ifmp::complex z(3, 4); const ifmp::complex v(2, 5); std::cout << "Print x: " << x << " (expect (0,0)) \n"; std::cout << "Print y: " << y << " (expect (4,0)) \n"; std::cout << "Print z: " << z << " (expect (3,4)) \n"; std::cout << "Print v: " << v << " (expect (2,5)) \n"; std::cout << "\n\n"; std::cout << "Print Re(z): " << z.get_real() << " (expect 3) \n"; std::cout << "Print Im(z): " << z.get_imag() << " (expect 4) \n"; std::cout << "\n\n"; std::cout << "Print z += v: " << (z += v) << " (expect (5,9)) \n"; std::cout << "Print z -= v: " << (z -= v) << " (expect (3,4)) \n"; std::cout << "Print z *= v: " << (z *= v) << " (expect (-14,23)) \n"; std::cout << "Print z /= v: " << (z /= v) << " (expect (3,4)) \n"; std::cout << "\n\n"; std::cout << "Print z + v: " << z + v << " (expect (5,9)) \n"; std::cout << "Print z - v: " << z - v << " (expect (1,-1)) \n"; std::cout << "Print z * v: " << z * v << " (expect (-14,23)) \n"; std::cout << "Print z / v: " << z / v << " (expect (0.896552,-0.241379)) \n"; std::cout << "\n\n"; std::cout << "Print x == v: " << (x == v) << " (expect 0) \n"; std::cout << "Print x != v: " << (x != v) << " (expect 1) \n"; std::cout << "\n\n"; std::cout << "Print the conjugate of v: " << conj(v) << " (expect (2,-5)) \n"; std::cout << "Print the absolute value of v: " << abs(v) << " (expect 5.38516) \n"; std::cout << "\n\n"; // Test arg const ifmp::complex r1(2, 5); // re > 0, im > 0 const ifmp::complex r2(-2, 5); // re < 0, im > 0 const ifmp::complex r3(2, -5); // re > 0, im < 0 const ifmp::complex r4(-2, -5); // re < 0, im < 0 std::cout << "Print the phase of r1: " << arg(r1) << " (expect 1.19029) \n"; std::cout << "Print the phase of r1: " << arg_ugly(r1) << " (expect 1.19029) \n"; std::cout << "\n\n"; std::cout << "Print the phase of r2: " << arg(r2) << " (expect 1.9513) \n"; std::cout << "Print the phase of r2: " << arg_ugly(r2) << " (expect 1.9513) \n"; std::cout << "\n\n"; std::cout << "Print the phase of r3: " << arg(r3) << " (expect -1.19029) \n"; std::cout << "Print the phase of r3: " << arg_ugly(r3) << " (expect -1.19029) \n"; std::cout << "\n\n"; std::cout << "Print the phase of r4: " << arg(r4) << " (expect -1.9513) \n"; std::cout << "Print the phase of r4: " << arg_ugly(r4) << " (expect -1.9513) \n"; std::cout << "\n\n"; return 0; }