/*
 *	Autor: Krzysztof Trynkiewicz, rok I inf.stos.
 *	mail: chris.trynkiewicz@gmail.com
 *	Program operuje na liczbach zespolonych
 *	Version: 1.0
 *	Last modified: 04-06-07
*/

	/* Includes */
	#include <iostream>
	#include <math.h>
	/* --- Koniec Includes */

using namespace std;

class Zespol{

private:
   
    double re, im;

public:

    Zespol();
    Zespol(double, double);
    ~Zespol();
   
    double get_re();
    double get_im();
    void set_re(double);
    void set_im(double);
   
    friend double mod(Zespol&);
    friend Zespol exp(Zespol&);
    friend Zespol sin(Zespol&);
    friend Zespol cos(Zespol&);
    friend Zespol tg(Zespol&);
    friend Zespol ctg(Zespol&);
    friend Zespol ln(Zespol&);
    friend Zespol pow(Zespol&, Zespol&);
    friend Zespol sqrt(Zespol&);
    friend double arg(Zespol&);
   
    friend Zespol operator+(Zespol, Zespol);
    friend Zespol operator-(Zespol, Zespol);
    friend Zespol operator*(Zespol, Zespol);
    friend Zespol operator/(Zespol, Zespol);
    friend ostream& operator<<(ostream&, Zespol&);
    friend istream& operator>>(istream&, Zespol&);

};

double mod(Zespol&);
Zespol exp(Zespol&);
Zespol sin(Zespol&);
Zespol cos(Zespol&);
Zespol tg(Zespol&);
Zespol ctg(Zespol&);
Zespol ln(Zespol&);
Zespol pow(Zespol&, Zespol&);
Zespol sqrt(Zespol&);
double arg(Zespol&);


Zespol operator+(Zespol, Zespol);
Zespol operator-(Zespol, Zespol);
Zespol operator*(Zespol, Zespol);
Zespol operator/(Zespol, Zespol);
ostream& operator<<(ostream&, Zespol&);
istream& operator>>(istream&, Zespol&);

int main(){

	/* Przedstawienie */
	printf("\n\tAutor: Krzysztof Trynkiewicz, I rok inf.stos.\n\tmail: chris.trynkiewicz@gmail.com || trynkiewicz@ibis.if.uj.edu.pl\n");
	printf("\tProgram operuje na liczbach zespolonych\n\n");
	/* --- Koniec Przedstawienia */

    Zespol a(1,2), b(3,4), c;
   
    cout <<"Wprowadz liczbe zespolona w postaci (x,y) lub x: ";
    cin >> c;
    cout << "Wprowadzona liczba: " << c << endl;

    cout << "a: " << a << endl;
    cout << "b: " << b << endl;
   
    c=a+b;
    cout << "a+b = " << c << endl;
   
    c=a-b;
    cout << "a-b = " << c << endl;

    c=a*b;
    cout << "a*b = " << c << endl;

    c=a/b;
   
    cout << "a/b = " << c << endl;

    c=exp(a);
    cout << "exp(a) = " << c << endl;

    c=sin(a);
    cout << "sin(a) = " << c << endl;

    c=cos(a);
    cout << "cos(a) = " << c << endl;
   
    cout << "arg(a) = " << arg(a) << endl;
   
    c=ln(a);
    cout << "ln(a) = " << c << endl;
   
    c=pow(a,b);
    cout << "a^b = " << c << endl;
   
    c=sqrt(a);
    cout << "sqrt(a) = " << c << endl;

    return 0;

}


Zespol::Zespol(){

    this->re=0;
    this->im=0;

}

Zespol::Zespol(double re, double im){

    this->re=re;
    this->im=im;

}

Zespol::~Zespol(){}

double Zespol::get_re(){

    return this->re;

}

double Zespol::get_im(){

    return this->im;

}

void Zespol::set_re(double x){

    this->re=x;

}

void Zespol::set_im(double x){

    this->im=x;

}

double mod(Zespol& z){

    return sqrt((z.re*z.re)+(z.im*z.im));

}

Zespol operator+(Zespol z1, Zespol z2){

    return Zespol(z1.re+z2.re, z1.im+z2.im);

}

Zespol operator-(Zespol z1, Zespol z2){

    return Zespol(z1.re-z2.re, z1.im-z2.im);

}

Zespol operator*(Zespol z1, Zespol z2){

    return Zespol((z1.re*z2.re)-(z1.im*z2.im), (z1.re*z2.im)+(z1.im*z2.re));

}

Zespol operator/(Zespol z1, Zespol z2){

    double a=0, b=0;
   
    if(!mod(z2)){
    cout << "dzielenie niewykonalne, zwracam (0,0)\n";
    return Zespol(0,0);
    }
    a=((z1.re*z2.re)+(z1.im*z2.im))/(mod(z2)*mod(z2));
    b=((z1.im*z2.re)-(z1.re*z2.im))/(mod(z2)*mod(z2));
   
    return Zespol(a, b);

}

ostream& operator<<(ostream& s, Zespol& z){

    s<<"("<<z.get_re()<<","<<z.get_im()<<")";
   
    return s;

}

istream& operator>>(istream& s, Zespol& z){
   
    char line[100];
    double t1,t2;
   
    s>>line;
    if(line[0]=='('){
    sscanf(line, "(%lf,%lf)", &t1, &t2);
    z.re=t1;
    z.im=t2;
    }else{
    sscanf(line, "%lf", &t1);
    z.re=t1;
    z.im=0;
    }
   
    return s;
   
}

Zespol exp(Zespol& z){

    return Zespol((exp(z.re)*cos(z.im)), (exp(z.re)*sin(z.im)));

}

Zespol sin(Zespol& z){

    return Zespol((-sin(z.re)*(exp(-z.im)+exp(z.im)))/-2, (cos(z.re)*(exp(-z.im)-exp(z.im)))/-2);

}

Zespol cos(Zespol& z){

    return Zespol((cos(z.re)*(exp(-z.im)+exp(z.im)))/2, (sin(z.re)*(exp(-z.im)-exp(z.im)))/2);

}

Zespol tg(Zespol& z){
   
    return sin(z)/cos(z);

}

Zespol ctg(Zespol& z){

    return cos(z)/sin(z);

}

Zespol ln(Zespol& z){

    return Zespol(log(mod(z)), arg(z));

}

Zespol pow(Zespol& z1, Zespol& z2){

    Zespol tmp=z2*ln(z1);   

    return exp(tmp);

}

Zespol sqrt(Zespol& z){

    return Zespol(sqrt(mod(z))*cos(arg(z)/2),sqrt(mod(z))*sin(arg(z)/2));   

}

double arg(Zespol& z){

    return atan2(z.im, z.re);

}

	/* --- Koniec Programu */
