// FICHIER : Vecteur.h
// 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/>.


/************************************************************************
*     DATE:        23/01/97                                            *
*                                                                $     *
*     AUTEUR:      G RIO                                               *
*                                                                $     *
*     PROJET:      Herezh++                                            *
*                                                                $     *
************************************************************************
*
// La classe Vecteur permet de declarer des vecteurs d'une longueur predefinie par
// une allocation dynamique de memoire. Les composantes d'un vecteur de cette classe
// sont de type double.
// correspond au vecteur absolu ( par opposition avec des vecteurs avec des coordonnees
// covariantes ou contravariantes
*
*                                                                $     *
*     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
*     MODIFICATIONS:                                                   *
*     !  date  !   auteur   !       but                          !     *
*     ------------------------------------------------------------     *
*                                                                $     *
************************************************************************/



#ifndef VECTEURS__H
#define VECTEURS__H

//#include "Debug.h"

#include <iostream>
#include <stdlib.h>
#include "Sortie.h"

#include "mvvtp_GR.h" // classe template MV++



/** @defgroup Les_classes_Vecteur
*
// Les classes de type "vecteur" permettent de declarer des vecteurs d'une longueur predefinie par
// une allocation dynamique de memoire. Les composantes d'un vecteur
// sont de type double.
// correspond au vecteur absolu ( par opposition avec des vecteurs avec des coordonnees
// covariantes ou contravariantes
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       Définition des classes de type "vecteur"
*
*/



/// @addtogroup Les_classes_Vecteur
///  @{
///

class Coordonnee;  // declare a la fin du fichier, car coordonnees utilise aussi vecteur
class CoordonneeH;  // declare a la fin du fichier, car coordonnees utilise aussi vecteur
class CoordonneeB;  // declare a la fin du fichier, car coordonnees utilise aussi vecteur

/// La classe Vecteur permet de declarer des vecteurs d'une longueur predefinie par
/// une allocation dynamique de memoire. Les composantes d'un vecteur de cette classe
/// sont de type double.
/// Correspond à un vecteur absolu ( par opposition avec des vecteurs avec des coordonnees
/// covariantes ou contravariantes

class Vecteur
{
	
  /// utilisation directe du pointeur de double par la classe MatLapack
  friend class MatLapack;
  
	public :
	
  /// Surcharge de l'operateur * : multiplication entre un scalaire et un vecteur
  friend Vecteur operator* (double val,const Vecteur& vec);
  /// surcharge de l'operator de lecture
  /// les informations sont le type puis la taille puis les datas
  friend istream & operator >> (istream &, Vecteur &);
  /// surcharge de l'operator d'ecriture non formatée
  /// les informations sont le type puis la taille puis les datas séparées par
  /// un espace
  friend ostream & operator << (ostream &, const Vecteur &);
  
       // spécifiquement à la classe MV_Vector<double>
 //      friend MV_Vector<double> * Nouveau_MV_Vector_double(Vecteur & b);
  //     friend const MV_Vector<double> * Nouveau_MV_Vector_double_const(const Vecteur & b);
	
		// CONSTRUCTEURS :
		
		/// Constructeur par defaut
		Vecteur ();
		/// Constructeur fonction de la taille du vecteur
		/// initialisation à zéro par défaut
		Vecteur (int n);		
		/// Constructeur fonction de la taille du vecteur et d'une
		/// valeur d'initialisation pour les composantes
		Vecteur (int n,double val);		
		/// Constructeur fonction d'un tableau de composantes de type T
  /// aucun test n'est fait concernant la taille disponible de vec
  /// routine dangereuse !!!!!
		Vecteur (int n,double* vec);		
		// Constructeur fonction d'un Point
// trop dangereux, car en fait il y a des conversions implicites dans des calculs par exemple, qui se passent
//  sans qu'on le voit explicitement
//il vaut mieux utiliser la conversion explicite (même si ça parait un peu plus long, mais je crois que l'on gagne au final
//		Vecteur (const Coordonnee& a);	
//		Vecteur (const CoordonneeH& a);	
//		Vecteur (const CoordonneeB& a);

		/// constructeur fonction d'un MV_Vector : oui car c'est un cas particulier (différent des coordonnées)
		Vecteur (const MV_Vector <double>& a);
		/// Constructeur de copie
		Vecteur (const Vecteur& vec);
		
		
		/// DESTRUCTEUR :
		~Vecteur ();
		
		
		// METHODES :
		
		/// Retourne la taille du vecteur
		int Taille () const; 
		/// Affichage des composantes du vecteur
		void Affiche ()  const ;		
		/// Affichage des composantes du vecteur avec paramètres de contrôle
		void Affiche (int min_i,int max_i,int pas_i, int nbdiggit)  const ;		
  /// affichage à l'écran après une demande interactive du vecteur
  /// entete: une chaine explicative, a afficher en entête
  void Affichage_ecran(string entete) const;
                
		/// Change la taille du vecteur (la nouvelle taille est n)
		/// si la nouvelle taille est inférieur, on garde les valeurs existantes du vecteur
		/// si la nouvelle taille est supérieur, on garde les valeurs existantes et les
		/// nouvelles valeurs sont mises à 0
		void Change_taille (int n);		
		/// Change la taille du vecteur avec initialisation de tous le nouveau vecteur
		void Change_taille (int n,const double& val_init);		
		/// Permet de desallouer l'ensemble des elements du vecteur
		void Libere();		
		/// Calcul du maximum en valeur absolu des composantes du vecteur
		double Max_val_abs ()  const ;		
		/// Calcul du maximum en valeur absolu des composantes du vecteur
		/// ramene egalement l'indice de tableau du maximum
		double Max_val_abs (int& i)  const ;
		/// Calcul du maximum en valeur absolu des composantes du vecteur
		/// mais ramène la grandeur signée (avec son signe)
		double Max_val_abs_signe()  const ;		
		/// Calcul du maximum en valeur absolu des composantes du vecteur
		/// mais ramène la grandeur signée (avec son signe)
		/// ramene egalement l'indice de tableau du maximum
		double Max_val_abs_signe(int& i)  const ;
  /// calcul, récupération et affichage éventuelle
  /// des mini, maxi, et en valeur absolue la moyenne des composantes du vecteur
  /// en retour: le min, le max et la moyenne en valeur absolue
  Coordonnee MinMaxMoy(bool affiche) const;

		/// Calcul de la norme euclidienne des composantes du vecteur
		double Norme ()  const ;
		/// norme le vecteur
		Vecteur& Normer () ;
		/// Calcul du produit scalaire entre deux vecteurs
		double Prod_scal (const Vecteur& vec) const ;	
		/// somme de tous les composantes du vecteur
		double Somme() const ;
  /// somme de tous les valeurs absolues des composantes du vecteur
  double SommeAbs() const ;
		/// moyenne de tous les composantes du vecteur
		double Moyenne() const ;
		/// Surcharge de l'operateur + : addition entre deux vecteurs
		Vecteur operator+ (const Vecteur& vec) const ;
		/// Surcharge de l'operateur - : soustraction entre deux vecteurs
		Vecteur operator- (const Vecteur& vec) const ;
		/// Surcharge de l'operateur - : oppose d'un vecteur
  Vecteur operator- () const; 
		/// Surcharge de l'operateur +=
		void operator+= (const Vecteur& vec);		
		/// Surcharge de l'operateur -=
		void operator-= (const Vecteur& vec);		
		/// Surcharge de l'operateur *= : multiplication d'un scalaire par un vecteur
		void operator*= (double val);		
		/// Surcharge de l'operateur == : test d'egalite entre deux vecteurs
		int operator== (const Vecteur& vec) const ;
		/// Surcharge de l'operateur !=
		/// Renvoie 1 si les deux vecteurs ne sont pas egaux
		/// Renvoie 0 sinon
		int operator!= (const Vecteur& vec) const ;
		/// Surcharge de l'operateur = : realise l'egalite de deux vecteurs
		Vecteur& operator= (const Vecteur& vec);		
		// Surcharge de l'operateur = : affectation a partir d'un point
// trop dangereux, il vaut mieux utiliser la conversion explicite		
//		Vecteur& operator= ( const  Coordonnee& point);		
//        Vecteur& Egale_Coordonnee( const  Coordonnee& point);
		/// affectation avec un MV_Vecteur
  Vecteur& operator= ( const MV_Vector<double> & A);
		/// Surcharge de l'operateur * : multiplication d'un vecteur par un scalaire
  Vecteur operator* (double val)  const ;
		/// Surcharge de l'operateur / : division des composantes d'un vecteur par un scalaire
		Vecteur operator/ ( const double val) const ;		
		/// Surcharge de l'operateur /= : division des composantes d'un vecteur par un scalaire
		void operator/= ( const double val);
		/// Surcharge de l'operateur * : multiplication entre deux vecteurs
		/// Permet de realiser le produit scalaire entre deux vecteurs
		double operator* (const Vecteur& vec) const ;
		/// Retourne la ieme composante du vecteur : acces en lecture uniquement
		double operator() (int i) const; 
		/// Retourne la ieme composante du vecteur : acces en lecture et en ecriture
		double& operator() (int i);
		/// Surcharge de l'operateur ! : renvoie la norme d'un vecteur
		double operator! () const ;
		/// mise a zero d'un vecteur
		void Zero(); 
		/// initialise toutes les composantes à val
  void Inita(double val);
		/// calcul le produit P(i) = (*this)(i) * A(i); ramène P qui est passé en paramètre
		Vecteur& Prod_ii(const Vecteur& A, Vecteur& P) const;
  /// -- création explicite de coordonnees équivalentes
  Coordonnee Coordo() const;
  /// -- création explicite de coordonnees équivalentes
  CoordonneeH CoordoH() const;
  /// -- création explicite de coordonnees équivalentes
  CoordonneeB CoordoB() const;
 
  /// 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
  Vecteur& Egale_une_partie_de(const Vecteur& vec,int indice); 
  /// 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
  Vecteur& Une_partie_egale(int indice, const Vecteur& vec); 
  
  /// methode pour la compatibilite avec des classes derivees
  Vecteur & Vect();
  /// 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
  MV_Vector <double> MV_vecteur_double();
  const MV_Vector <double> MV_vecteur_double() const ;
  /// spécifiquement à la classe MV_Vector<double>
  /// ramène un pointeur de nouveau vecteur MV_Vector <double> qui utilise la même place
  /// mémoire que this ce qui pemet d'utiliser le type MV_Vector
  MV_Vector<double> * Nouveau_MV_Vector_double();
  /// idem en const
  const MV_Vector<double> * Nouveau_MV_Vector_double_const() const;
		
	protected :
	
	
		int taille; // taille du vecteur
		double* v; // pointeur sur les composantes du vecteur
		
		
		// fonction protégé pour l'accès directe au pointeur, utilisé
		// par MV_Vector<double> pour créer un vecteur à la même place
		double * Pointeur_vect() {return v;}
	
};

 /// @}  // end of group

/// @addtogroup Les_classes_Vecteur
///  @{
///


/// définition d'une classe de jonction entre les Vecteurs et les MV_Vecteurs
class MV_Vecteur : public MV_Vector<double>, public Vecteur
{
	
// Pour l'instant il y a des possibilités de pb due à des possibles
// non syncrhonisation entre des modifications des deux parties	
	public :
   /// par défaut
	  MV_Vecteur ()  { }; // défaut
	    
	  /// utilise la même place mémoire que vec
	  MV_Vecteur (const Vecteur& vec) :
	    Vecteur(vec)
	     { p_ = v ;dim_ = taille ;ref_=1;};
   /// de copie
	  MV_Vecteur (const MV_Vector<double>& vec) :
	    MV_Vector<double>(vec)
	     { taille = dim_; v = p_;ref_=1;};
	     
	  /// Change la taille du vecteur (la nouvelle taille est n)
	  void Change_taille (int )
	    { cout << "\n erreur !! fonction pour l'instant interdite "
	           << " dans le cas d'objet de type MV_Vecteur "
	           << "\n MV_Vecteur::Change_taille (int n)";
	      Sortie(1);
	     };     		
	  /// Permet de desallouer l'ensemble des elements du vecteur
	  void Libere()
	    { cout << "\n erreur !! fonction pour l'instant interdite "
	           << " dans le cas d'objet de type MV_Vecteur "
	           << "\n MV_Vecteur::Libere()";
	      Sortie(1);
	     };     		
	     
	  
 };	  
/// @}  // end of group

#ifndef MISE_AU_POINT
  #include "Vecteur.cc"
  #define  VECTEUR_H_deja_inclus
#endif

//#include "Coordonnee.h"

#endif
