

// 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-2021 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/>.


# include <iostream>
using namespace std;  //introduces namespace std
//#include "Debug.h"
#include "Tenseur1.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include <iomanip>

#ifndef  Tenseur1_H_deja_inclus
//================================================================  
// deux fois contravariants HH
//================================================================  

#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HH::Tenseur1HH():  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = 0.; };
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HH::Tenseur1HH(double val):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = val; };

#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HH::~Tenseur1HH()
  {  listdouble1.erase(ipointe); // suppression de l'élément de la liste
  //  cout << " appel du destructeur de 1HH \n"; 
  }; 
// constructeur a partir d'une instance non differenciee  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HH::Tenseur1HH (const TenseurHH & B):  
 ipointe()
  { dimension = 1;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::Tenseur1HH ( etc..");
     #endif
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *(this->t) = *(B.t);
  };     
// constructeur de copie  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HH::Tenseur1HH ( const Tenseur1HH & B):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *(this->t) = *(B.t);
  };     
// initialise toutes les composantes à val
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1HH::Inita(double val)
  {*(this->t) =val;};   
// operations 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator + ( const TenseurHH & B) const 
  {  TenseurHH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator + ( etc..");
     #endif
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) + *(B.t); //somme des données
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HH::operator += ( const TenseurHH & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator += ( etc..");
     #endif
     *(this->t) += *(B.t);}; //somme des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator - () const 
  {  TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = - *(this->t); //oppose
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator - ( const TenseurHH & B) const 
  {  TenseurHH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator - ( etc..");
     #endif
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) - *(B.t); //soustraction des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HH::operator -= ( const TenseurHH & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator -= ( etc..");
     #endif
     *(this->t) -= *(B.t);}; //soustraction des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator = ( const TenseurHH & B)
  { *(this->t) = *(B.t); //affectation des données
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator = ( etc..");
     #endif
    LesMaillonsHH::Libere(); // destruction des tenseurs intermediaires
    return *this; };
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator * ( const double & b) const 
  {  TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) * b; //multiplication des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HH::operator *= ( const double & b)
  { *(this->t) *= b;}; //multiplication des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator / ( const double & b) const 
  {  TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) / b; //division des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HH::operator /= ( const double & b)
  { *(this->t) /= b;}; //division des données
// produit contracte avec un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
CoordonneeH Tenseur1HH::operator * ( const CoordonneeB & B) const 
  { 
    #ifdef MISE_AU_POINT	 	 
	 if (B.Dimension() != dimension)
	    { cout << "\nErreur : dimensions vecteur tenseur non egales !\n";
		  cout << " Tenseur1HH::operator *\n";
		  Sortie(1);
		};
    #endif
    CoordonneeH v(dimension);
    v(1) = *(this->t) * B(1);
    return v;
  };    
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::operator * ( const TenseurBH & B) const 
  {  TenseurHH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator * ( etc..");
     #endif
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HH::operator * ( const TenseurBB & B) const 
  {  TenseurHB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator * ( etc..");
     #endif
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  };  
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HH::operator && ( const TenseurBB & B) const 
  { double result;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator && ( etc..");
     #endif
    result =  (*(this->t)) * (*(B.t)); // contraction
    return result;};
// test
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1HH::operator == ( const TenseurHH & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator == ( etc..");
     #endif
     if (*(this->t) != *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1HH::operator != ( const TenseurHH & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HH::operator + ( etc..");
     #endif
     if (*(this->t) == *(B.t))
         return 0 ;
      else
         return 1;};
// calcul du determinant des coordonnees du tenseur
#ifndef MISE_AU_POINT
  inline 
#endif
double Tenseur1HH::Det() const 
  { return *(this->t) ;};         
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1HH::Inverse() const 
  { TenseurBB * res;
    res =  new Tenseur1BB;
    LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
#ifdef MISE_AU_POINT	 	 
	if  (Dabs(*(this->t)) <= ConstMath::trespetit)
			{ cout << "\nErreur : la coordonnee du tenseur est nulle !\n";
			  cout << "Tenseur1HH::Inverse() \n";
			  Sortie(1);
			};
#endif    
    *(res->t) = 1./ (*(this->t));
    return *res;
  };                
             
#ifndef MISE_AU_POINT
  inline 
#endif
// affectation de B dans this,  plusZero = false: les données manquantes sont inchangées,
// plusZero = true: les données manquantes sont mises à 0
// si au contraire la dimension de B est plus grande que *this, il y a uniquement affectation
// des données possibles
void Tenseur1HH::Affectation_trans_dimension(const TenseurHH & B,bool plusZero)
{ // dans tous les cas il suffit de récupérer le premier élément et de l'affecter
  this->t[0] = B.t[0]; //on affecte le seul terme disponible
};

#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::Transpose() const 
   { TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           
    // ---- manipulation d'indice ---- -> création de nouveaux tenseurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB& Tenseur1HH::Baisse2Indices() const
   { TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH& Tenseur1HH::BaissePremierIndice() const
   { TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           

#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB& Tenseur1HH::BaisseDernierIndice() const
   { TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           

//fonctions static définissant le produit tensoriel de deux vecteurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HH::Prod_tensoriel(const CoordonneeH & aH, const CoordonneeH & bH)
  {  TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = aH(1)*bH(1); 
     return *res;}; 
	 
	 // lecture et écriture de données
#ifndef MISE_AU_POINT
  inline 
#endif
istream & Tenseur1HH::Lecture(istream & entree)
  { // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1HH")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*(this->t));
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
ostream & Tenseur1HH::Ecriture(ostream & sort) const 
  { // écriture du type
    sort << "Tenseur1HH ";
    // puis les datas
    sort  << setprecision (ParaGlob::NbdigdoCA()) <<   (*(this->t)) << " ";
     return sort;      
  };

#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator de lecture
istream & operator >> (istream & entree, Tenseur1HH & A)
  { int dim = A.Dimension();
     #ifdef MISE_AU_POINT
       if (dim != 1) A.Message(1,"operator >> (istream & entree, Tenseur1HH & A)");
    #endif
    // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1HH")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*A.t);
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort , const Tenseur1HH & A)
  { // écriture du type
    sort << "Tenseur1HH ";
    // puis les datas
    sort  << setprecision (ParaGlob::NbdigdoCA()) <<   (*A.t) << " ";
     return sort;      
  };
      
//================================================================  
//  mixtes deux fois covariant  BB
//================================================================
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BB::Tenseur1BB():  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = 0.; };
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BB::Tenseur1BB(const double val):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = val; };

#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BB::~Tenseur1BB()
  {  listdouble1.erase(ipointe); // suppression de l'élément de la liste
 //   cout << " appel du destructeur de 1BB \n";
 }; 
// constructeur a partir d'une instance non differenciee  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BB::Tenseur1BB ( const TenseurBB & B):  
 ipointe()
  { dimension = 1;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::Tenseur1BB ( etc..");
     #endif
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *(this->t) = *(B.t);
  };     
// constructeur de copie  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BB::Tenseur1BB ( const Tenseur1BB & B):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *(this->t) = *(B.t);
  };     
// initialise toutes les composantes à val
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1BB::Inita(double val)
  {*(this->t) =val;};   
// operations 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator + ( const TenseurBB & B) const 
  {  TenseurBB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator + ( etc..");
     #endif
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) + *(B.t); //somme des données
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BB::operator += ( const TenseurBB & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator += ( etc..");
     #endif
     *(this->t) += *(B.t);}; //somme des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator - () const 
  {  TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = - *(this->t); //oppose
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator - ( const TenseurBB & B) const 
  {  TenseurBB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator - ( etc..");
     #endif
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) - *(B.t); //soustraction des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BB::operator -= ( const TenseurBB & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator -= ( etc..");
     #endif
    *(this->t) -= *(B.t);}; //soustraction des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator = ( const TenseurBB & B)
  { *(this->t) = *(B.t); //affectation des données
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator = ( etc..");
     #endif
    LesMaillonsBB::Libere(); // destruction des tenseurs intermediaires
    return *this; };
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator * ( const double & b) const 
  {  TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) * b; //multiplication des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BB::operator *= ( const double & b)
  { *(this->t) *= b;}; //multiplication des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator / (const double & b) const
  {  TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) / b; //division des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BB::operator /= ( const double & b)
  { *(this->t) /= b;}; //division des données
  // produit contracte avec un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
CoordonneeB Tenseur1BB::operator * ( const CoordonneeH & B) const 
  { 
    #ifdef MISE_AU_POINT	 	 
	 if (B.Dimension() != dimension)
	    { cout << "\nErreur : dimensions vecteur tenseur non egales !\n";
		  cout << " Tenseur1BH::operator *\n";
		  Sortie(1);
		};
    #endif
    CoordonneeB v(dimension);
    v(1) = *(this->t) * B(1);
    return v;
  }; 
 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::operator * ( const TenseurHB & B) const 
  {  TenseurBB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator * ( etc..");
     #endif
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BB::operator * ( const TenseurHH & B) const 
  {  TenseurBH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator * ( etc..");
     #endif
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  };  
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BB::operator && ( const TenseurHH & B) const 
  { double result;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator && ( etc..");
     #endif
    result =  (*(this->t)) * (*(B.t)); // contraction
    return result;};
// test
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1BB::operator == ( const TenseurBB & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator == ( etc..");
     #endif
     if (*(this->t) != *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1BB::operator != ( const TenseurBB & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BB::operator != ( etc..");
     #endif
      if (*(this->t) == *(B.t))
         return 0 ;
      else
         return 1;};
// calcul du determinant des coordonnees du tenseur
#ifndef MISE_AU_POINT
  inline 
#endif
double Tenseur1BB::Det() const 
  { return *(this->t) ;};             
 #ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1BB::Inverse() const 
  { TenseurHH * res;
    res =  new Tenseur1HH;
    LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
    #ifdef MISE_AU_POINT	 	 
	 if  (Dabs(*(this->t)) <= ConstMath::trespetit)
			{ cout << "\nErreur : la coordonnee du tenseur est nulle !\n";
			  cout << "Tenseur1BB::Inverse() \n";
			  Sortie(1);
			};
    #endif    
    *(res->t) = 1./ (*(this->t));
    return *res;
  };             
             
#ifndef MISE_AU_POINT
  inline 
#endif
// affectation de B dans this,  plusZero = false: les données manquantes sont inchangées,
// plusZero = true: les données manquantes sont mises à 0
// si au contraire la dimension de B est plus grande que *this, il y a uniquement affectation
// des données possibles
void Tenseur1BB::Affectation_trans_dimension(const TenseurBB & B,bool plusZero)
{ // dans tous les cas il suffit de récupérer le premier élément et de l'affecter
  this->t[0] = B.t[0]; //on affecte le seul terme disponible
};

#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::Transpose() const 
   { TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           

    
    // ---- manipulation d'indice ---- -> création de nouveaux tenseurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH& Tenseur1BB::Monte2Indices() const
   { TenseurHH * res;
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB& Tenseur1BB::MontePremierIndice() const
   { TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           

#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH& Tenseur1BB::MonteDernierIndice() const
   { TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           

//fonctions static définissant le produit tensoriel de deux vecteurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BB::Prod_tensoriel(const CoordonneeB & aB, const CoordonneeB & bB)
  {  TenseurBB * res;
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = aB(1)*bB(1); 
     return *res;}; 
	 
	 // lecture et écriture de données
#ifndef MISE_AU_POINT
  inline 
#endif
istream & Tenseur1BB::Lecture(istream & entree)
  { // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1BB")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*(this->t));
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
ostream & Tenseur1BB::Ecriture(ostream & sort) const 
  { // écriture du type
    sort << "Tenseur1BB ";
    // puis les datas
    sort  << setprecision (ParaGlob::NbdigdoCA()) <<   (*(this->t)) << " ";
     return sort;      
  };

#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator de lecture
istream & operator >> (istream & entree, Tenseur1BB & A)
  { int dim = A.Dimension();
     #ifdef MISE_AU_POINT
       if (dim != 1) A.Message(1,"operator >> (istream & entree, Tenseur1BB & A)");
    #endif
    // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1BB")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*A.t);
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort , const Tenseur1BB & A)
  { // écriture du type
    sort << "Tenseur1BB ";
    // puis les datas
    sort  << setprecision(ParaGlob::NbdigdoCA()) <<   (*A.t) << " ";
     return sort;      
  };


    
#endif    
