#ifndef POLYNOMIAL_HPP
#define POLYNOMIAL_HPP

#include "../AttractorKernel.hpp"

unsigned int calculateNumberOfParameters(const unsigned int dimension, const unsigned int orde) {
	double n_coef = orde + 1;
	for(unsigned int i = 2; i <= dimension; i++) {
		n_coef = n_coef*(orde + i)/(i - 1);
	}

	const unsigned int output = (unsigned int) n_coef;
	return output;
}


class Polynomial : public AttractorKernel {
private:
	unsigned int orde;

	void recur(unsigned int curr_dimension, unsigned int prev_i, unsigned int n, unsigned int& m, double prev_product=1.0) {
		double product;
		for(unsigned int i = prev_i; i < dimension; i++) {

			product = prev_product * vectorOld[i];
			vectorNew[curr_dimension] += parameters[m] * product;
			m++;
			if(n < orde) {
				recur(curr_dimension, i, n+1, m, product);
			}
		}
	}

public:
	Polynomial():
		AttractorKernel(3, calculateNumberOfParameters(3, 2)), orde(2) {}

	Polynomial(const unsigned int dimension, const unsigned int orde):
		AttractorKernel(dimension, calculateNumberOfParameters(dimension, orde)), orde(orde) {}

	virtual std::string type() { return "polynomial"; };

	virtual void operator()() {
		std::swap(vectorNew, vectorOld);

		unsigned int m = 0;
		for(unsigned int i = 0; i < dimension; i++) {

			vectorNew[i] = parameters[m];
			m++;
			recur(i, 0, 1, m);
		}
	}
};

#endif // POLYNOMIAL_HPP