// FICHIER : Vecteur.cc
// CLASSE : Vecteur


// 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 "Debug.h"

# include <iostream>
using namespace std;  //introduces namespace std
#include <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include <iomanip>
#include "ParaGlob.h"
#include "CharUtil.h"

#include "Vecteur.h"

#ifndef  VECTEUR_H_deja_inclus
 

#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur permettant de definir un vecteur de taille n initialise a 0
Vecteur::Vecteur (int n)
{  
 #ifdef MISE_AU_POINT
 if ( n<0 )
   {	cout << "\nErreur : taille invalide !\n";
    cout << "VECTEUR::VECTEUR (int ) \n";
    Sortie(1);
   };
 #endif
	if ( n==0 )
   // cas ou la taille selectionnee est nulle : initialisation identique a l'appel
   // du constructeur par defaut
   {	taille=0;
    v=NULL;
   }
	else
   {v=new double [n]; // allocation de la place memoire
    taille=n;
    for (int i=0;i<n;i++)
     // affectation des composantes du vecteur a 0
     v[i]=0.0; 				    		
   };
};
 
#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur permettant de definir un vecteur de taille n initialise a val
Vecteur::Vecteur (int n,double val)
{
 #ifdef MISE_AU_POINT
	if ( n<0 )
   {	cout << "\nErreur : taille invalide !\n";
    cout << "VECTEUR::VECTEUR (int ,double ) \n";
    Sortie(1);
   };
 #endif
	if ( n==0 )
   // cas ou la taille selectionnee est nulle : initialisation identique a l'appel
   // du constructeur par defaut
   {	taille=0;
    v=NULL;
   }
	else
   {v=new double [n]; // allocation de la place memoire
    taille=n;
    for (int i=0;i<n;i++)
    // affectation des composantes du vecteur a val
     v[i]=val; 			
   };	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur permettant de definir un vecteur de taille n dont les premieres valeurs
// sont celles de vec
// aucun test n'est fait concernant la taille disponible de vec
Vecteur::Vecteur (int n,double* vec)  // routine dangereuse !!!!!
{	
 #ifdef MISE_AU_POINT
  if ( n < 0)
    {
     cout << "\nErreur : taille invalide ! n= " << n << '\n';
     cout << "VECTEUR::VECTEUR (int ,double* ) \n";
     Sortie(1);
    };
 #endif
	if ( n==0 )
   // cas ou la taille selectionnee est nulle : initialisation identique a l'appel
   // du constructeur par defaut
   {	taille=0;
    v=NULL;
   }
	else
   {v = new double [n]; // allocation de la place memoire
    taille=n;
    for (int i=0;i<n;i++)
    // affectation des composantes du vecteur au tableau vec
     v[i]=vec[i]; 			
   };	
};
		
		
#ifndef MISE_AU_POINT
  inline 
#endif
// Destructeur
Vecteur::~Vecteur ()
{	Libere(); };

// Retourne la taille du vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
int Vecteur::Taille () const 
		{ return taille; };

#ifndef MISE_AU_POINT
  inline 
#endif
// Affiche les donnees concernant le vecteur
void Vecteur::Affiche ()  const 
{double* ptr=v;
	cout << "\nTaille du vecteur : " << taille << " .\n";
	cout << "Composante(s) :\n\t{  ";
	for (int i=0;i<taille;i++)
		cout << (*ptr++) << "  ";
	cout << "}\n" << endl;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Affichage des composantes du vecteur avec paramètres de contrôle
void Vecteur::Affiche (int min_i,int max_i,int pas_i, int nbd)  const 
{cout << "\nTaille du vecteur : " << taille << " .\n";
	cout << "Composante(s) :\n\t{  ";
    for (int i=min_i;i<=max_i;i+=pas_i)
       cout << setw(nbd) << setprecision(nbd) << (*this)(i) << " ";
	cout << "}\n" << endl;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Affiche les donnees concernant le vecteur
void Vecteur::Affichage_ecran(string entete)  const 
 {// affichage éventuelle du vecteur       
  cout << "\n --- " << entete << " -----";
  string rep;
  cout << "\n voulez-vous afficher le vecteur ? (o ou n(defaut)) ";
  rep = lect_return_defaut(false,"n");
  if (rep == "o") 
    {cout << "\n parametre d'affichage par defaut (tout le vecteur) ? (o ou n(defaut))  " ;
     rep = lect_return_defaut(false,"n");
     int min_i,max_i,pas_i,nd;
     if (rep =="o")
         { min_i=1; max_i=taille; pas_i=1; nd=14;}
     else
        {try 
           { cout << "\n a partir de quel numero de composante ? (1) "; min_i=(int)lect_double();
             cout << " jusqu'a quel numero de composante ? ("<<taille<<")  "; max_i=(int)lect_double();
             cout << " par pas de ? (1) "; pas_i=(int)lect_double();
             cout << "\n nombre de diggit ? (14) "; nd=(int)lect_double();
            }   
         catch (ErrSortieFinale)
              // cas d'une direction voulue vers la sortie
              // on relance l'interuption pour le niveau supérieur
            { ErrSortieFinale toto;
              throw (toto);
            }
         catch (...)
           { cout << "\n Erreur sur l'entree des donnee !!, on prend les valeurs par defaut ";
             min_i=1; max_i=taille; pas_i=1; nd=14;
            }
         }
     this->Affiche(min_i,max_i,pas_i,nd);
     cout << "\n entrez une lettre pour continuer ? "; 
     rep = lect_chaine();
  }   
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Permet de modifier la taille du vecteur 
// N.B. : Si la nouvelle taille est superieure a l'ancienne alors le vecteur
// est complete par des 0
void Vecteur::Change_taille (int n)
{ // si la taille est identique, on ne fait rien
  if (n == taille)
    return;
  // la suite concerne le cas où il faut vraiment faire quelque chose
  if ( n<0 )
   	// cas ou la taille selectionnee est negative
   	{	cout << "\nErreur : taille invalide !\n";
   	 	cout << "VECTEUR::CHANGE_TAILLE (int ) \n";
   			Sortie(1);
    };
	 if ( n==0 )
   	// cas ou la taille selectionnee est nulle : initialisation identique a
   	// l'appel du constructeur par defaut
   	{	taille=0;
   		 v=NULL;
   		 return ;
   	};
	 double* tempo;
	 tempo=new double [n];
	 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 vecteur d'origine dans le vecteur pointe par tempo
		      tempo[i] = v[i];
	   }
	 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 vecteur d'origine dans le vecteur pointe par tempo
   		   tempo[i] = v[i];
   		 for (int i=taille;i<n;i++)
   		   // initialisation des composantes supplementaires a 0
   		   tempo[i] = 0.0;
   	};
	 delete [] v; // desallocation du vecteur pointe par v
	 v=tempo; // affectation du pointeur v au pointeur tempo
	 taille=n;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Change la taille du vecteur avec initialisation de tous le nouveau vecteur
void Vecteur::Change_taille (int n,const double& val_init)		
{ // si la taille est identique, on ne fait que l'initialisation
  if (n == taille)
    {	for (int i=0;i<taille;i++)
			       v[i] = val_init; // affectation des composantes du vecteur
      return;
    };
  // la suite concerne le cas où il faut vraiment faire quelque chose
 	if ( n<0 )
    // cas ou la taille selectionnee est negative
    {	cout << "\nErreur : taille demandee="<<n<<" invalide !\n";
    	 cout << "VECTEUR::CHANGE_TAILLE (int,const double& val_init ) \n";
    	 Sortie(1);
    };
	 if ( n==0 )
    // cas ou la taille selectionnee est nulle : initialisation identique a
    // l'appel du constructeur par defaut
    {	taille=0;
    	 v=NULL;
    	 return ;
    };
  double* tempo;
	 tempo=new double [n];
	 double * pt=tempo;
	 for (int i=0; i< n; i++)
	   (*pt++) = val_init;
	 delete [] v; // desallocation du vecteur pointe par v
	 v=tempo; // affectation du pointeur v au pointeur tempo pointant au début !!
	 taille=n;
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Apres l'appel de cette methode, le vecteur est identique a ce qu'il aurait
// ete a la suite de l'appel du contructeur par defaut
void Vecteur::Libere ()
{if ( taille>0 )
		{delete [] v;} // desallocation du vecteur pointe par v
	else
  {	if ( v!=NULL )
     {	cout << "\nErreur de liberation de la place memoire\n";
       cout << "VECTEUR::LIBERE () \n";
       Sortie(1);
     };
  };
	v=NULL;
	taille=0; 	
};

#ifndef MISE_AU_POINT 
  inline 
#endif
// Retourne le maximum en valeur absolue des composantes du vecteur
double Vecteur::Max_val_abs () const 
{	double max;
	 max=fabs(v[0]); // affectation de max a la premiere composante du vecteur
	 for (int i=1;i<taille;i++)
	  {	if ( max<fabs(v[i]) ) 
		    // cas ou la composante pointee excede max
			   max=fabs(v[i]);
   };
	 return max;
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne le maximum en valeur absolue des composantes du vecteur
double Vecteur::Max_val_abs (int& in) const 
{double max;
	in = 1;
	max=fabs(v[0]); // affectation de max a la premiere composante du vecteur
	for (int i=1;i<taille;i++)
	 {	if ( max<fabs(v[i]) ) 
		   // cas ou la composante pointee excede max
      { max=fabs(v[i]);
        in = i+1;
      };
	  };
	return max;	
};
#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne le maximum en valeur absolue des composantes du vecteur
// mais ramène la grandeur signée (avec son signe)
double Vecteur::Max_val_abs_signe () const 
{double max;
	int in = 1;
	max=fabs(v[0]); // affectation de max a la premiere composante du vecteur
	for (int i=1;i<taille;i++)
	 {	if ( max<fabs(v[i]) ) 
		   // cas ou la composante pointee excede max
     { max=fabs(v[i]);
       in = i+1;
     };
	  };
	// affectation à la grandeur signée
	max = v[in-1];  
	return max;	
};


#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne le maximum en valeur absolue des composantes du vecteur
// mais ramène la grandeur signée (avec son signe)
double Vecteur::Max_val_abs_signe (int& in) const 
{double max;
	in = 1;
	max=fabs(v[0]); // affectation de max a la premiere composante du vecteur
	for (int i=1;i<taille;i++)
	 {	if ( max<fabs(v[i]) ) 
		   // cas ou la composante pointee excede max
		   { max=fabs(v[i]);
		     in = i+1;
		   };
  };
	// affectation à la grandeur signée
	max = v[in-1];  
	return max;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne la norme euclidienne du vecteur
double Vecteur::Norme ()  const 
{double norme=0.0;
	for (int i=0;i<taille;i++)
	// somme du carre des composantes du vecteur
		norme += v[i] * v[i];
	// calcul de la norme et retour
	return sqrt(norme);	
};

// norme le vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur& Vecteur::Normer () 
  { *this /=  this->Norme();
    return *this;};

#ifndef MISE_AU_POINT
  inline 
#endif
// Realise le produit scalaire entre le vecteur courant et le vecteur
// vec et retourne le resultat obtenu
// N.B.: Les vecteurs doivent etre de meme taille
double Vecteur::Prod_scal (const Vecteur& vec) const 
{
 #ifdef MISE_AU_POINT
  if ( taille!=vec.taille )
   {	cout << "\nErreur : tailles non egales !\n";
    cout << "VECTEUR::PROD_SCAL (Vecteur ) \n";
    Sortie(1);
   };
 #endif
	double prod_scal=0.0;
	for (int i=0;i<taille;i++)
	  // somme du produit des composantes des deux vecteurs
		 prod_scal+=(v[i] * vec.v[i]);
	return prod_scal;	
};

// somme de tous les composantes du vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
double Vecteur::Somme() const 
  { double somme=0;
	   for (int i=0;i<taille;i++)
      somme += v[i];	 
    return somme;
  };          

// somme de tous les valeurs absolues des composantes du vecteur
#ifndef MISE_AU_POINT
  inline
#endif
double Vecteur::SommeAbs() const
  { double somme=0;
    for (int i=0;i<taille;i++)
      somme += fabs(v[i]);
    return somme;
  };


// Moyenne de tous les composantes du vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
double Vecteur::Moyenne() const 
  { double moyenne=0;
    if (taille != 0)
	    { for (int i=0;i<taille;i++)
         moyenne += v[i];
		     moyenne /= taille;
		   };
    return moyenne;
  };          

#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur Vecteur::operator+ (const Vecteur& vec) const 
// Surcharge de l'operateur + : addition entre deux vecteurs
// N.B.: Les vecteurs doivent etre de meme taille
{	
 #ifdef MISE_AU_POINT
  if ( taille!=vec.taille )
   {	cout << "\nErreur : tailles non egales !\n";
    cout << "VECTEUR::OPERATOR+ (Vecteur ) \n";
    Sortie(1);
   };
 #endif
	Vecteur result(taille);
	for (int i=0;i<taille;i++)
  // somme des composantes des deux vecteurs vec et v, puis stockage
  // dans le vecteur result
		result.v[i]=v[i]+vec.v[i];		
	return result;	
};

// Surcharge de l'operateur - : oppose d'un vecteur 
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur Vecteur::operator- () const 
{Vecteur result(taille);
	for (int i=0;i<taille;i++)
	    result.v[i]=-v[i];
	return result;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur - : soustraction entre deux vecteurs
// N.B.: Les vecteurs doivent etre de meme taille
Vecteur Vecteur::operator- (const Vecteur& vec) const 
{	
 #ifdef MISE_AU_POINT
  if ( taille!=vec.taille )
   {	cout << "\nErreur : tailles non egales !\n";
    cout << "VECTEUR::OPERATOR- (Vecteur ) \n";
    Sortie(1);
   };
 #endif
	Vecteur result(taille);
	for (int i=0;i<taille;i++)
   // soustraction des composantes des vecteurs vec et v, puis stockage
   // dans le vecteur result
		 result.v[i]=v[i]-vec.v[i];
	return result;
};


#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur += : additionne au vecteur courant le vecteur vec
// N.B.: Les vecteurs doivent etre de meme taille
void Vecteur::operator+= (const Vecteur& vec)
{
 #ifdef MISE_AU_POINT
  if ( taille!=vec.taille )
   {	cout << "\nErreur : tailles non egales !\n";
    cout << "VECTEUR::OPERATOR+= (Vecteur ) \n";
    Sortie(1);
   };
 #endif
	for (int i=0;i<taille;i++)
		 v[i]+=vec.v[i];
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur -= : soustrait au vecteur courant le vecteur vec
// N.B.: Les vecteurs doivent etre de meme taille
void Vecteur::operator-= (const Vecteur& vec)
{
 #ifdef MISE_AU_POINT
  if ( taille!=vec.taille )
  {	cout << "\nErreur : tailles non egales !\n";
   cout << "VECTEUR::OPERATOR-= (Vecteur ) \n";
   Sortie(1);
  };
 #endif
	for (int i=0;i<taille;i++)
		 v[i]-=vec.v[i];
};		

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur *= : multiplie les composantes du vecteur courant par
// le scalaire val
// N.B.: Les vecteurs doivent etre de meme taille
void Vecteur::operator*= (double val)
{	for (int i=0;i<taille;i++)
		  v[i]*=val;
};	

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur == : test d'egalite entre deux vecteurs
// Renvoie 1 si les deux vecteurs sont egaux
// Renvoie 0 sinon
int Vecteur::operator== (const Vecteur& vec) const 
{if ( vec.taille!=taille )
		{return 0;}
	else
	 {for (int i=0;i<taille;i++)
		  {	if ( v[i] !=vec.v[i] )
				   return 0;
    };
		 return 1;
	 };
};	

// Surcharge de l'operateur !=
// Renvoie 1 si les deux vecteurs ne sont pas egaux
// Renvoie 0 sinon
#ifndef MISE_AU_POINT
  inline 
#endif
int Vecteur::operator!= (const Vecteur& vec) const 
		{	if ( (*this)==vec )
				  return 0;
			  else
				  return 1;
		};
	
#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur = : realise l'egalite de deux vecteurs
// (Affecte le vecteur courant au vecteur vec)
Vecteur& Vecteur::operator= (const Vecteur& vec)
{	// cas ou l'adresse des vecteurs a gauche et a droite sont identiques
  if (&vec == this) return (*this);
  // cas où les deux tailles sont égales 
  if ( vec.taille==taille )
     {  for (int i=0;i<taille;i++)
         // copie des elements du vecteur se trouvant a droite dans le vecteur se trouvant
         // a gauche du signe d'affectation
         v[i] = vec.v[i];
      }
  else
     { if (v!=NULL)
		       Libere();	// cas ou le vecteur se trouvant a gauche du signe =
       // n'est pas vide mais est different en taille
       // de celui de droite : desallocation de ce vecteur
	      if ( vec.taille==0 )
        // cas ou le vecteur se trouvant a droite du signe = est vide : initialisation
        // identique a l'appel du constructeur par defaut
        {	taille=0;
          v=NULL;
        }
       else
         // autres cas
        {	taille=vec.taille;
          v=new double [taille];
          for (int i=0;i<taille;i++)
          // copie des elements du vecteur se trouvant a droite dans le vecteur se trouvant
          // a gauche du signe d'affectation
          v[i] = vec.v[i];
        };
     };
	 return (*this);
};
		

// définition d'une surcharge basique d'affectation avec un MV_Vector
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur& Vecteur::operator= (const MV_Vector<double> & A)
{	// cas où les deux tailles sont égales
  if ( taille==A.size() )
     {  for (int i=0;i<taille;i++)
          // copie des elements du vecteur se trouvant a droite dans le vecteur se trouvant
          // a gauche du signe d'affectation
		        v[i] = A[i];
     }
  else
     { if (v!=NULL)
		       Libere();	// cas ou le vecteur se trouvant a gauche du signe =
       // n'est pas vide mais est different en taille
       // de celui de droite : desallocation de ce vecteur
	      if ( A.size()==0 )
        // cas ou le vecteur se trouvant a droite du signe = est vide : initialisation
        // identique a l'appel du constructeur par defaut
        {	taille=0;
          v=NULL;
         }
       else
         // autres cas
        {	taille=A.size();
          v=new double [taille];
          for (int i=0;i<taille;i++)
            // copie des elements du vecteur se trouvant a droite dans le vecteur se trouvant
            // a gauche du signe d'affectation
            v[i] = A[i];
        };
	    };
	 return (*this);
};

// Surcharge de l'operateur * : multiplication d'un vecteur par un scalaire
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur Vecteur::operator* (double val)  const 
{	
 #ifdef MISE_AU_POINT
 if ( taille==0 )
    {	cout << "\nErreur : taille nulle !\n";
     cout << "VECTEUR::OPERATOR* (double ) \n";
     Sortie(1);
    };
 #endif
	Vecteur result(taille);
	for (int i=0;i<taille;i++)
  // stockage dans le vecteur result du produit des composantes du vecteur courant
  // avec val
		result.v[i]=val*v[i];
	return result;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur / : division des composantes d'un vecteur par un scalaire
Vecteur  Vecteur::operator/ (double val) const 
{
 #ifdef MISE_AU_POINT
	if ( (taille==0) || (val==0) )
   {	cout << "\nErreur : taille nulle ou division par zero !\n";
    cout << "VECTEUR::OPERATOR/ (double ) \n";
    Sortie(1);
   };
 #endif
	Vecteur result(taille);
	for (int i=0;i<taille;i++)
  // stockage dans le vecteur result de la division des composantes du vecteur courant
  // avec val
		result.v[i] = v[i]/val;
	return result;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur / : division des composantes d'un vecteur par un scalaire
void Vecteur::operator/= (double val)
{
 #ifdef MISE_AU_POINT
	if ( (taille==0) || (val==0) )
   {	cout << "\nErreur : taille nulle ou division par zero !\n";
    cout << "VECTEUR::OPERATOR/ (double ) \n";
    Sortie(1);
   };
 #endif
 //	double* ptr=v;
	for (int i=0;i<taille;i++)
		 v[i] /= val;
};	

// Surcharge de l'operateur * : multiplication entre deux vecteurs
// Permet de realiser le produit scalaire entre deux vecteurs
#ifndef MISE_AU_POINT
  inline 
#endif
double Vecteur::operator* (const Vecteur& vec) const 
		{	return Prod_scal(vec);	};
		
#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne la ieme composante du vecteur : acces en lecture uniquement
double Vecteur::operator() (int i) const 
		{
   #ifdef MISE_AU_POINT
    if ( (i<1) || (i>taille) )
      {	cout << "\nErreur : composante inexistante !\n";
       cout << "VECTEUR::OPERATOR() (int ) \n";
       Sortie(1);
      };
   #endif
			return v[i-1];	
		};

#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne la ieme composante du vecteur : acces en lecture et en ecriture
double& Vecteur::operator() (int i)
		{
   #ifdef MISE_AU_POINT
    if ( (i<1) || (i>taille) )
      {	cout << "\nErreur : composante inexistante !\n";
       cout << "VECTEUR::OPERATOR() (int ) \n";
       Sortie(1);
      };
   #endif
			return v[i-1];	
		};

#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur ! : renvoie la norme d'un vecteur
double Vecteur::operator! () const 
		{	return Norme();	};

// mise a zero d'un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
void Vecteur::Zero()
 {for (int i=0;i<taille;i++)
		 // affectation des composantes du vecteur a 0
			v[i] = 0.0;
 };  

#ifndef MISE_AU_POINT
  inline 
#endif
// calcul le produit P(i) = (*this)(i) * A(i); ramène P qui est passé en paramètre
Vecteur& Vecteur::Prod_ii(const Vecteur& A, Vecteur& P) const
 {	
  #ifdef MISE_AU_POINT
   if ( taille != A.Taille() )
     {cout << "\nErreur : la taille de this ("<<taille<<") est differente"
           << " de celle de A ("<<A.Taille()<<" la methode Prod_ii ne peut s'effectuer !\n";
      cout << "Vecteur::Prod_ii(const Vecteur& A, Vecteur& P) \n";
      Sortie(1);
     };
  #endif
	 if (P.Taille() != taille )
	  P.Change_taille(taille); 
  for (int i=0;i<taille;i++)
    // affectation des composantes du vecteur de retour
    P.v[i] = v[i] * A.v[i];
	 return P;
 };  

#ifndef MISE_AU_POINT
  inline 
#endif
// initialise toutes les composantes à val
void Vecteur::Inita(double val)   
 {	for (int i=0;i<taille;i++)
		   // affectation des composantes du vecteur a 0
     v[i] = val;
 };  

// affectation à une partie d'un vecteur qui doit avoir une taille donc plus grande
// (*this)(i) = vec(i+indice-1); i= 1 à la taille de (*this)
// ramène *this
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur& Vecteur::Egale_une_partie_de(const Vecteur& vec,int indice) 
 { 
   #ifdef MISE_AU_POINT
    if ( (indice<1) || (indice-1+taille > vec.taille) )
      {	cout << "\nErreur, affectation impossible: indice= " << indice << " vec.Taille()= " << vec.taille
               << " (*this).Taille()= " << taille << " !\n";
       cout << "Vecteur::Egale_une_partie_de(const Vecteur& vec,int indice)\n";
       Sortie(1);
      };
   #endif
   int j=indice-1;
   for (int i=0;i<taille;i++,j++)
		    v[i] = vec.v[j];
	  return *this;
 }; 
  
// affectation d'une partie de (*this) au vecteur passé en paramètre
// (*this)(i+indice-1) = vec(i); i= 1 à la taille de vec
// ramène *this
#ifndef MISE_AU_POINT
  inline 
#endif
Vecteur& Vecteur::Une_partie_egale(int indice, const Vecteur& vec) 
 { 
   #ifdef MISE_AU_POINT
    if ( (indice<1) || (indice-1+vec.taille > taille) )
      {cout << "\nErreur, affectation impossible: indice= " << indice << " vec.Taille()= " << vec.taille
               << " (*this).Taille()= " << taille << " !\n";
       cout << "Vecteur::Une_partie_egale(int indice, const Vecteur& vec)\n";
       Sortie(1);
      };
   #endif
   int j=indice-1;
   for (int i=0;i<vec.taille;i++,j++)
		    v[j] = vec.v[i];
	  return *this;
 }; 

#ifndef MISE_AU_POINT
  inline 
#endif
// methode pour la compatibilite avec des classes derivees
Vecteur & Vecteur::Vect() 
  { return *this;};
  
#ifndef MISE_AU_POINT
  inline 
#endif
// Surcharge de l'operateur * : multiplication entre un scalaire et un vecteur
Vecteur operator* (double val,const Vecteur& vec)
{	return (vec*val);   };

// surcharge de l'operateur de lecture
// les informations sont le type puis la taille puis les datas 
#ifndef MISE_AU_POINT
  inline 
#endif
istream & operator >> (istream & entree, Vecteur & vec)
  { // vérification du type
    string type;
    entree >> type;
    if (type != "Vecteur")
      {Sortie (1);
       return entree;
      };
    // passage de la chaine donnant la taille puis lecture de la taille
    int taille;
    entree >> type >> taille; 
    // vérification de la taille sinon changement
    if (vec.Taille() != taille) vec.Change_taille(taille);  
    // lecture des données
    for (int i = 0; i< vec.taille; i++)
        entree >> vec.v[i];
    return entree;      
  };
  
// surcharge de l'operateur d'ecriture non formatée
// les informations sont le type puis la taille puis les datas séparées par
// un espace
#ifndef MISE_AU_POINT
  inline 
#endif
ostream & operator << ( ostream & sort,const  Vecteur & vec)
  { // tout d'abord un indicateur donnant le type
    sort << "Vecteur  taille= "  << vec.taille << " "; 
    for (int i = 0; i< vec.taille; i++)
        sort  << setprecision(ParaGlob::NbdigdoCA()) <<  vec.v[i] << " ";
//    sort << "\n";
    return sort;      
  };

       // spécifiquement à la classe MV_Vector<double>
#ifndef MISE_AU_POINT
  inline 
#endif
MV_Vector<double> * Vecteur::Nouveau_MV_Vector_double()
 { MV_Vector <double>* pt = 
            new MV_Vector <double> (v,taille,MV_Vector_::ref_type(1));
   return pt;
  };
#ifndef MISE_AU_POINT
  inline 
#endif
const MV_Vector<double> * Vecteur::Nouveau_MV_Vector_double_const() const 
 { const MV_Vector <double>* pt = 
            new const MV_Vector <double> (v,taille,MV_Vector_::ref_type(1));
   return pt;
  };



// ramène un vecteur MV_Vector <double> qui utilise la même place
// mémoire que this ce qui pemet d'utiliser le type MV_Vector
#ifndef MISE_AU_POINT
  inline 
#endif
MV_Vector <double> Vecteur::MV_vecteur_double()
 { return (MV_Vector <double> (v,taille,MV_Vector_::ref_type(1)));
  };
// ramène un vecteur constant MV_Vector <double> qui utilise la même place
// mémoire que this ce qui pemet d'utiliser le type MV_Vector
#ifndef MISE_AU_POINT
  inline 
#endif
const MV_Vector <double> Vecteur::MV_vecteur_double() const 
 { return (MV_Vector <double> (v,taille,MV_Vector_::ref_type(1)));
  };

#endif


