//Functions of points, sets.
#include "function.h"

datapoint operator +(datapoint a,datapoint b){
	for(int i = 1; i < a.size(); i++) a[i] += b[i];
	return a;
}

datapoint operator -(datapoint a,datapoint b){
	for(int i = 1; i < a.size(); i++) a[i] -= b[i];
	return a;
}

datapoint operator *(datapoint a, double b){
	for(int i = 1; i < a.size(); i++) a[i] *= b;
	return a;
}

datapoint operator /(datapoint a, double b){
	for(int i = 1; i < a.size(); i++) a[i] /= b;
	return a;
}

double norm(const datapoint &x){
	double ret = 0;
	for(int i = 1; i < x.size(); i++) 
		ret += x[i] * x[i];
	return sqrt(ret);
}

double dist(const datapoint &x, const datapoint &y){
	double d = 0;
	for(int i = 1; i < x.size(); i++)
		d += (x[i] - y[i]) * (x[i] - y[i]);
	return sqrt(d);
}

double dist(const datapoint &x,const dataset &C){
	if(C.empty()) return 1;
	double d = dist(x, C[0]);
	for(datapoint c : C) d = min(d, dist(x,c));
	return d;
}

datapoint NN(const datapoint &x, const dataset &C){
	datapoint c = C[0];
	for(datapoint y : C)
		if(dist(x, y) < dist(x, c)) c = y;
	return c;
}

double cost(const dataset &X, const dataset &C, int z){
	double ret = 0;
	for(datapoint x : X){
		ret += x[0] * Pow(dist(x, C), z);
	}
	return ret;
}

double cost(const dataset &X, const datapoint &c, int z){
	dataset temp; temp.push_back(c);
	return cost(X, temp, z);
}

double rcost(dataset X, const dataset &C, double m, int z){
	vector<pair<double,double> > d;
	double sum = 0;
	for(datapoint x : X){
		double dst = dist(x,C);
		sum += x[0] * Pow(dst, z);
		d.push_back(make_pair(dst, x[0]));
	}
	sort(d.begin(),d.end()); reverse(d.begin(),d.end());
	for(int i = 0; i < d.size(); i++){
		double t = min(m, d[i].second);
		m -= t;
		sum -= t * Pow(d[i].first, z);
		if(m < 1e-7) break;
	} 
	return sum;
}

void Union(parti &_A, parti _B){
	if(_A.size() < _B.size()) swap(_A,_B);
	if(_B.empty()) return ;
	_A.reserve(_A.size() + _B.size()); // preallocate memory
	_A.insert(_A.end(), _B.begin(), _B.end());
}

void Union(dataset &A, dataset B){
	if(A.size() < B.size()) swap(A,B);
	if(B.empty()) return ;
	A.reserve(A.size() + B.size()); // preallocate memory
	A.insert(A.end(), B.begin(), B.end());
}
