//   Class for representing spherical harmonic coefficients
//              G. Le Meur      2000
// DAPNIA/SPP (Saclay) / CEA    LAL - IN2P3/CNRS  (Orsay)

#ifndef ALM_SEEN
#define ALM_SEEN

#include "randinterf.h"
#include "nbmath.h"
#include "trngmtx.h"
#include "tvector.h"

namespace SOPHYA {  

// ----- Classe Alm 
template <class T>
class Alm : public LowerTriangularMatrix< complex<T> > {
public :
 
  Alm() : LowerTriangularMatrix<complex<T> >()  {}
//! instanciate the class from the maximum value of the index \f$l\f$ in the sequence of the \f$a_{lm}\f$'s 
  Alm(sa_size_t nlmax) : LowerTriangularMatrix<complex<T> >(nlmax+1) {}
//! copy constructor 
  Alm(const Alm<T>& a,  bool share=false)  : LowerTriangularMatrix<complex<T> >(a, share)  {}
//! Constructor, generates alm from a cl vector
  Alm(const TVector<T> & clin, const r_8 fwhm) ;
//! Constructor, generates alm from a cl vector, using the specified random generator object
  Alm(const TVector<T> & clin, const r_8 fwhm, RandomGeneratorInterface& rg);

//! Resize with a new lmax 
  inline void ReSizeToLmax(sa_size_t nlmax) {this->ReSizeRow(nlmax+1);}
  inline sa_size_t Lmax() const {return this->rowNumber()-1;}

//! Computes the corresponding pwer spectrum (Cl vector)
  TVector<T> powerSpectrum() const;

  inline  Alm<T>& SetComplexT(complex<T> a)
    {  this->SetT(a);  return *this;  }
  inline Alm<T>& operator = (complex<T> a)
    {  return SetComplexT(a);  } 

private:
  void GenFromCl(const TVector<T> & clin, const r_8 fwhm, RandomGeneratorInterface& rg);
};


//------------ Classe Bm , vecteur avec index  -mMax <= index <= +mMax 
template <class T>
class Bm  {
public :
  Bm(): nmmax_(0) {;};
//! Constructor with the specification of the maximum absolute value of the index : |mMax|
//! Copy contrsuctor 
  Bm(sa_size_t mmax) : nmmax_(mmax)   { bm_.ReSize( (2*mmax+1) );}
  Bm(const Bm<T>& b,  bool share=false) : nmmax_(b.nmmax_), bm_(b.bm_, share) { }
 //! resize with a new value of mmax 
  inline void ReSizeToMmax(sa_size_t mmax) 
    { nmmax_= mmax; bm_.ReSize(2* nmmax_+1); }

//! Acces to element with index m  ( -mMax <= m <= +mMax  ) 
  inline T operator()(sa_size_t m) const { return bm_( m+nmmax_); }
//! Acces to element with index m  ( -mMax <= m <= +mMax  ) 
  inline T& operator()(sa_size_t m) { return bm_( m+nmmax_); }

//! Return the current value of the maximum absolute value of the index 
  inline sa_size_t Mmax() const   { return nmmax_; }

  inline Bm<T>& operator = (const Bm<T>& b)
    {
    if (this != &b) {
       nmmax_= b.nmmax_;
       bm_=  b.bm_;
       }
    return *this;
    }


 private:
  sa_size_t nmmax_;
  NDataBlock<T> bm_;
  };

} // namespace SOPHYA

#endif
