ParamData.hh 8.2 KB
/**
 * ParamData.hh
 *
 *  Created on: 17 oct. 2012
 *      Author: AKKA IS
 */

#ifndef PARAMDATA_HH_
#define PARAMDATA_HH_

#include <map>
#include <string>
#include <vector>
#include <cmath>
#include <math.h>
#include <limits>

#include <boost/shared_ptr.hpp>

#include <log4cxx/logger.h>

#include "AMDA_exception.hh"

#include "Demangle.hh"
#include "Parameter.hh"
#include "Container.hh"
#include "VisitorOfParamData.hh"

class NotANumber {
};

extern const NotANumber notANumber;

namespace AMDA {
namespace Parameters {

/**
 * @brief storage data of a Parameter
 *
 *	contain Time data and this implementation contain data value
 *	Respect design pattern Visitor is an visited element
 */
class ParamData {
public:
	typedef Container<double> BlockTimeTab;

	ParamData();
	virtual ~ParamData();

	/**
	 * get string accessor to an element
	 */
	static std::string getAccessor() {return "->get(index)";}

	BlockTimeTab& getTimeList() { return _blockTimeTab; }

	/**
	 * design pattern visitor
	 * accept a visitor
	 */
	virtual void accept(VisitorOfParamData &visitor) = 0;

	/**
	 * addTime in TimeSet
	 * @param dataNumber number data must be added in data set
	 * @param data data must be added in data set, the real type is known by the child of ParamData
	 */
	virtual void pushTime( double time) { _blockTimeTab.push_back(time); }

	/**
	 * addTime in TimeSet
	 * @param dataNumber number data must be added in data set
	 * @param data data must be added in data set, the real type is known by the child of ParamData
	 */
	virtual double getTime(unsigned int index) const { return _blockTimeTab[index]; }

	virtual void freeBefore(unsigned int pIndexMin) {
		_blockTimeTab.freeBefore(pIndexMin);
		_paramDataIndexInfo._startIndex=pIndexMin;
	}

	double getMinSampling() {
		return _minSampling;
	}
	void setMinSampling(double pMinSampling){  _minSampling = pMinSampling;}

	ParamDataIndexInfo &getIndexInfo() {
		_paramDataIndexInfo._nbDataToProcess = _blockTimeTab.size();
		return _paramDataIndexInfo;
	}


	virtual const char *getParamDataType() = 0;
	virtual const char *getElementType() = 0;

	virtual unsigned int getDim1()= 0;
	virtual unsigned int getDim2()= 0;
        
        virtual void updateDims() = 0;

	virtual void setNAN(unsigned int index) = 0;

	unsigned int getDataNumber() { return _blockTimeTab.size(); }

	void setFillValue(double fillValue) { _fillValue = fillValue; }

protected:

	/** logger of paramData */
	static log4cxx::LoggerPtr _logger;
	/**
	 * must be updated by ApramGet or process which sampling modify
	 */
	double _minSampling;


	double _fillValue;

private:


	/**
	 * vector of block of NB_DATA_BY_BLOCK data
	 */
	BlockTimeTab _blockTimeTab;

	ParamDataIndexInfo _paramDataIndexInfo;

};


template<class ElType, class ClassName>
class ParamDataSpec_CRTP : public ParamData{
public:
	/**
	 * alias of element type
	 */
	typedef ElType ElementType ;
	typedef ClassName ParamType ;

	ParamDataSpec_CRTP(int dim1=1, int dim2=2) : _dim1(dim1), _dim2(dim2) {}
	~ParamDataSpec_CRTP() {}

	typedef Container<ElementType> DataList;

	const ElementType& get(unsigned int index) const { return _dataList[index]; }
	DataList& getDataList() { return _dataList; }
	const DataList& getDataList() const { return _dataList; }
	double getMinSampling(){ return _minSampling;}

	void push(ElementType el) ;
	

	virtual unsigned int getDim1() { return _dim1; }
	virtual unsigned int getDim2() { return _dim2; }

        void setDim1(unsigned int dim1) { _dim1 = dim1; }
	void setDim2(unsigned int dim2) { _dim2 = dim2; }
        

	/**
	 * design pattern visitor
	 * accept a visitor
	 */
	virtual void accept(VisitorOfParamData &visitor) {
		visitor.visit(dynamic_cast<ParamType*>(this));
	}

	virtual void freeBefore(unsigned int indexMin) { ParamData::freeBefore(indexMin); _dataList.freeBefore(indexMin); }

	virtual const char *getParamDataType() { return Helpers::Demangle(typeid(ClassName).name());}
	virtual const char *getElementType() {return Helpers::Demangle(typeid(ElType).name());}

        virtual void updateDims() {
            if (_dataList.size() > 0)
                updateParamDataDims(get(0));
        }

	virtual void setNAN(unsigned int index) {
		ElType val;
		val << NotANumber();
		_dataList.replace(val,index);
	}

	
        
private:
    template<typename Type>
    void updateParamDataDims(Type /*data*/) {
        _dim1 = 1;
        _dim2 = 1;
    }
    
    template<typename Type>
    void updateParamDataDims(std::vector<Type> data) {
        _dim1 = data.size();
        _dim2 = 1;
    }

    template<typename Type>
    void updateParamDataDims(Tab2DData<Type> data) {
        _dim1 = data.getDim1Size();
        _dim2 = data.getDim2Size();
    }
    
    /**
     * vector of block of NB_DATA_BY_BLOCK data
    */
    DataList _dataList;

    unsigned int _dim1;
    unsigned int _dim2;

        
};

template <typename Type>
class ParamDataSpec;

template <class Type>
class ParamDataSpec: public ParamDataSpec_CRTP<Type, ParamDataSpec<Type> > {
public:
ParamDataSpec(int dim1=1,int dim2=1) : ParamDataSpec_CRTP<Type, ParamDataSpec<Type> >(dim1,dim2) {}
virtual ~ParamDataSpec() {}

};


	template <typename ElementType>
	ParamData* generate() { return NULL; }

	//ParamDataSpec<float> generate(float) { return ParamDataSpec<float>(); }
#define GENERATED_generate(Type) inline ParamDataSpec<Type> generate(Type) { return ParamDataSpec<Type>(); }\
inline ParamDataSpec<std::vector<Type> > generate(std::vector<Type>) { return ParamDataSpec<std::vector<Type> >(); }\
inline ParamDataSpec<Tab2DData<Type> > generate(Tab2DData<Type>) { return ParamDataSpec<Tab2DData<Type> >(); }

	GENERATED_generate(short)
	GENERATED_generate(float)
	GENERATED_generate(double)
	GENERATED_generate(long double)
	GENERATED_generate(int)
	GENERATED_generate(LogicalData)

} /* namespace Parameters */
} /* namespace AMDA */

class ElemNull {

};
extern const ElemNull elemNull;


#define GENARATED_SCALAIRE(type, val) \
		void operator <<(type &a, NotANumber b) ; \
		void operator <<(type &a, ElemNull b) ; \
		void applyFillValue(type &a, double fillVal) ;

GENARATED_SCALAIRE(short, SHRT_MIN)
GENARATED_SCALAIRE(float, NAN)
GENARATED_SCALAIRE(double, NAN)
GENARATED_SCALAIRE(long double, NAN)
GENARATED_SCALAIRE(int, INT_MIN)
GENARATED_SCALAIRE(AMDA::Parameters::LogicalData, AMDA::Parameters::LogicalData::NaN)

#define GENARATED_VECTOR(type, val) \
		void operator <<(std::vector<type> &a, NotANumber b); \
		void operator <<(std::vector<type> &a, ElemNull b); \
		void applyFillValue(std::vector<type> &a, double fillVal); 

GENARATED_VECTOR(short,SHRT_MIN)
GENARATED_VECTOR(float, NAN)
GENARATED_VECTOR(double, NAN)
GENARATED_VECTOR(long double, NAN)
GENARATED_VECTOR(int, INT_MIN)
GENARATED_VECTOR(AMDA::Parameters::LogicalData, AMDA::Parameters::LogicalData::NaN)

#define GENARATED_TAB2D(type, val) \
		void operator <<(AMDA::Parameters::Tab2DData<type> &a, NotANumber b); \
		void operator <<(AMDA::Parameters::Tab2DData<type> &a, ElemNull b); \
		void applyFillValue(AMDA::Parameters::Tab2DData<type> &a, double fillVal);

GENARATED_TAB2D(short,SHRT_MIN)
GENARATED_TAB2D(float, NAN)
GENARATED_TAB2D(double, NAN)
GENARATED_TAB2D(long double, NAN)
GENARATED_TAB2D(int, INT_MIN)
GENARATED_TAB2D(AMDA::Parameters::LogicalData, AMDA::Parameters::LogicalData::NaN)

template<class ElType, class ClassName>
void AMDA::Parameters::ParamDataSpec_CRTP<ElType, ClassName>::push(ElementType el) {
		if (!std::isnan(_fillValue))
			applyFillValue(el,_fillValue);
		_dataList.push_back(el); 
}

bool isNAN(short pval);
bool isNAN(float pval);
bool isNAN(double pval);
bool isNAN(long double pval);
bool isNAN(int pval);
bool isNAN(AMDA::Parameters::LogicalData pval);

bool isNAN(std::vector<short> pval);
bool isNAN(std::vector<float> pval);
bool isNAN(std::vector<double> pval);
bool isNAN(std::vector<long double> pval);
bool isNAN(std::vector<int> pval);
bool isNAN(std::vector<AMDA::Parameters::LogicalData> pval);

bool isNAN(AMDA::Parameters::Tab2DData<short> pval);
bool isNAN(AMDA::Parameters::Tab2DData<float> pval);
bool isNAN(AMDA::Parameters::Tab2DData<double> pval);
bool isNAN(AMDA::Parameters::Tab2DData<long double> pval);
bool isNAN(AMDA::Parameters::Tab2DData<int> pval);
bool isNAN(AMDA::Parameters::Tab2DData<AMDA::Parameters::LogicalData> pval);

bool isApproximatelyEqual(double a, double b);

#endif /* PARAMDATA_HH_ */