#include"tools.h"
namespace EVO {
	string GetInfoINCAR(char key[])
	{
		FILE* fp = fopen("INCAR", "r");
		string value;
		if (fp == NULL)
		{
			perror("INCAR IS NOT EXIST!\n");
			exit(1);
		}
		char buf[1024];
		int iat = 0;
		while (fgets(buf, 1024, fp) != NULL)
		{
			if (strstr(buf, key) != NULL)
			{
				for (int i = 0; i < strlen(buf); i++)
				{
					if (buf[i] == '#')
						break;
					if (buf[i] == '=')
						iat = 1;
					if (iat)
					{
						if (buf[i] != '=' && buf[i] != ' ')
							value.push_back(buf[i]);
					}
				}
			}
		}
		fclose(fp);
		return value;
	}

	int IsNum(string symbol)
	{
		for (int i = 0; i < symbol.length(); i++)
		{
			int tmp = (int)symbol[i];
			if (tmp >= 48 && tmp <= 57)
			{
				continue;
			}
			else
			{
				return false;
			}
		}
		return true;
	}

	vector<double> AddVec(vector<double> v1, vector<double> v2)
	{
		vector<double> ret;
		if (v1.size() != v2.size())
			return ret;
		ret.resize(v1.size());
		for (int i = 0; i < v1.size(); i++)
			ret[i] = v1[i] + v2[i];
		return ret;
	}

	vector<double> operator-(vector<double> v1, double value)
	{
		vector<double> ret;
		ret.resize(v1.size());
		for (int i = 0; i < v1.size(); i++)
			ret[i] = v1[i] - value;
		return ret;
	}

	vector<double> operator+(vector<double> v1, vector<double> v2)
	{
		vector<double> ret;
		if (v1.size() != v2.size())
			return ret;
		ret.resize(v1.size());
		for (int i = 0; i < v1.size(); i++)
			ret[i] = v1[i] + v2[i];
		return ret;
	}

	vector<double> operator*(vector<double> v1, vector<double> v2)
	{
		vector<double> ret;
		if (v1.size() != v2.size())
			return ret;
		ret.resize(v1.size());
		for (int i = 0; i < v1.size(); i++)
			ret[i] = v1[i] * v2[i];
		return ret;
	}

	vector<double> Intergral(vector<double> v1, vector<double> v2)
	{
		vector<double> v3;
		if (v1.size() != v2.size())
			return v3;
		v3.push_back(0);
		for (int i = 1; i < v1.size(); i++)
			v3.push_back((v1[i] - v1[i - 1]) * (v2[i] + v2[i - 1]) / 2 + v3[i - 1]);
		return v3;
	}

	double SumVec(vector<double> v)
	{
		double sum = 0;
		for (int i = 0; i < v.size(); i++)
			sum += v[i];
		return sum;
	}

	double volume(double a[3][3])
	{
		double odd = 0;
		double even = 0;
		for (int i = 0; i < 3; i++)
			odd += a[0][i] * a[1][(i + 1) % 3] * a[2][(i + 2) % 3];
		for (int i = 0; i < 3; i++)
			even += a[0][i] * a[1][(i + 2) % 3] * a[2][(i + 1) % 3];
		return fabs(odd - even);
	}

	void RecMat(double POSI[3][3], double ret[3][3])
	{
		double v = volume(POSI);
		if (v == 0)
			v == 1;
		ret[0][0] = (POSI[1][1] * POSI[2][2] - POSI[1][2] * POSI[2][1]) * (2 * Pi) / v;
		ret[0][1] = -(POSI[1][0] * POSI[2][2] - POSI[1][2] * POSI[2][0]) * (2 * Pi) / v;
		ret[0][2] = (POSI[1][0] * POSI[2][1] - POSI[1][1] * POSI[2][0]) * (2 * Pi) / v;
		ret[1][0] = -(POSI[0][1] * POSI[2][2] - POSI[0][2] * POSI[2][1]) * (2 * Pi) / v;
		ret[1][1] = (POSI[0][0] * POSI[2][2] - POSI[0][2] * POSI[2][0]) * (2 * Pi) / v;
		ret[1][2] = -(POSI[0][0] * POSI[2][1] - POSI[0][1] * POSI[2][0]) * (2 * Pi) / v;
		ret[2][0] = (POSI[0][1] * POSI[1][2] - POSI[1][1] * POSI[0][2]) * (2 * Pi) / v;
		ret[2][1] = -(POSI[0][0] * POSI[1][2] - POSI[1][0] * POSI[0][2]) * (2 * Pi) / v;
		ret[2][2] = (POSI[1][1] * POSI[0][0] - POSI[1][0] * POSI[0][1]) * (2 * Pi) / v;
	}

	void copy_vec3d(double vec1[3][3], double vec2[3][3])
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				vec2[i][j] = vec1[i][j];
	}

	void multi_mat(double mat1[3][3], double mat2[3][3], double multi_mat[3][3])
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				multi_mat[i][j] = mat1[i][0] * mat2[0][j] + mat1[i][1] * mat2[1][j] + mat1[i][2] * mat2[2][j];
			}
		}
	}

	bool Isequal(double a, double b, double SYMPREC)
	{
		return fabs(a - b) > SYMPREC ? 0 : 1;
	}

	vector<int> ExtractNumbersFromString(char a[], int len)
	{
		int i, j, count = 0, wei[20], times = 0;
		vector<int> num(len);
		bool ctoi = 0, befctoi = 0;
		for (i = 0; i < len + 1; i++)
		{
			if (a[i] >= '0' && a[i] <= '9')
			{
				ctoi = 1;
			}
			else
			{
				ctoi = 0;
			}
			if (befctoi == 0 && ctoi == 1)
			{
				wei[count] = a[i] - '0';
				befctoi = 1;
				count++;
			}
			else if (befctoi == 1 && ctoi == 1)
			{
				wei[count] = a[i] - '0';
				count++;
			}
			else if (befctoi == 1 && ctoi == 0)
			{
				for (j = 0; j < count; j++)
				{
					num[times] += wei[j] * pow(10, count - j - 1);
				}
				times++;
				befctoi = 0;
				count = 0;
			}
		}
		return num;
	}

	double maxvalue(vector<double> v)
	{
		double ret = v[0];
		for (int i = 1; i < v.size(); i++)
			ret = max(ret, v[i]);
		return ret;
	}

	double minvalue(vector<double> v)
	{
		double ret = v[0];
		for (int i = 1; i < v.size(); i++)
			ret = min(ret, v[i]);
		return ret;
	}

	double maxvalue(vector<vector<double> >v)
	{
		double ret = v[0][0];
		for (int i = 0; i < v.size(); i++)
			for (int j = 0; j < v[i].size(); j++)
				ret = max(ret, v[i][j]);
		return ret;
	}

	double minvalue(vector<vector<double> >v)
	{
		double ret = v[0][0];
		for (int i = 0; i < v.size(); i++)
			for (int j = 0; j < v[i].size(); j++)
				ret = min(ret, v[i][j]);
		return ret;
	}

	string RemovePostfixNum(string elem)
	{
		int length = elem.size();
		for (int i = 0; i < elem.length(); i++)
		{
			int tmp = (int)elem[i];
			if (tmp >= 48 && tmp <= 57)
			{
				length = i;
				break;
			}
		}
		string ret(elem.begin(), elem.begin() + length);
		return ret;
	}

	vector<int> closest::getclosest(vector<pair<int, int> > v, int target)
	{
		globaldelta = target;
		backtrack(v, 0, 0, target, target);
		return result;
	}

	bool mysort(pair<int, int> a, pair<int, int> b)
	{
		return a.second < b.second;
	}

	void closest::backtrack(vector<pair<int, int> > v, int start, int sum, int delta, int target)
	{
		set<int> record;
		if (delta < globaldelta) {
			globaldelta = delta;
			result = path;
		}
		if (delta == 0)
			return;
		int limit = 1e10;
		for (int i = start; i < v.size(); i++) {
			if (v[i].second >= limit)
				continue;
			if (find(record.begin(), record.end(), v[i].second) != record.end())
				continue;
			record.insert(v[i].second);
			sum += v[i].second;
			int newdelta = abs(sum - target);
			if (newdelta > delta) {
				limit = v[i].second;
				sum -= v[i].second;
				continue;
			}
			path.push_back(i);
			backtrack(v, i + 1, sum, newdelta, target);
			sum -= v[i].second;
			path.pop_back();
		}
	}
}
