//----------------------------------------------------------- // Classes Sequence, RandomSequence, EnumeratedSequence ... // Utility classes for template numerical arrays // SOPHYA class library - (C) UPS+LAL IN2P3/CNRS , CEA-Irfu // R. Ansari , C.Magneville 03/2000 //----------------------------------------------------------- // Utility classes for template numerical arrays // R. Ansari, C.Magneville 03/2000 #ifndef UtilArray_SEEN #define UtilArray_SEEN #include "machdefs.h" #include "mutyv.h" #include "randinterf.h" #include #include namespace SOPHYA { /* Quelques utilitaires pour les tableaux (Array) */ /*! \ingroup TArray \typedef Arr_DoubleFunctionOfX \brief define a function of double which returns a double */ typedef double (* Arr_DoubleFunctionOfX) (double x); /*! \ingroup TArray \typedef Arr_FloatFunctionOfX \brief define a function of float which returns a float */ typedef float (* Arr_FloatFunctionOfX) (float x); /*! \ingroup TArray \typedef Arr_ComplexDoubleFunctionOfX \brief define a function of a complex which returns a complex */ typedef std::complex (* Arr_ComplexDoubleFunctionOfX) (std::complex x); /*! \ingroup TArray \typedef Arr_ComplexFloatFunctionOfX \brief define a function of complex which returns a complex */ typedef float (* Arr_ComplexFloatFunctionOfX) (std::complex x); ////////////////////////////////////////////////////////// //! Class to generate a sequence of values class Sequence { public: virtual ~Sequence(); virtual MuTyV & Value(sa_size_t k) const = 0; inline MuTyV & operator () (sa_size_t k) const { return(Value(k)) ; } }; class RandomSequence : public Sequence { public: //! to define the generator type enum { Gaussian = 0, //!< gaussian generator Flat = 1 //!< Flat generator }; explicit RandomSequence(int typ = RandomSequence::Gaussian, double m=0., double s=1.); explicit RandomSequence(RandomGeneratorInterface& rgen, RNDTypes rtyp=C_RND_Gaussian, double mean=0., double sigma=1.); virtual ~RandomSequence(); virtual MuTyV & Value(sa_size_t k) const ; double Next() const ; protected: RNDTypes typ_; //!< random generation type double mean_, sig_; //!< generation parameters mean and sigma (if needed) mutable MuTyV retv_; mutable RandomGeneratorInterface* rgp_; }; ////////////////////////////////////////////////////////// //! Class to generate a sequence of values class RegularSequence : public Sequence { public: explicit RegularSequence (double start=0., double step=1., Arr_DoubleFunctionOfX f=NULL); virtual ~RegularSequence(); //! return start value of the sequence inline double & Start() { return start_; } //! return step value of the sequence inline double & Step() { return step_; } virtual MuTyV & Value(sa_size_t k) const ; protected: double start_; //!< start value of the sequence double step_; //!< step value of the sequence Arr_DoubleFunctionOfX myf_; //!< pointer to the sequence function mutable MuTyV retv_; }; ////////////////////////////////////////////////////////// //! Class for creation and handling of an explicitly defined list of values class EnumeratedSequence : public Sequence { public: explicit EnumeratedSequence(); EnumeratedSequence(EnumeratedSequence const & es); virtual ~EnumeratedSequence(); virtual MuTyV & Value(sa_size_t k) const ; inline sa_size_t Size() const { return vecv_.size(); } EnumeratedSequence & operator , (MuTyV const & v); EnumeratedSequence & operator = (MuTyV const & v); EnumeratedSequence & operator = (EnumeratedSequence const & es); inline void Clear() { vecv_.clear(); } void Print(std::ostream& os) const; sa_size_t Append(EnumeratedSequence const & seq); sa_size_t Append(std::string const & str, int & nbad, const char* sep=" \t"); sa_size_t FillFromFile(std::istream& is, sa_size_t& nr, sa_size_t& nc, char clm='#', const char* sep=" \t"); private: std::vector vecv_; mutable MuTyV retv_; }; //! prints/displays the enumerated sequence on the ostream \b os inline std::ostream& operator << (std::ostream& os, const EnumeratedSequence& a) { a.Print(os); return(os); } //inline EnumeratedSequence operator , (MuTyV const & a, MuTyV const & b) //{ EnumeratedSequence seq; return ((seq,a),b) ; } ////////////////////////////////////////////////////////// //! Class to define a range of indexes class Range { public: //! Index range containing a single index = \b start Range(sa_size_t start); //! Index range start \<= index \<= end Range(sa_size_t start, sa_size_t end); //! Index range start \<= index \<= end with increment step Range(sa_size_t start, sa_size_t end, sa_size_t step); //! General Index range specification, using size or start/end and increment Range(sa_size_t start, sa_size_t end, sa_size_t size, sa_size_t step); //! Index range specified as a string, in the form start:end:step Range(std::string s); //! copy constructor Range(Range const & a); //! copy (equal) operator Range& operator = (Range const & a); //! tests the equality between two Range object - return true if equal bool IsEqual(Range const & a) const; //! Return a reference to the start index inline sa_size_t & Start() { return start_; } //! Return a reference to the last index inline sa_size_t & End() { return end_; } //! Return a reference to the size inline sa_size_t & Size() { return size_; } //! Return a reference to the step inline sa_size_t & Step() { return step_; } //! Return the start index (const version) inline sa_size_t Start() const { return start_; } //! Return the last index (const version) inline sa_size_t End() const { return end_; } //! Return the size (const version) inline sa_size_t Size() const { return size_; } //! Return the step (const version) inline sa_size_t Step() const { return step_; } //! prints/displays the Range object on the ostream \b os - No new line appended std::ostream& Print(std::ostream& os) const; //! return a constant value defining the first element inline static sa_size_t firstIndex() { return 0; } //! return a constant value as a placeholder for the last valid index inline static sa_size_t lastIndex() { return -1; } //! return a Range object specifing all indices, from first to last inline static Range all() { return Range(Range::firstIndex() , Range::lastIndex()); } //! return a Range object specifing the first index inline static Range first() { return Range(Range::firstIndex() , Range::firstIndex(), 1, 1); } //! return a Range object specifing the last valid index inline static Range last() { return Range(Range::lastIndex() , Range::lastIndex(), 1, 1); } //! return a vector of ranges decoding the provided string as [rs1,rs2,...] with rs=start:end:step static std::vector str2vranges(std::string s); //! For internal TArray module use. void Update(sa_size_t osz); protected: sa_size_t start_; //!< start index sa_size_t end_; //!< end index sa_size_t size_; //!< size sa_size_t step_; //!< step }; //! equality comparison operator between two ranges inline bool operator == (Range const& a1, Range const& a2) { return a1.IsEqual(a2); } //! inequality comparison operator between two ranges inline bool operator != (Range const& a1, Range const& a2) { return !(a1.IsEqual(a2)); } //! prints/displays the Range objet on the ostream \b os inline std::ostream& operator << (std::ostream& os, const Range& a) { a.Print(os); return(os); } ////////////////////////////////////////////////////////// //! Class to define an identity matrix class IdentityMatrix { public: explicit IdentityMatrix(double diag=1., sa_size_t n=0); //! return the size of the identity matrix inline sa_size_t Size() { return size_; } //! return the value of the diagonal elements inline double Diag() { return diag_; } protected: sa_size_t size_; //!< size of the matrix double diag_; //!< value of the diagonal elements }; /*! \class SOPHYA::Range_Array_Grp \ingroup TArray \brief A utiliy class to gather an array and set of Range specification This class is a utility object returned by SOPHYA::RangeArrayGroup() functions, and specify the portion of a multi-dimensional data set. */ template class TArray; template class Range_Array_Grp { public: explicit Range_Array_Grp() : arrp_(nullptr) { } explicit Range_Array_Grp(TArray & arr) : arrp_(&arr) { } TArray * arrp_; std::vector vr_; }; /*! \fn SOPHYA::RangeArrayGroup \ingroup TArray \brief A utiliy function to ease creation of Range_Array_Grp from Ranges and an array Note that the optional flag \b fgrevdim, reverses the order of Ranges put in the corresponding vector in Range_Array_Grp if set to true. The default order (fgrevdim=false) correspond to the SOPHYA::TArray convention. The first element in the vector correspond to SizeX/OffsetX. */ //! Creates a Range_Array_Grp corresponding to a one-dimensional array template inline Range_Array_Grp RangeArrayGroup(Range const & r1, TArray & arr) { Range_Array_Grp sa(arr); sa.vr_.push_back(r1); return sa; } //! Creates a Range_Array_Grp corresponding to a two-dimensional array template inline Range_Array_Grp RangeArrayGroup(Range const & r1, Range const & r2, TArray & arr, bool fgrevdim=false) { Range_Array_Grp sa(arr); if (fgrevdim) { sa.vr_.push_back(r1); sa.vr_.push_back(r2); } else { sa.vr_.push_back(r2); sa.vr_.push_back(r1); } return sa; } //! Creates a Range_Array_Grp corresponding to a three-dimensional array template inline Range_Array_Grp RangeArrayGroup(Range const & r1, Range const & r2, Range const & r3, TArray & arr, bool fgrevdim=false) { Range_Array_Grp sa(arr); if (fgrevdim) { sa.vr_.push_back(r1); sa.vr_.push_back(r2); sa.vr_.push_back(r3); } else { sa.vr_.push_back(r3); sa.vr_.push_back(r2); sa.vr_.push_back(r1); } return sa; } //! Creates a Range_Array_Grp corresponding to a four-dimensional array template inline Range_Array_Grp RangeArrayGroup(Range const & r1, Range const & r2, Range const & r3, Range const & r4, TArray & arr, bool fgrevdim=false) { Range_Array_Grp sa(arr); if (fgrevdim) { sa.vr_.push_back(r1); sa.vr_.push_back(r2); sa.vr_.push_back(r3); sa.vr_.push_back(r4); } else { sa.vr_.push_back(r4); sa.vr_.push_back(r3); sa.vr_.push_back(r2); sa.vr_.push_back(r1); } return sa; } //! Creates a Range_Array_Grp corresponding to a five-dimensional array template inline Range_Array_Grp RangeArrayGroup(Range const & r1, Range const & r2, Range const & r3, Range const & r4, Range const & r5, TArray & arr, bool fgrevdim=false) { Range_Array_Grp sa(arr); if (fgrevdim) { sa.vr_.push_back(r1); sa.vr_.push_back(r2); sa.vr_.push_back(r3); sa.vr_.push_back(r4); sa.vr_.push_back(r5); } else { sa.vr_.push_back(r5); sa.vr_.push_back(r4); sa.vr_.push_back(r3); sa.vr_.push_back(r2); sa.vr_.push_back(r1); } return sa; } } // Fin du namespace #endif