// complejo.h - Declaración de la clase CComplejo
#if !defined(_COMPLEJO_H_)
#define _COMPLEJO_H_

#include <cmath>
#include <iostream>

/////////////////////////////////////////////////////////////////
// Clase para operar con números complejos
class CComplejo
{
  private:
    double real;  // parte real
    double imag;  // parte imaginaria

  protected:
    static void error(char *);

  public:
    // Constructores
    // CComplejo(const CComplejo&)
    // es creado por omisión por el compilador
    CComplejo(const double r = 0, const double i = 0)
      : real(r), imag(i) {}
      
    // Paso de forma polar a binómica: m(cos alfa + isen alfa)=a+bi
    friend CComplejo po_bi(const double, const double);
  
    // Operaciones aritméticas con complejos
    friend CComplejo operator+(const CComplejo&, const CComplejo&);
    friend CComplejo operator-(const CComplejo&, const CComplejo&);
    friend CComplejo operator*(const CComplejo&, const CComplejo&);
    friend CComplejo operator/(const CComplejo&, const CComplejo&);
      
    // Comparación de complejos
    friend bool operator==(const CComplejo&, const CComplejo&);
    friend bool operator!=(const CComplejo&, const CComplejo&);
    friend bool operator< (const CComplejo&, const CComplejo&);
    friend bool operator<=(const CComplejo&, const CComplejo&);
    friend bool operator> (const CComplejo&, const CComplejo&);
    friend bool operator>=(const CComplejo&, const CComplejo&);
    
    // Operaciones trigonométricas con complejos
    friend CComplejo cos(const CComplejo&);
    friend CComplejo sin(const CComplejo&);
    friend CComplejo tan(const CComplejo&);
    
    friend CComplejo cosh(const CComplejo&);
    friend CComplejo sinh(const CComplejo&);
    friend CComplejo tanh(const CComplejo&);
    
    // Operaciones logaritmo, exponencial, potencia y raíz cuadrada
    friend CComplejo exp(const CComplejo&);
    friend CComplejo log(const CComplejo&);
    friend CComplejo pow(const CComplejo&, const CComplejo&);
    friend CComplejo sqrt(const CComplejo& c);
    
    // Operaciones de entrada/salida                                 
    friend std::istream& operator>>(std::istream&, CComplejo&);
    friend std::ostream& operator<<(std::ostream&, const CComplejo&);
    
    // Obtención de valores
    double ParteReal() const
      { return real; }
    double ParteImag() const
      { return imag; }
    double mod() const
      { return sqrt(real*real + imag*imag); }
    double arg() const
      { return atan2(imag, real); }
    double norm() const
      { return real*real + imag*imag; }
    
    // Operaciones varias
    CComplejo conjugado() { return CComplejo(real, -imag); }
    CComplejo negativo()  { return CComplejo(-real, imag); }
    
    // Menos unario. Complejos opuestos
    CComplejo operator-()   { return CComplejo(-real, -imag); }

    // Asignación de complejos
    // operator=() lo crea el compilador por defecto
    CComplejo operator+=(const CComplejo& c)
      { return *this = *this + c; }
    CComplejo operator-=(const CComplejo& c)
      { return *this = *this - c; }
    CComplejo operator*=(const CComplejo& c)
      { return *this = *this * c; }
    CComplejo operator/=(const CComplejo& c)
      { return *this = *this / c; }
};

#endif // _COMPLEJO_H_
/////////////////////////////////////////////////////////////////
