Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cmath> // pour les fonctions mathématiques
- #include <string> // pour les string
- #include <sstream> // pour les ostringstream
- #include <typeinfo> // pour le typeid
- #include <iostream> // pour les flux I/O
- #include <utility>
- using namespace std;
- #include "CComplex.h"
- // ----------------------------------------------------------------------------
- // Constructeurs / Desctructeur
- // ----------------------------------------------------------------------------
- /*
- * Constructeur d'un complexe cartésien à partir de ses parties
- * réelles et imaginaires
- * @param r la partie réelle
- * @param i la partie imaginaire
- */
- template <class T>
- CComplex<T>::CComplex(const T r, const T i) // TODO Compléter la liste d'initialisation en n'oubliant pas de commencer par un des constructeurs de la classe mère
- {
- this->NbInstances=this->NbInstances+1;
- this->_real=r;
- this->_imag=i;
- this->_instanceNumber=this->NbInstances;
- clog << "CComplex<" << typeid(T).name() << ">[" << _instanceNumber
- << "](" << r << ", " << i << ")";
- clog << endl;
- }
- /*
- * Constructeur de copie d'un complexe cartésien
- * @param c le complexe cartésien dont on doit copier les valeurs
- */
- template <class T>
- CComplex<T>::CComplex(const Complex<T> & c) // TODO Compléter la liste d'initialisation en oubliant pas de commencer par un des constructeurs de la classe mère
- {
- CComplex<T>(c.real(),c.imag());
- clog << "CComplex<" << typeid(T).name() << ">[" << _instanceNumber
- << "](" << c << ")";
- clog << endl;
- }
- /*
- * Constructeur de copie/conversion d'un complexe cartésien de nature différente
- * @param c le complexe cartésien d'un autre type dont on doit
- * copier les valeurs
- */
- template <class T>
- template <class U>
- CComplex<T>::CComplex(const Complex<U> & c) // TODO Compléter la liste d'initialisation en oubliant pas de commencer par un des constructeurs de la classe mère
- {
- /*
- * NOTE pour caster on peut utiliser
- * le cast de C ordinaire :
- * T1 v1 = ...
- * T2 v2 = (T2) v1;
- * le static_cast du C++
- * T1 v1 = ...
- * T2 v2 = static_cast<T2>(v1);
- */
- CComplex<T>((CComplex<T>) c);
- clog << "CComplex<" << typeid(T).name() << ">[" << _instanceNumber << "]<"
- << typeid(U).name() << ">(" << c << ")";
- clog << endl;
- }
- /*
- * Véritable constructeur de copie d'un complexe cartésien de même type
- * @param cc le complexe cartésien à copier
- */
- template <class T>
- CComplex<T>::CComplex(const CComplex<T> & cc) // TODO Compléter la liste d'initialisation en oubliant pas de commencer par un des constructeurs de la classe mère
- {
- CComplex<T>((CComplex<T>)cc);
- clog << "CComplex<" << typeid(T).name() << ">[" << _instanceNumber
- << "](" << cc << ")";
- clog << endl;
- }
- /*
- * Constructeur de déplacement
- * @param c le complexe à déplacer
- * @post le nombre d'instances n'est pas changé
- * @post le numéro d'instance de c a été copié dans this
- */
- template <class T>
- CComplex<T>::CComplex(Complex<T> && c) :
- Complex<T>(std::forward<Complex<T>>(c))
- // TODO compléter la liste d'initialisation
- {
- clog << "Move CComplex<" << typeid(T).name() << ">[" << _instanceNumber << "]"
- << "(" << c << ")";
- clog << endl;
- // TODO ne pas oublier de faire un reset sur c
- }
- template <class T>
- CComplex<T>::~CComplex()
- {
- // clog << "~CComplex<" << typeid(T).name() << ">[" << _instanceNumber
- // << "]";
- // clog << endl;
- }
- // ----------------------------------------------------------------------------
- // Propriétés des nombres complexes
- // ----------------------------------------------------------------------------
- /*
- * partie réelle (accesseur en lecture seule)
- * @return la partie réelle du nombre complexe
- */
- template <class T>
- T CComplex<T>::real() const
- {
- return this->_real;
- }
- /*
- * partie réelle (accesseur en lecture/écriture)
- * @return une référence vers la partie réelle du nombre complexe
- */
- template <class T>
- T & CComplex<T>::real()
- {
- return (this->_real);
- }
- /*
- * Partie imaginaire (accesseur en lecture seule)
- * @return la partie imaginaire du nombre complexe
- */
- template <class T>
- T CComplex<T>::imag() const
- {
- return this->_imag;
- }
- /*
- * Partie imaginaire (accesseur en lecture/écriture)
- * @return une référence vers la partie imaginaire du nombre complexe
- */
- template <class T>
- T & CComplex<T>::imag()
- {
- return (this->_imag);
- }
- /*
- * Norme du nombre complexe dans le plan complexe
- * @return la norme du nombre dans le plan complexe
- */
- template <class T>
- T CComplex<T>::abs() const
- {
- // TODO remplacer par l'implémentation
- return sqrt(((this->_real)*(this->_real))+((this->_imag)*(this->_imag)));
- }
- /*
- * L'angle du nombre dans le plan complexe.
- * a > 0 ==> theta = atan(b/a) ou atan2(b,a)
- * a < 0 & b >= 0 ==> theta = atan(b/a) + PI
- * a < 0 & b < 0 ==> theta = atan(b/a) - PI
- * a = 0 & b > 0 ==> PI/2
- * a = 0 & b < 0 ==> -PI/2
- * a = 0 & b = 0 ==> indéterminé
- * @return l'angle du nombre dans le plan complexe
- */
- template <class T>
- double CComplex<T>::arg() const throw (ComplexException)
- {
- if(this->_real>0){
- return atan(this->_imag/this->_real);
- }
- else if(this->_real<0){
- if(this->imag()>=0){
- return atan(this->_imag/this->_real)+M_PI;
- }
- else{
- return atan(this->_imag/this->_real)-M_PI;
- }
- }
- else {
- if(this->_imag>0){
- return M_PI/2;
- }
- else if(this->_imag<0){
- return -M_PI/2;
- }
- else {
- return 0.0;
- }
- }
- }
- // ----------------------------------------------------------------------------
- // Self Operations
- // ----------------------------------------------------------------------------
- /*
- * Opérateur de copie à partir de n'importe quel complexe
- * @param la référence d'un autre nombre complexe
- * @return la référence vers le nouveau nombre complexe
- */
- template <class T>
- template <class U>
- Complex<T> & CComplex<T>::operator =(const Complex<U> & c)
- {
- return *this;
- }
- /*
- * Opérateur de copie à partir d'un complexe cartésien
- * @param la référence d'un autre nombre complexe à copier
- * @return la référence vers le nouveau nombre complexe
- * @note Cette méthode est redondante avec celle définie juste au dessus
- * mais étant donné qu'elle était définie dans la classe abstraite
- * Complex<T> elle DOIT être implémentée ici, quitte à utiliser
- * la méthode ci-dessus dans son corps.
- */
- template <class T>
- Complex<T> & CComplex<T>::operator =(const Complex<T> & c)
- {
- /*
- * TODO Remplacer par
- * Réutilisation de l'opérateur ci-dessus en précisant le paramètre de
- * type <T>
- */
- return *this;
- }
- /*
- * Véritable opérateur de copie à partir d'un complexe cartésien
- * @param c la référence vers le complex à coller
- * @return la référence vers le nombre complexe courant
- * @post le contenu du complex c est copié dans le complex courant
- */
- template <class T>
- Complex<T> & CComplex<T>::operator =(const CComplex<T> & c)
- {
- // TODO Compléter ...
- return *this;
- }
- /*
- * Opérateur de déplacement à partir d'un complexe
- * @param c la référence d'un autre nombre complexe à déplacer
- * @return la référence vers le nombre complexe courant
- * @post le nombre d'instances n'a pas été changé
- * @post le numéro d'instance de c a été copié dans this en utilisant
- */
- template <class T>
- Complex<T> & CComplex<T>::operator =(Complex<T> && c)
- {
- // TODO Compléter (sans oublier de faire un reset sur c) ...
- return *this;
- }
- /*
- * Opérateur de self addition.
- * @param c le complexe à ajouter au complexe courant
- * @return une référence vers le complexe courant
- */
- template <class T>
- Complex<T> & CComplex<T>::operator +=(const Complex<T> & c)
- {
- // TODO Compléter ...
- return *this;
- }
- /*
- * Opérateur de self soustraction.
- * @param c le complexe à soustraire au complexe courant
- * @return une référence vers le complexe courant
- */
- template <class T>
- Complex<T>& CComplex<T>::operator -=(const Complex<T> & c)
- {
- // TODO Compléter ...
- return *this;
- }
- /*
- * Opérateur de self multiplication.
- * @param c le complexe à multiplier au complexe courant
- * @return une référence vers le complexe courant
- */
- template <class T>
- Complex<T>& CComplex<T>::operator *=(const Complex<T> & c)
- {
- // (a+ ib)*(c +id) = (ac-bd) + i(bc+ad)
- // TODO Compléter ...
- return *this;
- }
- /*
- * Opérateur de self division.
- * @param c le complexe qui divise le complexe courant
- * @return une référence vers le complexe courant
- */
- template <class T>
- Complex<T> & CComplex<T>::operator /=(const Complex<T> & c)
- {
- // (a + ib) ac + bd bc - ad
- // -------- = ----------- + i -----------
- // (c + id) c^2 + d^2 c^2 + d^2
- // TODO Compléter ...
- return *this;
- }
- // ----------------------------------------------------------------------------
- // Operations
- // ----------------------------------------------------------------------------
- /*
- * Opérateur d'addition de deux nombres complexes.
- * @param la référence vers un autre nombre complexe
- * @return un nouveau nombre complexe résultant de l'addition
- */
- template <class T>
- CComplex<T> CComplex<T>::operator +(const CComplex<T> & c) const
- {
- CComplex<T> newComplex(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur d'addition de deux nombres complexes quelconques
- * @param c la référence vers un autre nombre complexe
- * @return un poiteur vers un nouveau nombre complexe résultant de
- * l'addition (La classe Complex<T> étant abstraite, elle ne peut pas
- * avoir d'instances, il faut donc utiliser soit des références, soit
- * des pointeurs)
- */
- template <class T>
- Complex<T> * CComplex<T>::operator +(const Complex<T> & c) const
- {
- Complex<T> * newComplex = new CComplex<T>(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de soustraction de deux nombres complexes
- * @param la référence vers un autre nombre complexe
- * @return un nouveau nombre complexe résultant de l'addition
- */
- template <class T>
- CComplex<T> CComplex<T>::operator -(const CComplex<T> & c) const
- {
- CComplex<T> newComplex(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de soustraction de deux nombres complexes quelconques
- * @param c la référence vers un autre nombre complexe
- * @return un pointeur vers un nouveau nombre complexe résultant de
- * la soustraction
- */
- template <class T>
- Complex<T> * CComplex<T>::operator -(const Complex<T> & c) const
- {
- Complex<T> * newComplex = new CComplex<T>(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de multiplication de deux nombres complexes
- * @param la référence vers un autre nombre complexe
- * @return un nouveau nombre complexe résultant de l'addition
- */
- template <class T>
- CComplex<T> CComplex<T>::operator *(const CComplex<T> & c) const
- {
- CComplex<T> newComplex(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de multiplication de deux nombres complexes quelconques
- * @param c la référence vers un autre nombre complexe
- * @return un pointeur vers un nouveau nombre complexe résultant de
- * la multiplication
- */
- template <class T>
- Complex<T> * CComplex<T>::operator *(const Complex<T> & c) const
- {
- Complex<T> * newComplex = new CComplex<T>(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de division de deux nombres complexes
- * @param la référence vers un autre nombre complexe
- * @return un nouveau nombre complexe résultant de l'addition
- */
- template <class T>
- CComplex<T> CComplex<T>::operator /(const CComplex<T> & c) const
- {
- CComplex<T> newComplex(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Opérateur de division de deux nombres complexes quelconques
- * @param c la référence vers un autre nombre complexe
- * @return un pointeur vers un nouveau nombre complexe résultant de
- * la division
- */
- template <class T>
- Complex<T> * CComplex<T>::operator /(const Complex<T> & c) const
- {
- Complex<T> * newComplex = new CComplex<T>(*this);
- // TODO Compléter (voir sujet p4) ...
- return newComplex;
- }
- /*
- * Inverse d'un complexe cartésien.
- * \f[ \frac{1}{a + ib} = \frac{a - ib}{a^2 + b^2} \f]
- * @return le complexe inversé
- * @throw ComplexException si l'on tente de créer un complexe inverse
- * à partir d'un complexe de parties réelle et imaginaire nulle ce
- * qui entraine une division par zéro.
- */
- template <class T>
- Complex<T> * CComplex<T>::inverse() const throw (ComplexException)
- {
- CComplex<T> * newComplex = NULL;
- // 1 a - ib
- // -------- = ---------
- // (a + ib) a^2 + b^2
- /*
- * TODO Compléter ...
- * En commençant par le calcul du dénominateur car si celui ci est nul
- * il faudra lever une exception comme vous l'avez déjà fait dans
- * Complex<T>::computeArgument
- */
- return newComplex;
- }
- /*
- * Complexe conjugué.
- * \f[ \overline{a + ib} = a - ib \f]
- * @return une référence vers le complexe conjugué
- */
- template <class T>
- Complex<T> * CComplex<T>::conjugate() const
- {
- // conjugate(a+ib) = a-ib
- // TODO remplacer par l'implémentation
- return NULL;
- }
- // ----------------------------------------------------------------------------
- // Affichage
- // ----------------------------------------------------------------------------
- /*
- * Chaine de caractères représentant l'objet
- * @return une chaine de caractères représentant le Complexe
- */
- template <class T>
- string CComplex<T>::toString() const
- {
- // ostringstream s'utilise comme un flux de sortie
- ostringstream outstring;
- /*
- * TODO Compléter par l'ajout dans outstring en utilisant les
- * opérateurs de sortie standard (<<) des différents éléments
- * format à respecter pour les tests : (real + i imag)[instanceNumber]
- */
- outstring << "(" << this->_real << " + i " << this->_imag << ")[" << this->_instanceNumber << "]";
- return outstring.str();
- }
- /*
- * Opérateur d'entrée à partir d'une référence.
- * @pre le Complexe doit déjà exister et est remplit avec les valeurs
- * lue sur le flux d'entrée : on lit d'abord la partie réelle puis la partie
- * imaginaire
- * @param in le flux d'entrée à partir duquel on lit
- * @param c référence vers le Complexe à remplir
- * @return une référence vers le flux d'entrée de manière à pouvoir
- * cumuler les opérateurs
- */
- template <class T>
- istream & operator >>(istream & in, CComplex<T> & c)
- {
- in >> c._real;
- in >> c._imag;
- return in;
- }
- // ----------------------------------------------------------------------------
- // Opérateurs de conversion vers d'autres types de contenus
- // ----------------------------------------------------------------------------
- /*
- * Opérateur de conversion générique d'un CComplex<T> en CCompplex<U>
- * @return une instance de CComplex<U>
- */
- template <class T>
- template <class U>
- CComplex<T>::operator CComplex<U>() const
- {
- // TODO Remplacer par l'implémentation
- return CComplex<U>();
- }
- /*
- * Remise à zéro d'une instance de complexe déplacé
- * @post le numéro d'instance est remis à 0 et les parties réelles
- * et imaginaires sont remises à Complex<T>::ZERO
- */
- template <class T>
- void CComplex<T>::reset()
- {
- /*
- * TODO Compléter par :
- * - reset parent
- * - remise à ZERO des parties réelles et imaginaires
- */
- }
- // ----------------------------------------------------------------------------
- // Instanciations et spécialisations
- // ----------------------------------------------------------------------------
- // proto instanciation du template CComplex pour les double
- template class CComplex<double>;
- // proto instanciation des méthodes templatisées
- template CComplex<double>::CComplex(const Complex<int> &); // int --> double
- template CComplex<double>::CComplex(const Complex<float> &); // float --> double
- template Complex<double> & CComplex<double>::operator =(const Complex<int> &);
- template Complex<double> & CComplex<double>::operator =(const Complex<float> &);
- template CComplex<double>::operator CComplex<int>() const;
- template CComplex<double>::operator CComplex<float>() const;
- // proto instanciation du template CComplex pour les float
- template class CComplex<float>;
- // proto instanciation des méthodes templatisées
- template CComplex<float>::CComplex(const Complex<double> &); // double --> float
- template CComplex<float>::CComplex(const Complex<int> &); // int --> float
- template Complex<float> & CComplex<float>::operator =(const Complex<int> &);
- template Complex<float> & CComplex<float>::operator =(const Complex<double> &);
- template CComplex<float>::operator CComplex<int>() const;
- template CComplex<float>::operator CComplex<double>() const;
- // proto instanciation du template CComplex pour les int
- template class CComplex<int>;
- // proto instanciation des méthodes templatisées
- template CComplex<int>::CComplex(const Complex<double> &); // double --> int
- template CComplex<int>::CComplex(const Complex<float> &); // float --> int
- template Complex<int> & CComplex<int>::operator =(const Complex<float> &);
- template Complex<int> & CComplex<int>::operator =(const Complex<double> &);
- template CComplex<int>::operator CComplex<double>() const;
- template CComplex<int>::operator CComplex<float>() const;
- // instanciation des opérateurs externes sur les templates protoinstanciés
- template istream & operator >>(istream &, CComplex<double> &);
- template istream & operator >>(istream &, CComplex<float> &);
- template istream & operator >>(istream &, CComplex<int> &);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement