/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/


//Warning : this file has been generated automatically by the phoenix_hdf5 program
//You can find it at https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS/PhoenixHDF5
//Do NOT modify it


#include <string.h>
#include <sstream>
#include "MatrixHdf5.h"

///Constructor of the class MatrixHdf5
MatrixHdf5::MatrixHdf5(){
	p__nbRow = 0lu;
	p__tableName = "matrix";
	p_nbCol = 0lu;
	p_nbRow = 0lu;
	p_tabMat = NULL;
}

///Destructor of the class MatrixHdf5
MatrixHdf5::~MatrixHdf5(){
	clear();
}

///Set the HDF5 name of the Table MatrixHdf5
/**	@param name : name of the table to be saved
*/void MatrixHdf5::setTableName(const std::string & name){
	p__tableName = name;
}

///Get the total number of rows in the current Table MatrixHdf5
/**	@return total number of rows
*/size_t MatrixHdf5::getNbEntries() const{
	return p__nbRow;
}

///Resize the table MatrixHdf5
/*	@param nbRow : new number of rows of the Table
*/
void MatrixHdf5::resize(size_t nbRow){
	if(nbRow == p__nbRow){return;}	//Nothing to do
	clear();
	allocate(nbRow);
}

///Clear the table MatrixHdf5 (delete all column)
void MatrixHdf5::clear(){
	if(p_tabMat != NULL){delete [] p_tabMat;p_tabMat = NULL;}
}

///Read the table MatrixHdf5 from given file
/**	@param fileName : name of the HDF5 file to be used
*/
void MatrixHdf5::read(const std::string & fileName){
	H5::H5File file(fileName, H5F_ACC_RDONLY);
	read(file);
}

///Read the table MatrixHdf5 from given file
/**	@param file : HDF5 file to be used
*/
void MatrixHdf5::read(const H5::H5File & file){
	H5::DataSet dataset = file.openDataSet(p__tableName);
	readDataSet(dataset);
}

///Read the table MatrixHdf5 from given group
/**	@param group : HDF5 group to be used
*/
void MatrixHdf5::read(const H5::Group & group){
	H5::DataSet dataset = group.openDataSet(p__tableName);
	readDataSet(dataset);
}

///Create and write the table MatrixHdf5 in given file
/**	@param fileName : name of the HDF5 file to be used
*/
void MatrixHdf5::write(const std::string & fileName) const{
	H5::H5File file(fileName, H5F_ACC_TRUNC);
	write(file);
}

///Create and write the table MatrixHdf5 in given file
/**	@param file : HDF5 file to be used
*/
void MatrixHdf5::write(H5::H5File & file) const{
	hsize_t dim[1];
	dim[0] = p__nbRow;
	H5::DataSpace space(1, dim);
	H5::DataSet dataset = file.createDataSet(p__tableName, getCompTypeAll(), space);
	writeDataSet(dataset);
}

///Create and write the table MatrixHdf5 in given file
/**	@param group : HDF5 group to be used
*/
void MatrixHdf5::write(H5::Group & group) const{
	hsize_t dim[1];
	dim[0] = p__nbRow;
	H5::DataSpace space(1, dim);
	H5::DataSet dataset = group.createDataSet(p__tableName, getCompTypeAll(), space);
	writeDataSet(dataset);
}

///Set a full row of the table MatrixHdf5
/**	@param i : index of the row to be set
 * 	@param tabMat : attribute to be set
*/
void MatrixHdf5::setRow(size_t i, float * tabMat){
	setTabMat(i, tabMat);
}

///Get a full row of the table MatrixHdf5 (without tensor copy, only with pointer)
/**	@param i : index of the row to get its values
 * 	@param[out] tabMat : attribute to be get
*/
void MatrixHdf5::getRow(size_t i, float *& tabMat){
	tabMat = getTabMat(i);
}

///Get a full row of the table MatrixHdf5 (without tensor copy, only with pointer)
/**	@param i : index of the row to get its values
 * 	@param[out] tabMat : attribute to be get
*/
void MatrixHdf5::getRow(size_t i, const float *& tabMat) const{
	tabMat = getTabMat(i);
}

///Set the attribute tabMat (column image)
/**	@param i : index of the row to be used
 * 	@param tabVal : table of value to be copied
*/
void MatrixHdf5::setTabMat(size_t i, const float * tabVal){
	size_t sizeRow(p_nbRow*p_nbCol);
	memcpy(p_tabMat + i*sizeRow, tabVal, sizeRow*sizeof(float));
}

///Get the full column of the attribute tabMat (column image)
/**	@return pointer of the full column
*/
const float * MatrixHdf5::getTabMatFull() const{
	return p_tabMat;
}

///Get the full column of the attribute tabMat (column image)
/**	@return pointer of the full column
*/
float * MatrixHdf5::getTabMatFull(){
	return p_tabMat;
}

///Get the tensor i of the attribute tabMat (column image)
/**	@param i : index of the row to be used
 * 	@return pointer to the corresponding tensor
*/
const float * MatrixHdf5::getTabMat(size_t i) const{
	return p_tabMat + i*p_nbRow*p_nbCol;
}

///Get the tensor i of the attribute tabMat (column image)
/**	@param i : index of the row to be used
 * 	@return pointer to the corresponding tensor
*/
float * MatrixHdf5::getTabMat(size_t i){
	return p_tabMat + i*p_nbRow*p_nbCol;
}

///Set all the dimentions of the Tensor in the table
/**	@param nbCol : set the tensor dimention nbCol
 * 	@param nbRow : set the tensor dimention nbRow
*/
void MatrixHdf5::setAllDim(size_t nbCol, size_t nbRow){
	setNbCol(nbCol);
	setNbRow(nbRow);
}

///Set the Tensor dimention nbCol
/**	@param val : set the tensor dimention nbCol
*/
void MatrixHdf5::setNbCol(size_t val){
	 p_nbCol = val;
}

///Get the Tensor dimention nbCol
/**	@return the tensor dimention nbCol
*/
size_t MatrixHdf5::getNbCol() const{
	return p_nbCol;
}

///Set the Tensor dimention nbRow
/**	@param val : set the tensor dimention nbRow
*/
void MatrixHdf5::setNbRow(size_t val){
	 p_nbRow = val;
}

///Get the Tensor dimention nbRow
/**	@return the tensor dimention nbRow
*/
size_t MatrixHdf5::getNbRow() const{
	return p_nbRow;
}

///Get the offset of the attribute tabMat
/**	@return offset of the attribute in bytes
*/
size_t MatrixHdf5::getOffsetTabMat() const{
	return 0lu;
}

H5::CompType MatrixHdf5::getCompTypeAll() const{
	size_t sizeAll(sizeof(float)*p_nbRow*p_nbCol);
	H5::CompType typeCol(sizeAll);
	typeCol.insertMember("image", getOffsetTabMat(), getTypeTabMat());
	return typeCol;
}

///Get DataType of attribute tabMat (column image)
/**	@return DataType of the attribute tabMat
*/
H5::CompType MatrixHdf5::getCompTypeTabMat() const{
	H5::CompType typeCol(sizeof(float)*p_nbRow*p_nbCol);
	typeCol.insertMember("image", 0, getTypeTabMat());
	return typeCol;
}

///Get DataType of attribute tabMat (column image)
/**	@return DataType of the attribute tabMat
*/
H5::DataType MatrixHdf5::getTypeTabMat() const{
	hsize_t dims[2];
	dims[0] = p_nbRow;
	dims[1] = p_nbCol;
	H5::ArrayType arrayType(H5::PredType::NATIVE_FLOAT, 2, dims);
	return arrayType;
}

///Read the given DataSet and fill the Table with it
/**	@param dataset : dataset to be used
*/
void MatrixHdf5::readDataSet(const H5::DataSet & dataset){
	H5::CompType compType = dataset.getCompType();
	readDimTabMat(compType);
	H5::DataSpace dataSpace = dataset.getSpace();
	size_t nbEntries(dataSpace.getSimpleExtentNpoints());
	resize(nbEntries);
	dataset.read(p_tabMat, getCompTypeTabMat());
}

///Write the given DataSet and fill the Table with it
/**	@param[out] dataset : dataset to be modified
*/
void MatrixHdf5::writeDataSet(H5::DataSet & dataset) const{
	dataset.write(p_tabMat, getCompTypeTabMat());
}

///Allocate the table MatrixHdf5 (delete all column)
/*	@param nbRow : new number of rows of the Table
*/
void MatrixHdf5::allocate(size_t nbRow){
	p__nbRow = nbRow;
	p_tabMat = new float[p__nbRow*p_nbRow*p_nbCol];
}

///Update the dimentions of the tensor tabMat (column 'image')
/**	@param compType : main type to be used to update the tensor dimentions*/
void MatrixHdf5::readDimTabMat(const H5::CompType & compType){
	int indexCol = compType.getMemberIndex("image");
	H5::ArrayType arrayType = compType.getMemberArrayType(indexCol);
	//Check if the number of dientions matches
	if(arrayType.getArrayNDims() != 2){
		std::stringstream strError;
		strError << "MatrixHdf5::readDimTabMat wrong number of dimentions : expect 2 but "<< arrayType.getArrayNDims() <<" provided from the file" << std::endl;
		throw std::runtime_error(strError.str());
	}
	hsize_t dims[2];
	arrayType.getArrayDims(dims);
	p_nbRow = dims[0];
	p_nbCol = dims[1];
}

