#pragma once
#ifndef CmapMat_H
#define  CmapMat_H

#include "stdafx.h"
#include <map>
#include <vector>
#define VALNOEXIST_FLOAT	(float) 1.e+30 
#define VALNOEXIST_INT		(int) -1 
#include "garray.h"
#include "th.h"

#pragma pack(8)
typedef struct HeadCostConj
{
	int		ver;		//versión
	bool	isVect;		// vect o map
	int		n;			//num de elems guardados
}HeadCostConj;
typedef struct HeadCostAng
{
	int		ver;	//versión
	int		n;		//num de elems guardados
}HeadCostAng;
#pragma pack (1)
typedef struct MapDataFloat{
	int k;
	float v;
}MapDataFloat;
typedef struct MapDataInt{
	int k;
	int v;
}MapDataInt;
#pragma pack(16)
#define  MAX_THREAD_LEE 8
//matixFloat---------------------------------------------
class UTILES_EXPORT CmapRowFloat
{
	
public:
	//*********************************
	//Variables
	bool isVect;
	int imin, imax;
	std::map<int, float> dat;
	std::vector<float> datv;
	//*********************************
	//Métodos
	CmapRowFloat()
	{
		isVect = false;
		imin=INT_MAX;
		imax=INT_MIN;
	}
	~CmapRowFloat(void)
	{
	}
	//******************************************************
	inline void set(int i, float v)
	{
		

		if(isVect)
			 datv[i]=v;
		else
		{
			if(v== VALNOEXIST_FLOAT)
				return;
			dat[i] = v;
			if(i<imin)
				imin=i;
			if(i>imax)
				imax=i;
		}
	}
	//******************************************************
	inline float operator[](int irow)
	{
		if(isVect)
			return datv[irow];
		if(irow< imin || irow>imax)
			return	VALNOEXIST_FLOAT;
		//si tiene esa clave la devuelve, si no, devuelve MAYUSCULO
		std::map<int, float>::iterator elem = dat.find(irow);
		if(elem == dat.end())
			//no tiene la clave
			return VALNOEXIST_FLOAT;
		return elem->second;
	}
	inline void configVector(int ymax)
	{
		isVect = true;
		dat.clear();

		//datv.reserve(ymax);
		datv.insert(datv.begin(),ymax,VALNOEXIST_FLOAT);

		bool inVector = false;
		/*for (int i =0 ; i<ymax; i++)
			datv.push_back(VALNOEXIST_FLOAT);*/
	}
	//ajusta map a memoria justa
	inline void memAjust()
	{
		
	}
	inline void clear()
	{
		dat.clear();
		datv.clear();
		isVect=false;
	}

	BOOL guarda(HeadCostConj hd, int ic, char *path , char *ext, Cgarray<MapDataFloat> *bufer = NULL);
	BOOL lee(int ic, char *path , char *ext, int ntot, BOOL mismosvect=TRUE, Cgarray<MapDataFloat> *bufer = NULL);
};
#define MAX_MEM_MAPFLOAT 1024.*1024.*300./sizeof(float)

class UTILES_EXPORT CmapMatFloat
{
public:
	//*********************************
	//Variables
	std::vector<CmapRowFloat> dat;
	
	//*********************************
	//Métodos
	CmapMatFloat()
	{
	}
	~CmapMatFloat(void)
	{
	}
	//******************************************************
	inline CmapRowFloat& operator[](int irow)
	{
		return dat[irow];
	}

	inline void set(int x, int y, float val)
	{
		if(val>= VALNOEXIST_FLOAT)
			return;
		
		dat[x].set(y,val);
	}
	//ajusta los map a la memoria minima posible
	inline void memAjust()
	{
		for(std::vector<CmapRowFloat>::iterator elem = dat.begin(); elem!= dat.end(); elem++)
		{
			elem->memAjust();
		}
	}
	inline void clear()
	{
		dat.clear();
	}

	//reparte los nvect disponibles entre los threads, poniendo las primeras filas de cada uno de vect
	inline void inicializa(int xmax, int nthr, int nvect=-1)
	{		
		dat.reserve(xmax);
		bool inVector = false;
		if(nvect<0)
			nvect =(int)(MAX_MEM_MAPFLOAT/xmax);

		int vectthr=0,novecthr=0,iparc=0;
		if(nvect<xmax)
		{
			vectthr = (int)(nvect*1./nthr);
			novecthr = (int)((xmax-nvect)*1./nthr);
		}
		//xmax = novec;
		for (int i =0 ; i<xmax; i++)
		{
			dat.push_back(CmapRowFloat());
			if(nvect>=xmax)
				dat[i].configVector(xmax);
			else if(nvect>0)
			{
				if((i-iparc)<vectthr)
					dat[i].configVector(xmax);
				else if((i-iparc)>=(vectthr+novecthr))
					iparc+=vectthr+novecthr;
			}
		}
	} 
	BOOL lee(char *path, char *ext, BOOL mismosvect=TRUE);
	BOOL leeThread( char *path, char *ext, int nthread, BOOL mismosvect/*=TRUE*/);
};
class  UTILES_EXPORT ThMapMatFloatLee: public Cth
{
public:
	CmapMatFloat *pclas;
	int ini;//fila inicio 
	int fin;//fila fin
	int ithr;
	BOOL mal;//indica si ha ido bien
	BOOL mismosvect;
	char*path;
	char*ext;
	virtual void run();
};
class UTILES_EXPORT CmapRowInt
{
public:
	//*********************************
	//Variables
	std::map<int, int> dat;
	std::vector<int> datv;
	int imin, imax;
	bool isVect;
	//*********************************
	//Métodos
	CmapRowInt()
	{
		imin=INT_MAX;
		imax=INT_MIN;
		isVect = false;
	}
	~CmapRowInt(void)
	{
	}
	//******************************************************
	inline void set(int i, int v)
	{
		if(v== VALNOEXIST_INT)
			return;

		if(isVect)
			 datv[i]=v;
		else
			dat[i] = v;

		if(i<imin)
			imin=i;
		if(i>imax)
			imax=i;
	}
	//******************************************************
	inline int operator[](int irow)
	{
		if(isVect)
			return datv[irow];
		if(irow< imin || irow>imax)
			return	-1;

		//si tiene esa clave la devuelve, si no, devuelve MAYUSCULO
		std::map<int, int>::iterator elem = dat.find(irow);
		if(elem == dat.end())
			//no tiene la clave
			return VALNOEXIST_INT;
		return elem->second;
	}
	//ajusta map a memoria justa
	inline void memAjust()
	{

	}
	inline void configVector(int ymax)
	{
		isVect = true;
		dat.clear();
		datv.insert(datv.begin(),ymax,VALNOEXIST_INT);
		/*datv.reserve(ymax);
		for (int i =0 ; i<ymax; i++)
			datv.push_back(VALNOEXIST_INT);*/
	}
	void clear()
	{
		isVect = false;
		dat.clear();
		datv.clear();
	}
	BOOL guarda(HeadCostConj hd, int ic, char *path , char *ext);
	BOOL lee(int ic, char *path, char *ext, BOOL mismosvect=TRUE );
};
#define MAX_MEM_MAPINT 1024.*1024.*200./sizeof(int)
class UTILES_EXPORT CmapMatInt
{
public:
	//*********************************
	//Variables
	std::vector<CmapRowInt> dat;
	
	//*********************************
	//Métodos
	CmapMatInt()
	{
	}
	~CmapMatInt(void)
	{
	}
	//******************************************************
	inline CmapRowInt& operator[](int irow)
	{
		return dat[irow];
	}

	inline void set(int x, int y, int val)
	{
		if(val== VALNOEXIST_INT)
			return;
		dat[x].set(y,val);
	}
	//ajusta los map a la memoria minima posible
	inline void memAjust()
	{
		for(std::vector<CmapRowInt>::iterator elem = dat.begin(); elem!= dat.end(); elem++)
		{
			elem->memAjust();
		}
	}
	inline void clear()
	{
		dat.clear();
	}
	
	inline void inicializa(int xmax, int nthr, int nvect=-1)
	{
		dat.reserve(xmax);
		bool inVector = false;
		if(nthr<=0)
			nthr=1;
		if(nvect<0)
			nvect =(int)(MAX_MEM_MAPINT/xmax);
		int vectthr=0,novecthr=0,iparc=0;
		if(nvect<xmax)
		{
			vectthr = (int)(nvect*1./nthr);
			novecthr = (int)((xmax-nvect)*1./nthr);
		}

		for (int i =0 ; i<xmax; i++)
		{
			dat.push_back(CmapRowInt());
			if(nvect>=xmax)//nvec>=xmax
				dat[i].configVector(xmax);
			else if(nvect==0)
				continue;
			else
			{
				if((i-iparc)<vectthr)
					dat[i].configVector(xmax);
				else if((i-iparc)>=(vectthr+novecthr))
					iparc+=vectthr+novecthr;
			}
		}
	}
		 
};

#endif