
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *                                                                      *
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:         une spécialisation du tableau en incluant une       *
 *     surchage d'opérateurs courants. Le template n'est pas utilisable *
 *     par tous les objets: ces derniers doivent posséder également     *
 *     les surcharges correspondantes.                                  *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                      *
 *                                                                $     *
 *                                                                      *
 ************************************************************************/ 


#ifndef TABOPER_T_H
#define TABOPER_T_H


#include "Tableau_T.h"


/// @addtogroup Les_Tableaux_generiques
///  @{
///


template <class T>
class TabOper : public Tableau<T>
{

	
	public :

	
		// CONSTRUCTEURS :
		
		// Constructeur par defaut
		TabOper () : Tableau<T>() {};
		
		// Constructeur fonction de la taille du tableau
		TabOper (int nb) : Tableau<T>(nb) {};
		
		// Constructeur fonction de la taille du tableau et d'une 
		// valeur d'initialisation pour les composantes
		TabOper (int nb,T val) : Tableau<T>(nb,val) {};
		
		// Constructeur fonction d'un tableau de composantes de type T
		TabOper (int nb,T* tab) : Tableau<T>(nb,tab) {} ;
		
		// Constructeur de copie
		TabOper (const TabOper<T> & tab) : Tableau<T>(tab) {} ;
		
		
		// DESTRUCTEUR :
		
		~TabOper (){};

		// METHODES :
		// Surcharge de l'operateur + : addition entre deux tableaux	
		TabOper<T> operator+ (const TabOper<T>& vec);
		
		// Surcharge de l'operateur - : soustraction entre deux tableaux 
		TabOper<T> operator- (const TabOper<T>& vec);
		
		// Surcharge de l'operateur - : oppose d'un tableau 
		//TabOper operator- ();
        TabOper<T> operator- ();

		// Surcharge de l'operateur +=
		void operator+= (const TabOper<T>& vec);
		
		// Surcharge de l'operateur -=
		void operator-= (const TabOper<T>& vec);
		
		// Surcharge de l'operateur *= : multiplication d'un scalaire par un tableau
		void operator*= (double val);		
		
		// Surcharge de l'operateur * : multiplication d'un vecteur par un scalaire
		//TabOper<T> operator* (double val);
        inline TabOper<T> operator* (double val);
		
		// Surcharge de l'operateur / : division des composantes d'un vecteur par un scalaire
		TabOper<T> operator/ (double val);
		
		// Surcharge de l'operateur /= : division des composantes d'un vecteur par un scalaire
		void operator/= (double val);
				
		// mise a zero d'un vecteur
		 void Zero();  
		
};
/// @}  // end of group

template <class T>  
 TabOper<T> operator* (double val,TabOper<T>& vec)
// Surcharge de l'operateur * : multiplication entre un scalaire et un tableau
{	return (vec*val);   };


template <class T> TabOper<T>  
TabOper<T>::operator+ (const TabOper<T>& vec)
// Surcharge de l'operateur + : addition entre deux tableaux
// N.B.: Les tableaux doivent etre de meme taille
{	
   #ifdef MISE_AU_POINT
    if ( this->taille!=vec.taille )
	{	cout << "\nErreur : tailles non egales !\n";
		cout << "TabOper::OPERATOR+ (TabOper ) \n";
		Sortie(1);
	};
   #endif
	TabOper result(this->taille);
	T* ptr1=this->t;
	T* ptr2=vec.t;
	T* ptr3=result.t;
	for (int i=0;i<this->taille;i++)
	// somme des composantes des deux tableaux vec et v, puis stockage
	// dans le tableau result
		(*ptr3++)=(*ptr1++)+(*ptr2++);
	return result;	
}

template <class T> TabOper<T>  
TabOper<T>::operator- (const TabOper<T>& vec)
// Surcharge de l'operateur - : soustraction entre deux tableaux
// N.B.: Les tableaux doivent etre de meme taille
{	
   #ifdef MISE_AU_POINT
    if ( this->taille!=vec.taille )
	{	cout << "\nErreur : tailles non egales !\n";
		cout << "TabOper::OPERATOR- (TabOper ) \n";
		Sortie(1);
	};
   #endif
	TabOper result(this->taille);
	T* ptr1=this->t;
	T* ptr2=vec.t;
	T* ptr3=result.t;
	for (int i=0;i<this->taille;i++)
	// soustraction des composantes des tableaux vec et v, puis stockage
	// dans le tableau result
		(*ptr3++)=(*ptr1++)-(*ptr2++);
	return result;
}

template <class T> TabOper<T>  
TabOper<T>::operator- ()
// Surcharge de l'operateur - : oppose d'un tableau 
{	TabOper result(this->taille);
	T* ptr1=this->t;
	T* ptr2=result.t;
	for (int i=0;i<this->taille;i++)
		(*ptr2++)=-(*ptr1++);
	return result;	
}

template <class T> void
TabOper<T>::operator+= (const TabOper<T>& vec)
// Surcharge de l'operateur += : additionne au tableau courant le tableau vec
// N.B.: Les tableaux doivent etre de meme taille
{
   #ifdef MISE_AU_POINT
	if ( this->taille!=vec.taille )
	{	cout << "\nErreur : tailles non egales !\n";
		cout << "TabOper::OPERATOR+= (TabOper ) \n";
		Sortie(1);
	};
   #endif
	T* ptr1=this->t;
	T* ptr2=vec.t;
	for (int i=0;i<this->taille;i++)
		(*ptr1++)+=(*ptr2++);		
}

template <class T> void
TabOper<T>::operator-= (const TabOper<T>& vec)
// Surcharge de l'operateur -= : soustrait au tableau courant le tableau vec
// N.B.: Les tableaux doivent etre de meme taille
{
   #ifdef MISE_AU_POINT
	if ( this->taille!=vec.taille )
	{	cout << "\nErreur : tailles non egales !\n";
		cout << "TabOper::OPERATOR-= (TabOper ) \n";
		Sortie(1);
	};
   #endif
	T* ptr1=this->t;
	T* ptr2=vec.t;
	for (int i=0;i<this->taille;i++)
		(*ptr1++)-=(*ptr2++);		
}		

template <class T> void
TabOper<T>::operator*= (double val)
// Surcharge de l'operateur *= : multiplie les composantes du tableau courant par
// le scalaire val
// N.B.: Les tableaux doivent etre de meme taille
{	T* ptr=this->t;
	for (int i=0;i<this->taille;i++)
		(*ptr++)*=val;		
}	



template <class T> TabOper <T> 
TabOper<T>::operator* (double val)
// Surcharge de l'operateur * : multiplication d'un tableau par un scalaire
{	
   #ifdef MISE_AU_POINT
    if ( this->taille==0 )
	{	cout << "\nErreur : taille nulle !\n";
		cout << "TabOper::OPERATOR* (T ) \n";
		Sortie(1);
	};
   #endif
	TabOper result(this->taille);
	T* ptr1=this->t;
	T* ptr2=result.t;
	for (int i=1;i<=this->taille;i++)
	// stockage dans le tableau result du produit des composantes du tableau courant
	// avec val
		(*ptr2++)=val*(*ptr1++);
	return result;	
}

template <class T> TabOper<T>  
TabOper<T>::operator/ (double val)
// Surcharge de l'operateur / : division des composantes d'un tableau par un scalaire
{
   #ifdef MISE_AU_POINT
	if ( (this->taille==0) || (val==0) )
	{	cout << "\nErreur : taille nulle ou division par zero !\n";
		cout << "TabOper::OPERATOR/ (T ) \n";
		Sortie(1);
	};
   #endif
	TabOper result(this->taille);
	T* ptr1=this->t;
	T* ptr2=result.t;
	for (int i=1;i<=this->taille;i++)
	// stockage dans le tableau result de la division des composantes du tableau courant
	// avec val
		(*ptr2++)=(*ptr1++)/val;
	return result;	
}

template <class T> void 
TabOper<T>::operator/= (double val)
// Surcharge de l'operateur / : division des composantes d'un tableau par un scalaire
{
   #ifdef MISE_AU_POINT
	if ( (this->taille==0) || (val==0) )
	{	cout << "\nErreur : taille nulle ou division par zero !\n";
		cout << "TabOper::OPERATOR/ (T ) \n";
		Sortie(1);
	};
   #endif
 	T* ptr=this->t;
	for (int i=0;i<this->taille;i++)
		(*ptr++) /= val;		
}
	
template <class T>  
// mise a zero d'un tableau
void TabOper<T>::Zero()
 {		T* ptr=this->t;
		for (int i=0;i<this->taille;i++)
		// affectation des composantes du tableau a 0
			(*ptr++)=0.0;
 }  


#endif
