// FICHIER : Tableau_T.h
// CLASSE : Tableau_T

// 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:    La classe Tableau_T permet de declarer des tableaux de   *
 *     longueur determinee et dont les composantes sont du type T fixe  *
 *     a la declaration d'un objet de cette classe. L'operateur = doit  *
 *     etre surcharge pour les objets de la classe T.                   *
 *     L'allocation memoire est dynamique et permet de declarer des     *
 *     tableaux de  tailles indifferentes.                              *     
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/

#ifndef TABLEAU_T_H
#define TABLEAU_T_H


//#include "Debug.h"
#include <iostream> 
#include <stdlib.h>
#include <list>

using namespace std;  //introduces namespace std

#include "Sortie.h"
#include <iomanip>
#include <string>


/** @defgroup Les_Tableaux_generiques
*
*     BUT:   groupe des tableaux génériques: typiquement des templates, mais pas seulement
*
*
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       groupe des tableaux génériques: typiquement des templates, mais pas seulement
*
*/

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


template <class T>
class Tableau
{
  
   // surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream & sort, const Tableau<T> & tab)
     { // tout d'abord un indicateur donnant le type
       sort << "Tableau :taille= "  << tab.taille << " "; 
       for (int i=0;i<tab.taille;i++)
        { sort  << setprecision(nb_diggit_double_calcul) << tab.t[i] ; sort << " "; }
//       sort << "\n";    
       return sort;      
     }
     
   // affichage du premier élément pour les messages d'erreur
   friend void Affiche_premier_elem(ostream &sort , const Tableau<T> & tab )
        { if (tab.taille > 0)
           {sort << "\n le premier element du tableau pour info: ";
            sort << tab.t[0] ;
            sort << endl;};
        }

	
	public :

	
		// CONSTRUCTEURS :
		
		// Constructeur par defaut
		Tableau ();
		
		// Constructeur fonction de la taille du tableau
		Tableau (int nb);
		
		// Constructeur fonction de la taille du tableau et d'une 
		// valeur d'initialisation pour les composantes
		Tableau (int nb,T val);
		
		// Constructeur fonction de la taille du tableau et d'une
		// référence: pas facile à faire car ensuite on manipule des pointeurs de références !!
		// bref on ne sait pas ce que l'on fait , dans ce cas il vaut mieux utiliser
		// un tableau de pointeur de la grandeur en question  
		
		// Constructeur fonction d'un tableau de composantes de type T
		Tableau (int nb,T* tab);
		
		// Constructeur de copie
		Tableau (const Tableau<T> & tab);
		
		
		// DESTRUCTEUR :
		
		virtual ~Tableau ();
		
		
		// METHODES :
		
		inline int Taille () const
		// Retourne la taille du tableau
		{ return taille; };	
		
		// Retourne la ieme composante du tableau : acces en lecture et ecriture
		 T& operator() (int i) const;
		 
		// cas particulier ou l'on ne veut pas modifier les valeurs
		const T val_const(int i) const; 
		const T& ref_const(int i) const; 
		
		// Surcharge de l'operateur !=
		// Renvoie 1 si les deux tableaux ne sont pas egaux
		// Renvoie 0 sinon
		int operator!= (const Tableau<T>& tab) const; 
		
		// Surcharge de l'operateur ==
		int operator== (const Tableau<T>& tab) const ;
  
  // egalité  d'une même tranche
  // les  tableaux doivent avoir la même  taille
  int Egalite_tranche(int deb,const Tableau<T> & tab,int fin)const;
		
		// Surcharge de l'operateur d'affectation =
		Tableau<T>& operator= (const Tableau<T>& tab);
		
		// Change la taille du tableau (la nouvelle taille est n)
		void Change_taille (int n);
		// Change la taille du tableau (la nouvelle taille est n)
		// et initialisation de toutes les valeurs, anciennes et nouvelles à tb
		void Change_taille (int n,const T& tb);
		
		// Enleve la ieme composante du tableau
		void Enleve (int i);
		
		// Enleve toutes les composantes du tableau dont la valeur est val
		void Enleve_val (T val);
		
		// Permet de desallouer l'ensemble des elements du tableau
		void Libere ();
 
  // initialisation d'un tableau à partir d'une liste
  // premier du tableau == premier de la liste
  void Init_from_list(const std::list<T> & liste );
  
  // opération inverse: remplissage d'une liste à partir du tableau
  // premier de la liste == premier du tableau
  void Init_list(std::list<T> & liste ) const;

  // opération de lecture sur un flot d'entrée
  // les  données sont le type puis la dimension puis les datas
  istream & Entree(istream &);
  
  // les  données sont le type puis la dimension puis les datas
  // ici il n'y a pas redimentionnement du tableau si la taille est suffisante
  istream & Entree_sans_redim(istream &);
  
  // lectures sur le flot si la taille du tableau est identique ou supérieure à celle lue
  // retour d'un pointeur nulle
  // sinon, si la taille lue est supérieure à la taille du tableau actuellement existant
  // il y a création d'un nouveau tableau de même type avec la taille adéquate
  // et retour d'un pointeur sur le nouveau tableau
  Tableau<T> * New_en_lecture_si_taille_superieur_a_lire(istream &);

  // opération d'écriture non formatée
  // les données sont le type la dimension puis les datas, chacun 
  // séparé par un espace
  ostream & Sortir(ostream &) const ;
  // idem mais sans retour chariot à la fin
  ostream & Sortir_sansRet(ostream &) const;
  
  // test si la valeur passée en argument apartient au tableau
  // ramène 0 si ne contient pas
  // ramène l'indice dans le tableau de la grandeur si appartenance
  // il s'agit du premier élément trouvé à partir de l'élément 1
  int Contient(const T& e) const;
  
  // idem mais dans un intervalle de 1 à max d'indice
  int Contient(const T& e,int max) const;
 
  // initialisation avec la valeur passée en argument
  bool Inita(const T& e) ;
  
		
	protected :

		int taille; // taille du tableau
		T* t; // pointeur sur les composantes du tableau
  // on définit ici le nombre de diggit pour l'affichage de réel double
  static  int nb_diggit_double_calcul; //=17;

		
};
/// @}  // end of group

// cas de la surcharge de la lecture : il y a deux cas a considérer
// 1) cas d'élément constant : dans ce cas la lecture est une erreur
// 2) cas d'élément non constant : lecture permise
// les deux fonctions sont en dehors de la classe car sinon dans la classe il y a pris en compte
// du fait d'avoir des éléments constants ou non ce qui n'a pas l'air évident à traité sinon par
// deux classes différentes 

template <class T>
int Tableau<T>::nb_diggit_double_calcul=17;


template <class T>
// surcharge de l'operator de lecture d'élément non constant
 istream & operator >> (istream & entree, Tableau<T> & tab)
  { // vérification du type
    string type;
    entree >> type;
    if (type != "Tableau")
      {Sortie (1);
       return entree;
      };
    int dim; entree >> type >> dim;
    int tabtaille = tab.Taille();
    if (dim != tabtaille)
      tab.Change_taille(dim); 
    for (int i=1;i<=dim;i++)
        entree >> tab(i);
    return entree;      
  }

//=================================   def des differents elements ==================


template <class T>
inline Tableau<T>::Tableau ()
// Constructeur par defaut
{   taille=0;
	t=NULL;	
}


template <class T>
inline Tableau<T>::Tableau (int nb)
// Constructeur devant etre utilise quand la dimension nb du tableau est connu
{
   #ifdef MISE_AU_POINT
	if ( nb<0 )
	// cas ou la taille selectionnee est negative
	{	cout << "\nErreur : taille invalide !\n";
		cout << "TABLEAU_T::TABLEAU_T(int ) \n";
		Sortie(1);
	};
   #endif    		
	if ( nb==0 )
	// cas ou la taille selectionnee est nulle : initialisation identique a 
	// l'appel du constructeur par defaut
	{	taille=0;
		t=NULL;
	}
	else
	// autres cas
	{	taille=nb;
		t=new T [taille]; // allocation de la place memoire
		T* ptr=t;
		for (int i=0;i<taille;i++)
		// initialisation des composantes a l'aide de l'attribut statique defaut
		//	(*ptr++)=defaut;
		(*ptr++)= T();
	};	
}

template <class T>
inline Tableau<T>::Tableau (int nb, T val)
// Constructeur permettant de creer un tableau dont toutes les composantes
// sont egales a val
// N.B: La valeur de l'attribut defaut est fixee a val
{	// initialisation de l'element defaut 
   #ifdef MISE_AU_POINT
    if ( nb<0 )
    // cas ou la taille selectionnee est negative
    {	cout << "\nErreur : taille invalide !\n";
     cout << "TABLEAU_T::TABLEAU_T(int ,T ) \n";
     Sortie(1);
    };
   #endif
    if ( nb==0 )
      // cas ou la taille selectionnee est nulle : initialisation identique a
      // l'appel du constructeur par defaut
      {	taille=0;
       t=NULL;
      }
    else
      // autres cas
      {	taille=nb;
       t=new T [taille]; // allocation de la place memoire
       T* ptr=t;
       for (int i=0;i<taille;i++)
       // initialisation des composantes a val
        (*ptr++)=val;
      };
}

template <class T>
inline Tableau<T>::Tableau (int nb,T* tab)
// Constructeur permettant de creer un tableau de taille nb dont les composantes
// sont initialisees a l'aide des valeurs de tab
// N.B.: tab doit avoir au moins nb composantes (aucun test n'est realise pour le 
// verifier !!!)
{ 
   #ifdef MISE_AU_POINT
	if ( nb<0 )
	// cas ou la taille selectionnee est negative
	{	cout << "\nErreur : taille invalide !\n";
		cout << "TABLEAU_T::TABLEAU_T(int ,T* ) \n";
		Sortie(1);
	};
   #endif    		
	if ( nb==0 )
	// cas ou la taille selectionnee est nulle : initialisation identique a 
	// l'appel du constructeur par defaut
	{
		taille=0;
		t=NULL;
	}
	else
	// autres cas
	{
		taille=nb;
		t=new T [taille]; // allocation de la place memoire
		T* ptr1=t;
		T* ptr2=tab;
		for (int i=0;i<taille;i++)
		// copie des composantes du tableau tab dans le tableau declare
			(*ptr1++)=(*ptr2++);
	};	
}	

template <class T>
inline Tableau<T>::Tableau (const Tableau<T>& tab)
// Constructeur de copie
{	if ( tab.taille==0 )
	// cas ou le tableau copie est vide : initialisation identique a l'appel
	// du constructeur par defaut
	{	t=NULL;
		taille=0;
	}
	else
	// autres cas
	{	t=new T [tab.taille]; // allocation de la place memoire
		T* ptr1=t;
		T* ptr2=tab.t;
		for (int i=0;i<tab.taille;i++)
		// copie des composantes du tableau tab dans le tableau declare
			(*ptr1++)=(*ptr2++);
		taille=tab.taille;
	};	
}
	
template <class T>
inline Tableau<T>::~Tableau ()
// Destructeur (N.B. : Apres l'appel de ce destructeur le tableau est identique 
// a ce qu'il aurait ete a la suite d'un appel du constructeur par defaut)
{	Libere(); }

template <class T> void 
inline Tableau<T>::Change_taille (int n)
// Permet de modifier la taille du tableau
// N.B. : Si la nouvelle taille est superieure a l'ancienne alors le tableau est 
// complete par defaut
{
   #ifdef MISE_AU_POINT
	if ( n<0 )
	// cas ou la taille selectionnee est negative
	{	cout << "\nErreur : taille invalide !\n";
		 cout << "TABLEAU_T::CHANGE_TAILLE(int ) \n";
   cout << " NB: taille actuelle = "  << taille << " ";
		Sortie(1);
	}
   #endif	
	if ( n == taille ) // taille identique , on ne fait rien
	  return;
	if ( n==0 )
	// cas ou la taille selectionnee est nulle : initialisation identique a 
	// l'appel du constructeur par defaut
	{
		taille=0;
		if ( t!= NULL) delete [] t;
		t=NULL;
		return ;
	};
	T* tempo;
	tempo=new T [n];
	T* ptr1=t;
	T* ptr2=tempo;
	if ( n<=taille )
	// cas ou la taille selectionnee est inferieure a la taille d'origine
	{
		for (int i=0;i<n;i++)
		// copie des composantes du tableau d'origine dans le tableau pointe par tempo
			(*ptr2++)=(*ptr1++); 
	}
	else if ( n>taille )
	// cas ou la taille selectionnee est superieure a la taille d'origine
	{
		for (int i=0;i<taille;i++)
		// copie des composantes du tableau d'origine dans le tableau pointe par tempo
			(*ptr2++)=(*ptr1++);
		for (int i=taille;i<n;i++)
		// initialisation des composantes supplementaires a l'aide de l'element par defaut
			///(*ptr2++)=defaut;
			(*ptr2++)=T();
	};
	delete [] t; // desallocation du tableau pointe par t
	t=tempo; // affectation du pointeur t au pointeur tempo
	taille=n;
	
}
	
template <class T> void 
inline Tableau<T>::Change_taille (int n,const T& tb)
// Change la taille du tableau (la nouvelle taille est n)
// et initialisation de toutes les valeurs, anciennes et nouvelles à tb
{
   #ifdef MISE_AU_POINT
	if ( n<0 )
	// cas ou la taille selectionnee est negative
	{	cout << "\nErreur : taille invalide !\n";
		 cout << "TABLEAU_T::CHANGE_TAILLE(int ) \n";
   cout << " NB: taille actuelle = "  << taille << " ";
		 Sortie(1);
	}
   #endif	
	if ( n == taille ) // taille identique , on ne fait que l'initialisation
	  { T* ptr2= t;
		for (int i=0;i<n;i++)
		// copie des composantes à tb
			(*ptr2++)=tb;
	    return;		
	   }	
	  
	if ( n==0 )
	// cas ou la taille selectionnee est nulle : initialisation identique a 
	// l'appel du constructeur par defaut
	{
		taille=0;
		if ( t!= NULL) delete [] t;
		t=NULL;
		return ;
	};
	T* tempo;
	tempo=new T [n];
	T* ptr2=tempo;
	if ( n<=taille )
	// cas ou la taille selectionnee est inferieure a la taille d'origine
	{
		for (int i=0;i<n;i++)
		// copie des composantes du tableau d'origine dans le tableau pointe par tempo
			(*ptr2++)=tb; 
	}
	else if ( n>taille )
	// cas ou la taille selectionnee est superieure a la taille d'origine
	{
		for (int i=0;i<n;i++)
		// copie des composantes à tb
			(*ptr2++)=tb;
	};
	delete [] t; // desallocation du tableau pointe par t
	t=tempo; // affectation du pointeur t au pointeur tempo
	taille=n;	
}

template <class T>  
#ifndef MISE_AU_POINT
	inline 
#endif    					
T& Tableau<T>::operator() (int i) const
		// Retourne la ieme composante du tableau : acces en lecture et ecriture
		{
   #ifdef MISE_AU_POINT
		 if ( (i<1) || (i>taille) )
     {	cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
       cout << "T&  TABLEAU_T::OPERATOR() (int ) \n";
       cout << "\n  pour info: taille actuelle du tableau = "  << taille << " ";
       Sortie(1);
     };
		 #endif
   return t[i-1];
		}
		
		// cas particulier ou l'on ne veut pas modifier les valeurs 
template <class T>  
#ifndef MISE_AU_POINT
	inline 
#endif    					
const T Tableau<T>::val_const(int i) const 
//const T& Tableau<T>::operator() (int i) const 
		// Retourne la ieme composante du tableau : acces en lecture seulement
		{
   #ifdef MISE_AU_POINT
		 if ( (i<1) || (i>taille) )
     {	cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
       cout << "T TABLEAU_T::OPERATOR() (int )  const \n";
       cout << "\n  pour info: taille actuelle du tableau = "  << taille << " ";
       Sortie(1);
     };
		 #endif
		 T retour = t[i-1];    					
   return retour;
		}
		
// Retourne la référence constante à la ieme composante du tableau : acces en lecture seulement
template <class T>  
#ifndef MISE_AU_POINT
	inline 
#endif    					
const T& Tableau<T>::ref_const(int i) const 
//const T& Tableau<T>::operator() (int i) const 
		// Retourne la ieme composante du tableau : acces en lecture seulement
		{
   #ifdef MISE_AU_POINT
		 if ( (i<1) || (i>taille) )
    {	cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
      cout << "T TABLEAU_T::OPERATOR() (int )  const \n";
      cout << "\n  pour info: taille actuelle du tableau = "  << taille << " ";
      Sortie(1);
    };
		 #endif
   return t[i-1];
		}

template <class T>  
#ifndef MISE_AU_POINT
	inline 
#endif    					
int Tableau<T>::operator!= (const Tableau<T>& tab) const 
		// Surcharge de l'operateur !=
		// Renvoie 1 si les deux tableaux ne sont pas egaux
		// Renvoie 0 sinon
		{	if ( (*this)==tab ) // test de l'egalite des deux tableaux a l'aide
								// de l'operateur surcharge ==
				  return 0;
			 else
				  return 1;
		}
		
template <class T> void
inline Tableau<T>::Enleve (int i)
// Enleve la ieme composante du tableau en decrementant la taille
{
 #ifdef MISE_AU_POINT
	if ( (i<1) || (i>taille) )
   {
    cout << "\nErreur : composante inexistante "<<i<< " !\n";
    cout << "TABLEAU_T::ENLEVE(int ) \n";
    cout << "\n  pour info: taille actuelle du tableau = "  << taille << " ";
    Sortie(1);
   };
 #endif
 T* tempo;
	tempo=new T [taille-1];
	T* ptr1=t;
	T* ptr2=tempo;
	for (int j=0;j<i-1;j++)
	// copie des elements du tableau pointe par t dans le tableau pointe par tempo 
	// du 1er au (i-1)eme element 
		(*ptr2++)=(*ptr1++);
	ptr1++; // saut du ieme element du tableau pointe par t
	for (int j=i;j<taille;j++)
	// copie des elements du tableau pointe par t dans le tableau pointe par tempo 
	// du (i+1)eme au dernier element 
		(*ptr2++)=(*ptr1++);
	delete [] t; // desallocation du tableau pointe par t
	t=tempo; // affectation du pointeur t au pointeur tempo
	taille=taille-1;
}
	
template <class T> void
inline Tableau<T>::Enleve_val (T val)
// Enleve les composantes du tableau egales a val en decrementant la taille
{
	
	T* tempo;
	tempo=new T [taille];
	T* ptr1=t;
	T* ptr2=tempo;
	int nouvel_taille=taille;
	for (int j=0;j<taille;j++)
   // boucle sur les composantes du tableau
   {
    if ( (*ptr1)!=val )
      // l'objet pointe n'est pas egal a val
      (*ptr2++)=(*ptr1++);
    else 
      // l'objet pointe est egal a val, saut de celui-ci
      {
       ptr1++;
       nouvel_taille=nouvel_taille-1;
      };
	  };

 #ifdef MISE_AU_POINT
	if ( nouvel_taille==taille )
   {
    cout << "\nErreur : absence de la composante cherchee !\n";
    cout << "TABLEAU_T::ENLEVE_VAL(T ) \n";
    Sortie(1);
   };
 #endif
 delete [] t; // desallocation du tableau pointe par t
	t=tempo; // affectation du pointeur t au pointeur tempo
	taille=nouvel_taille;
	
}	
	
template <class T> void
inline Tableau<T>::Libere ()
// Apres l'appel de cette methode, le tableau est identique a ce qu'il aurait 
// ete a la suite d'un appel du constructeur par defaut
{
	if ( taille>0 )
		delete [] t; // desallocation du tableau pointe par t
	else
  {
   #ifdef MISE_AU_POINT
   if ( t!=NULL )
    { cout << "\nErreur de liberation de la place memoire\n";
      cout << "TABLEAU_T::LIBERE() \n";
//      Affiche_premier_elem( cout);
      Sortie(1);
    }
   #endif
	 };
	t=NULL;
	taille=0;
}

template <class T> void
inline Tableau<T>::Init_from_list(const std::list<T> & liste )
// initialisation d'un tableau à partir d'une liste
{ int tail_liste = liste.size(); // récup de la tail de la liste
  typename std::list<T>::const_iterator ili,ilifin=liste.end();
  Change_taille(tail_liste);
  int i=0;
  for (ili=liste.begin();ili!=ilifin;ili++,i++)
   t[i] = (*ili);
}

template <class T> void
inline Tableau<T>::Init_list(std::list<T> & liste ) const
// initialisation d'une liste à partir du tableau
// premier de la liste == premier du tableau
{ liste.clear(); // on initialise la liste
  // on balaie le tableau et on remplit la liste
  T* ptr1=t;
  for (int i=0;i<taille;i++)
    liste.push_back(*ptr1++);
}


template <class T> 
inline Tableau<T> & Tableau<T>::operator= (const Tableau<T> & tab)
// Surcharge de l'operateur = : realise l'egalite entre deux tableaux de pointeurs
{
	// on essaie d'optimiser un peu
	// -- si les tableaux sont identiques en taille, on ne réaffecte pas
	// on ne fait que la recopie
	if (taille == tab.taille)
	 { // on n'examine que si la taille est non nulle
	   if (taille != 0)
		  { T* ptr1=t;
		    T* ptr2=tab.t;
		    for (int i=0;i<taille;i++)
        // copie des elements du tableau se trouvant a droite dans le tableau se trouvant
        // a gauche du signe d'affectation
       (*ptr1++)=(*ptr2++);
		  };
		  // et retour
	    return (*this);  
	 };
	// sinon on réajuste les tailles 	
	if ( t!=NULL ) Libere(); // cas ou le tableau se trouvant a gauche du signe =
							// n'est pas vide : desallocation de ce tableau
	if ( tab.taille==0 )
	// cas ou le tableau se trouvant a droite du signe = est vide : initialisation
	// identique a l'appel du constructeur par defaut
   {
    taille=0;
    t=NULL;
   }
	else
	// autres cas
   {
    taille=tab.taille;
    t=new T [taille];
    T* ptr1=t;
    T* ptr2=tab.t;
    for (int i=0;i<taille;i++)
    // copie des elements du tableau se trouvant a droite dans le tableau se trouvant
    // a gauche du signe d'affectation
     (*ptr1++)=(*ptr2++);
   };
	return (*this);
	
}

template <class T> 
inline int Tableau<T>::operator ==(const Tableau<T> & tab) const 
// Surcharge de l'operateur ==
// Renvoie 1 si les deux tableaux sont egaux
// Renvoie 0 sinon
{
	
	if ( tab.taille!=taille )
		return 0;
	else
  {
   T* ptr1=t;
   T* ptr2=tab.t;
   for (int i=0;i<taille;i++)
    {
     if ( (*ptr2++)!=(*ptr1++) )
      return 0;
    };
   return 1;
  };
	
}

// egalité  d'une même tranche
// les  tableaux doivent avoir la même  taille
template <class T>
inline int Tableau<T>::Egalite_tranche(int deb,const Tableau<T> & tab,int fin)const
// Renvoie 1 si les tranches sont égales
// Renvoie 0 sinon
{
 #ifdef MISE_AU_POINT
 if (( deb  < 1 )||(deb > taille))
  { cout << "\nErreur l'indice de debut de tranche: "<< deb << " est inf 1 ou sup  taille: "<<  taille;
    cout << "\n TABLEAU_T::Egalite_tranche(.. \n";
    Sortie(1);
  }
 if ( fin  > taille )
  { cout << "\nErreur l'indice de fin de tranche: "<< fin << " est sup taille: "<< taille;
    cout << "\n TABLEAU_T::Egalite_tranche(.. \n";
    Sortie(1);
  }
 #endif

 if ( tab.taille!=taille )
  return 0;
 else
  {
   T* ptr1=t;
   T* ptr2=tab.t;
   for (int i=deb-1;i< fin;i++)
    {
     if ( (*ptr2++)!=(*ptr1++) )
      return 0;
    };
   return 1;
  };
 
}



// opération de lecture sur un flot d'entrée
// les  données sont le type puis la dimension puis les datas
template <class T> 
inline istream & Tableau<T>::Entree(istream & entree)
  { // vérification du type
    string type;
    entree >> type;
    if (type != "Tableau")
      {cout <<"\n *** erreur en lecture d'un tableau, on attendait Tableau "
            << " et on a lue "<< type << endl;
       Sortie (1);
       return entree;
       }
    int dime; entree >> type >> dime;
    if (dime != taille)
      Change_taille(dime); 
    for (int i=0;i<taille;i++)
        entree >> t[i];
    return entree;      
  }
  
// opération de lecture sur un flot d'entrée sans redimentionnement
// les  données sont le type puis la dimension puis les datas
// ici il n'y a pas redimentionnement du tableau si la taille est suffisente
template <class T> 
inline istream & Tableau<T>::Entree_sans_redim(istream & entree)
  { // vérification du type
    string type;
    entree >> type;
    if (type != "Tableau")
      {Sortie (1);
       return entree;
       }
    int dime; entree >> type >> dime;
    if (dime > taille) // redimensionnement que si la taille est insuffisente 
      Change_taille(dime); 
    for (int i=0;i<taille;i++)
        entree >> t[i];
    return entree;      
  }

// lectures sur le flot si la taille du tableau est identique ou supérieure à celle lue
// retour d'un pointeur nulle
// sinon, si la taille lue est supérieure à la taille du tableau actuellement existant
// il y a création d'un nouveau tableau de même type avec la taille adéquate
// et retour d'un pointeur sur le nouveau tableau
template <class T> 
inline Tableau<T> * Tableau<T>::New_en_lecture_si_taille_superieur_a_lire(istream& entree)
  { Tableau<T> * pt_tableau = NULL; // init au cas courant
    // vérification du type
    string type;
    entree >> type;
    if (type != "Tableau")
      {Sortie (1);
       return pt_tableau;
       }
    int dime; entree >> type >> dime;
    if (dime > taille) 
     { // on crée un nouveau tableau
       pt_tableau = new Tableau<T>(dime);
       for (int i=0;i<dime;i++)
        entree >> pt_tableau->t[i];
      }
    else
     { // cas d'une dimension suffisante 
       for (int i=0;i<dime;i++)
          entree >> t[i];
      };    
    return pt_tableau;      
  }
  
// opération d'écriture non formatée
// les données sont le type la dimension puis les datas, chacun 
// séparé par un espace
template <class T> 
inline ostream & Tableau<T>::Sortir( ostream & sort) const
  { // tout d'abord un indicateur donnant le type
    sort << "Tableau :taille= "  << taille << " "; 
    for (int i=0;i<taille;i++)
        sort << t[i] << " ";
    sort << "\n";    
    return sort;      
  }
  
// opération d'écriture non formatée, idem précédent mais sans retour chariot à la fin
// les données sont le type la dimension puis les datas, chacun 
// séparé par un espace
template <class T> 
inline ostream & Tableau<T>::Sortir_sansRet( ostream & sort) const
  { // tout d'abord un indicateur donnant le type
    sort << "Tableau :taille= "  << taille << " "; 
    for (int i=0;i<taille;i++)
        sort << t[i] << " ";
    return sort;      
  }
        
// test si la valeur passée en argument apartient au tableau
// ramène 0 si n'appartient pas sinon ramène l'indice dans le tableau
// du premier élément trouvé à partir de l'élément 1
// t(i) = t[i+1]
template <class T> 
inline int Tableau<T>::Contient(const T& e) const
 {  for (int i=0;i<taille;i++)
        if (t[i] == e) {return (i+1);}
    return 0;
 }

 // idem mais dans un intervalle de 1 à max d'indice
template <class T>
inline int Tableau<T>::Contient(const T& e,int max) const
 {  for (int i=0;i<max;i++)
        if (t[i] == e) {return (i+1);}
    return 0;
 }

// initialisation avec la valeur passée en argument
template <class T> 
inline bool Tableau<T>::Inita(const T& e)
  { for (int i=0;i<taille;i++)
      t[i] = e;
    return true; // par défaut
  };

//// affichage du premier élément pour les messages d'erreur
//template <class T>
//inline void Tableau<T>::Affiche_premier_elem( ostream & sort) const
//  { // on indique quelque infos sup pour la compréhension
//    sort << "Tableau :taille= "  << taille << " ";
//    if (taille >0)
//     {sort << "\n le premier element du tableau pour info: ";
//      sort << t[0] ;
//      sort << endl;};
//  }


//#include "ParaGlob.h"

#endif