// Arup Guha
// 2/18/02
// Complex Number Class
// Users of this class can create complex number objects and manipulate them 
// using standard arithmetic operations: adding, subtracting, multiplying,
// dividing and exponetiation to an non-negative integers.

#include <iostream.h>
#include <math.h>

class Complexno {
  public :
    Complexno();
    Complexno(double r);
    Complexno(double r, double c);
    friend Complexno add(const Complexno& num1, const Complexno& num2);
    friend Complexno mult(const Complexno& num1, const Complexno& num2);
    friend Complexno operator +(const Complexno& num1, const Complexno& num2);
    friend Complexno operator -(const Complexno& num1, const Complexno& num2);
    friend Complexno operator *(const Complexno& num1, const Complexno& num2);
    friend Complexno operator /(const Complexno& num1, const Complexno& num2);
    friend Complexno operator -(const Complexno& num);
    friend Complexno operator ^(const Complexno& base, const int& num2);
    friend ostream& operator <<(ostream& write, Complexno x);
    double magnitude();
    void enternum();
    void shownum();
  private :
    double real;
    double complex;
};

void main() {

  cout.setf(ios::fixed);
  cout.setf(ios::showpoint);
  cout.precision(1);

  Complexno n1, n2, n3;
  cout << "Welcome to the complex number calculator.\n";

  int choice;
  cout << "Would you like to\n";
  cout << "1. Add 2 complex numbers.\n";
  cout << "2. Subtract 2 complex numbers.\n";
  cout << "3. Multiply 2 complex numbers.\n";
  cout << "4. Divide 2 complex numbers.\n";
  cout << "5. Find the magnitude of a complex number.\n";
  cout << "6. Negate a complex number\n";
  cout << "7. Take a complex number to an integer power\n";
  cout << "8. Add a real number to a complex number\n";
  cin >> choice;

  cout << "Enter the first complex number : \n";
  n1.enternum();

  if (choice<5) {
    cout << "Enter the second complex number : \n";
    n2.enternum();
  }
  
  if (choice == 1) {
    n3 = n1 + n2;
    cout << n1 << " + " << n2 << " = " << n3 << endl;   
  }
  else if (choice == 2) {
    n3 = n1 - n2;
    cout << n1 << " - " << n2 << " = " << n3 << endl;   
  }
  else if (choice == 3) {
    n3 = n1 * n2;
    cout << n1 << " * " << n2 << " = " << n3 << endl;   
  }
  else if (choice == 4) {
    n3 = n1 / n2;
    cout << n1 << " / " << n2 << " = " << n3 << endl;   
  }
  else if (choice == 5) {
    cout << "|" << n1 << "| = " << n1.magnitude() << endl;
  }
  else if (choice==6) {
    n3 = -n1;
    cout << "-" << n1 << " = " << n3 << endl;
  }
  else if (choice == 7) {
    int exp;
    cout << "Enter integer you want to take the complex number to.\n";
    cin >> exp;
    n3 = n1 ^ exp;
    cout << n1 << " ^ " << exp << " = " << n3 << endl;
  }
  else {
    double number;
    cout << "Enter a real number you want to add to the complex one.\n";
    cin >> number;
    n3 = n1 + number;
    cout << n1 << " + " << number << " = " << n3 << endl;
  }
}

// Default constructor sets both components to 0.
Complexno::Complexno() {
  real = 0.0;
  complex = 0.0;
}

// Constructor that initializes a Complexno object with only a real component.
Complexno::Complexno(double r) {
  real = r;
  complex = 0.0;
}

// Constructor that is supplied with both a real and imaginary component.
Complexno::Complexno(double r, double c) {
  real = r;
  complex = c;
}

// Adds two complex numbers and returns the result in a complex number.
Complexno add(const Complexno& num1, const Complexno& num2) {  
  Complexno answer;
  answer.real = num1.real + num2.real;
  answer.complex = num1.complex + num2.complex;
  return answer;
}

// Multiplies...
Complexno mult(const Complexno& num1, const Complexno& num2) {
  
  Complexno answer;
  answer.real = num1.real*num2.real - num1.complex*num2.complex;
  answer.complex = num1.real*num2.complex + num1.complex*num2.real;
  return answer;
}

// Allows the user to initialize a Complexno object.
void Complexno::enternum() {

  cout << "Enter the real part of the complex number : ";
  cin >> real;
  cout << "Enter the imaginary part of the complex number : ";
  cin >> complex;
}
    
// Prints out a Complexno object.
void Complexno::shownum() {
  cout << "(" << real;
  if (complex>0.0)
    cout << " + " << complex << "i";
  else if (complex<0.0)
    cout << " - " << fabs(complex) << "i";
  cout << ")";
}

// Operator overloading...addition
Complexno operator +(const Complexno& num1, const Complexno& num2) {
  Complexno answer;
  answer.real = num1.real + num2.real;
  answer.complex = num1.complex + num2.complex;
  return answer;
}

// Subtraction...
Complexno operator -(const Complexno& num1, const Complexno& num2) {
  Complexno answer;
  answer.real = num1.real - num2.real;
  answer.complex = num1.complex - num2.complex;
  return answer;
}

// Multiplication...
Complexno operator *(const Complexno& num1, const Complexno& num2) {
  Complexno answer;
  answer.real = num1.real*num2.real - num1.complex*num2.complex;
  answer.complex = num1.real*num2.complex + num1.complex*num2.real;
  return answer;
}

// Division...
Complexno operator /(const Complexno& num1, const Complexno& num2) {
  Complexno answer;
  double den = pow(num2.real,2) + pow(num2.complex,2); 
  answer.real = (num1.real*num2.real + num1.complex*num2.complex)/den;
  answer.complex = (num1.complex*num2.real - num1.real*num2.complex)/den;
  return answer;
}

// Unary minus...
Complexno operator -(const Complexno& num) {
  Complexno answer;
  answer.real = -num.real;
  answer.complex = -num.complex;
  return answer;
}

// Returns the magnitude of a complex number.
double Complexno::magnitude() {
  return sqrt(pow(real,2)+pow(complex,2));
}

// Exponentiation...only works if the integer exponent is non-negative.
Complexno operator ^(const Complexno& base, const int& num2) {

  Complexno answer;
  answer.real=1;
  answer.complex=0;

  if (num2==0)
    return answer;
  if (num2==1)
    return base;
  else
    return base*(base^(num2-1));
  
  
}

// Overloading of the << operator for output.
ostream& operator <<(ostream& rite, Complexno x) {
  
  rite << "(" << x.real;
  if (x.complex>0.0)
    rite << " + " << x.complex << "i";
  else if (x.complex<0.0)
    rite << " - " << fabs(x.complex) << "i";
  rite << ")";
  return rite;
}

