Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tutil.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include <iterator></iterator>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using TConsts::epsilon;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMathException::TMathException(string msg)
Toshihiro Shimizu 890ddd
	: m_msg(toWideString(msg))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! maximum order for a polynomial
Toshihiro Shimizu 890ddd
const int MAX_ORDER = 12;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! smallest relative error we want
Toshihiro Shimizu 890ddd
const double RELERROR = 1.0e-14;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! max power of 10 we wish to search to
Toshihiro Shimizu 890ddd
const int MAXPOW = 32;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!max number of iterations
Toshihiro Shimizu 890ddd
const int MAXIT = 800;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! a coefficient smaller than SMALL_ENOUGH is considered to be zero (0.0).
Toshihiro Shimizu 890ddd
const double SMALL_ENOUGH = 1.0e-12;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline int getEl(int i, int j, int n)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (j - 1) + (i - 1) * n;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! structure type for representing a polynomial
Toshihiro Shimizu 890ddd
typedef struct
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	int ord;
Toshihiro Shimizu 890ddd
	double coef[MAX_ORDER];
Toshihiro Shimizu 890ddd
} poly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  compute number of root in (min,max)
Toshihiro Shimizu 890ddd
double evalpoly(int ord, double *coef, double x);
Toshihiro Shimizu 890ddd
int numchanges(int np, poly *sseq, double a);
Toshihiro Shimizu 890ddd
int buildsturm(int ord, poly *sseq);
Toshihiro Shimizu 890ddd
int modrf(int ord, double *coef, double a, double b, double *val);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void convert(const vector<double> &v, poly &p)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert((int)v.size() <= MAX_ORDER);
Toshihiro Shimizu 890ddd
	if ((int)v.size() > MAX_ORDER)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p.ord = v.size() - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::copy(v.begin(), v.end(), p.coef);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void convert(const poly &p, vector<double> &v)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	v.resize(p.ord);
Toshihiro Shimizu 890ddd
	std::copy(p.coef, p.coef + p.ord, v.begin());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  * modp
Toshihiro Shimizu 890ddd
  *
Toshihiro Shimizu 890ddd
  *  calculates the modulus of u(x) / v(x) leaving it in r, it
Toshihiro Shimizu 890ddd
  *  returns 0 if r(x) is a constant.
Toshihiro Shimizu 890ddd
  *  note: this function assumes the leading coefficient of v 
Toshihiro Shimizu 890ddd
  *  is 1 or -1
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
int modp(poly *u, poly *v, poly *r)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int k, j;
Toshihiro Shimizu 890ddd
	double *nr, *end, *uc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nr = r->coef;
Toshihiro Shimizu 890ddd
	end = &u->coef[u->ord];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	uc = u->coef;
Toshihiro Shimizu 890ddd
	while (uc <= end)
Toshihiro Shimizu 890ddd
		*nr++ = *uc++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (v->coef[v->ord] < 0.0) {
Toshihiro Shimizu 890ddd
		for (k = u->ord - v->ord - 1; k >= 0; k -= 2)
Toshihiro Shimizu 890ddd
			r->coef[k] = -r->coef[k];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (k = u->ord - v->ord; k >= 0; k--)
Toshihiro Shimizu 890ddd
			for (j = v->ord + k - 1; j >= k; j--)
Toshihiro Shimizu 890ddd
				r->coef[j] = -r->coef[j] - r->coef[v->ord + k] * v->coef[j - k];
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (k = u->ord - v->ord; k >= 0; k--)
Toshihiro Shimizu 890ddd
			for (j = v->ord + k - 1; j >= k; j--)
Toshihiro Shimizu 890ddd
				r->coef[j] -= r->coef[v->ord + k] * v->coef[j - k];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	k = v->ord - 1;
Toshihiro Shimizu 890ddd
	while (k >= 0 && fabs(r->coef[k]) < SMALL_ENOUGH) {
Toshihiro Shimizu 890ddd
		r->coef[k] = 0.0;
Toshihiro Shimizu 890ddd
		k--;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	r->ord = (k < 0) ? 0 : k;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (r->ord);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  * buildsturm
Toshihiro Shimizu 890ddd
  *
Toshihiro Shimizu 890ddd
  *  build up a sturm sequence for a polynomial in sseq, returning
Toshihiro Shimizu 890ddd
  * the number of polynomials in the sequence
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
int buildsturm(int ord, poly *sseq)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	double f, *fp, *fc;
Toshihiro Shimizu 890ddd
	poly *sp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sseq[0].ord = ord;
Toshihiro Shimizu 890ddd
	sseq[1].ord = ord - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  calculate the derivative and normalise the leadingcoefficient.
Toshihiro Shimizu 890ddd
	f = fabs(sseq[0].coef[ord] * ord);
Toshihiro Shimizu 890ddd
	fp = sseq[1].coef;
Toshihiro Shimizu 890ddd
	fc = sseq[0].coef + 1;
Toshihiro Shimizu 890ddd
	for (i = 1; i <= ord; i++)
Toshihiro Shimizu 890ddd
		*fp++ = *fc++ * i / f;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// construct the rest of the Sturm sequence
Toshihiro Shimizu 890ddd
	for (sp = sseq + 2; modp(sp - 2, sp - 1, sp); sp++) {
Toshihiro Shimizu 890ddd
		//  reverse the sign and normalise
Toshihiro Shimizu 890ddd
		f = -fabs(sp->coef[sp->ord]);
Toshihiro Shimizu 890ddd
		for (fp = &sp->coef[sp->ord]; fp >= sp->coef; fp--)
Toshihiro Shimizu 890ddd
			*fp /= f;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sp->coef[0] = -sp->coef[0]; // reverse the sign
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (sp - sseq);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  return the number of distinct real roots of the polynomial
Toshihiro Shimizu 890ddd
  described in sseq
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
int numroots(int np, poly *sseq, int &atneg, int &atpos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int
Toshihiro Shimizu 890ddd
		atposinf = 0,
Toshihiro Shimizu 890ddd
		atneginf = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	poly *s;
Toshihiro Shimizu 890ddd
	double f, lf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// change at positive infinity
Toshihiro Shimizu 890ddd
	lf = sseq[0].coef[sseq[0].ord];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (s = sseq + 1; s <= sseq + np; ++s) {
Toshihiro Shimizu 890ddd
		f = s->coef[s->ord];
Toshihiro Shimizu 890ddd
		if (0.0 == lf || lf * f < 0.0)
Toshihiro Shimizu 890ddd
			++atposinf;
Toshihiro Shimizu 890ddd
		lf = f;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// change at negative infinity
Toshihiro Shimizu 890ddd
	if (sseq[0].ord & 1)
Toshihiro Shimizu 890ddd
		lf = -sseq[0].coef[sseq[0].ord];
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		lf = sseq[0].coef[sseq[0].ord];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (s = sseq + 1; s <= sseq + np; ++s) {
Toshihiro Shimizu 890ddd
		if (s->ord & 1)
Toshihiro Shimizu 890ddd
			f = -s->coef[s->ord];
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			f = s->coef[s->ord];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (0.0 == lf || lf * f < 0.0)
Toshihiro Shimizu 890ddd
			++atneginf;
Toshihiro Shimizu 890ddd
		lf = f;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	atneg = atneginf;
Toshihiro Shimizu 890ddd
	atpos = atposinf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return atneginf - atposinf;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  * numchanges
Toshihiro Shimizu 890ddd
  *
Toshihiro Shimizu 890ddd
  * return the number of sign changes in the Sturm sequence in
Toshihiro Shimizu 890ddd
  * sseq at the value a.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
int numchanges(int np, poly *sseq, double a)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int changes;
Toshihiro Shimizu 890ddd
	double f, lf;
Toshihiro Shimizu 890ddd
	poly *s;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	changes = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	lf = evalpoly(sseq[0].ord, sseq[0].coef, a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (s = sseq + 1; s <= sseq + np; s++) {
Toshihiro Shimizu 890ddd
		f = evalpoly(s->ord, s->coef, a);
Toshihiro Shimizu 890ddd
		if (lf == 0.0 || lf * f < 0)
Toshihiro Shimizu 890ddd
			changes++;
Toshihiro Shimizu 890ddd
		lf = f;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (changes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  * sbisect
Toshihiro Shimizu 890ddd
  *
Toshihiro Shimizu 890ddd
  * uses a bisection based on the sturm sequence for the polynomial
Toshihiro Shimizu 890ddd
  * described in sseq to isolate intervals in which roots occur,
Toshihiro Shimizu 890ddd
  * the roots are returned in the roots array in order of magnitude.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
void sbisect(int np,
Toshihiro Shimizu 890ddd
			 poly *sseq,
Toshihiro Shimizu 890ddd
			 double min,
Toshihiro Shimizu 890ddd
			 double max,
Toshihiro Shimizu 890ddd
			 int atmin,
Toshihiro Shimizu 890ddd
			 int atmax,
Toshihiro Shimizu 890ddd
			 double *roots)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double mid;
Toshihiro Shimizu 890ddd
	int n1 = 0, n2 = 0, its, atmid;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((atmin - atmax) == 1) {
Toshihiro Shimizu 890ddd
		//first try a less expensive technique.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (modrf(sseq->ord, sseq->coef, min, max, &roots[0]))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
        * if we get here we have to evaluate the root the hard
Toshihiro Shimizu 890ddd
        * way by using the Sturm sequence.
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
		for (its = 0; its < MAXIT; its++) {
Toshihiro Shimizu 890ddd
			mid = (min + max) / 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			atmid = numchanges(np, sseq, mid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (fabs(mid) > RELERROR) {
Toshihiro Shimizu 890ddd
				if (fabs((max - min) / mid) < RELERROR) {
Toshihiro Shimizu 890ddd
					roots[0] = mid;
Toshihiro Shimizu 890ddd
					return;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else if (fabs(max - min) < RELERROR) {
Toshihiro Shimizu 890ddd
				roots[0] = mid;
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if ((atmin - atmid) == 0)
Toshihiro Shimizu 890ddd
				min = mid;
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				max = mid;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (its == MAXIT) {
Toshihiro Shimizu 890ddd
			/*
Toshihiro Shimizu 890ddd
      fprintf(stderr, "sbisect: overflow min %f max %f\
Toshihiro Shimizu 890ddd
      diff %e nroot %d n1 %d n2 %d\n",
Toshihiro Shimizu 890ddd
      min, max, max - min, nroot, n1, n2);
Toshihiro Shimizu 890ddd
        */
Toshihiro Shimizu 890ddd
			roots[0] = mid;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
    * more than one root in the interval, we have to bisect...
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
	for (its = 0; its < MAXIT; its++) {
Toshihiro Shimizu 890ddd
		mid = (min + max) / 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		atmid = numchanges(np, sseq, mid);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		n1 = atmin - atmid;
Toshihiro Shimizu 890ddd
		n2 = atmid - atmax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (n1 != 0 && n2 != 0) {
Toshihiro Shimizu 890ddd
			sbisect(np, sseq, min, mid, atmin, atmid, roots);
Toshihiro Shimizu 890ddd
			sbisect(np, sseq, mid, max, atmid, atmax, &roots[n1]);
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (n1 == 0)
Toshihiro Shimizu 890ddd
			min = mid;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			max = mid;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (its == MAXIT) {
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
    fprintf(stderr, "sbisect: roots too close together\n");
Toshihiro Shimizu 890ddd
    fprintf(stderr, "sbisect: overflow min %f max %f diff %e\
Toshihiro Shimizu 890ddd
    nroot %d n1 %d n2 %d\n",
Toshihiro Shimizu 890ddd
    min, max, max - min, nroot, n1, n2);
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
		for (n1 = atmax; n1 < atmin; n1++)
Toshihiro Shimizu 890ddd
			roots[n1 - atmax] = mid;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  * evalpoly
Toshihiro Shimizu 890ddd
  *
Toshihiro Shimizu 890ddd
  * evaluate polynomial defined in coef returning its value.
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
double evalpoly(int ord, double *coef, double x)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double *fp, f;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fp = &coef[ord];
Toshihiro Shimizu 890ddd
	f = *fp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (fp--; fp >= coef; fp--)
Toshihiro Shimizu 890ddd
		f = x * f + *fp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
    * modrf
Toshihiro Shimizu 890ddd
    *
Toshihiro Shimizu 890ddd
    * uses the modified regula-falsi method to evaluate the root
Toshihiro Shimizu 890ddd
    * in interval [a,b] of the polynomial described in coef. The
Toshihiro Shimizu 890ddd
    * root is returned is returned in *val. The routine returns zero
Toshihiro Shimizu 890ddd
    * if it can't converge.
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
int modrf(int ord, double *coef, double a, double b, double *val)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int its;
Toshihiro Shimizu 890ddd
	double fa, fb, x, fx, lfx;
Toshihiro Shimizu 890ddd
	double *fp, *scoef, *ecoef;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	scoef = coef;
Toshihiro Shimizu 890ddd
	ecoef = &coef[ord];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fb = fa = *ecoef;
Toshihiro Shimizu 890ddd
	for (fp = ecoef - 1; fp >= scoef; fp--) {
Toshihiro Shimizu 890ddd
		fa = a * fa + *fp;
Toshihiro Shimizu 890ddd
		fb = b * fb + *fp;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  if there is no sign difference the method won't work
Toshihiro Shimizu 890ddd
	if (fa * fb > 0.0)
Toshihiro Shimizu 890ddd
		return (0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fabs(fa) < RELERROR) {
Toshihiro Shimizu 890ddd
		*val = a;
Toshihiro Shimizu 890ddd
		return (1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fabs(fb) < RELERROR) {
Toshihiro Shimizu 890ddd
		*val = b;
Toshihiro Shimizu 890ddd
		return (1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	lfx = fa;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (its = 0; its < MAXIT; its++) {
Toshihiro Shimizu 890ddd
		x = (fb * a - fa * b) / (fb - fa);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fx = *ecoef;
Toshihiro Shimizu 890ddd
		for (fp = ecoef - 1; fp >= scoef; fp--)
Toshihiro Shimizu 890ddd
			fx = x * fx + *fp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fabs(x) > RELERROR) {
Toshihiro Shimizu 890ddd
			if (fabs(fx / x) < RELERROR) {
Toshihiro Shimizu 890ddd
				*val = x;
Toshihiro Shimizu 890ddd
				return (1);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (fabs(fx) < RELERROR) {
Toshihiro Shimizu 890ddd
			*val = x;
Toshihiro Shimizu 890ddd
			return (1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((fa * fx) < 0) {
Toshihiro Shimizu 890ddd
			b = x;
Toshihiro Shimizu 890ddd
			fb = fx;
Toshihiro Shimizu 890ddd
			if ((lfx * fx) > 0)
Toshihiro Shimizu 890ddd
				fa /= 2;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			a = x;
Toshihiro Shimizu 890ddd
			fa = fx;
Toshihiro Shimizu 890ddd
			if ((lfx * fx) > 0)
Toshihiro Shimizu 890ddd
				fb /= 2;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		lfx = fx;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// fprintf(stderr, "modrf overflow %f %f %f\n", a, b, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
    a x^2 + b x + c
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
      Remark: 
Toshihiro Shimizu 890ddd
      poly[0] = c 
Toshihiro Shimizu 890ddd
      poly[1] = b
Toshihiro Shimizu 890ddd
      poly[2] = a 
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
int rootForQuadraticEquation(const vector<double> &v,</double>
Toshihiro Shimizu 890ddd
							 vector<double> &sol)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double q, delta;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
      if( isAlmostZero(v[2]))
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
      if ( isAlmostZero(v[1]) )
Toshihiro Shimizu 890ddd
      return -1;
Toshihiro Shimizu 890ddd
      
Toshihiro Shimizu 890ddd
        sol.push_back(-v[0]/v[1]);
Toshihiro Shimizu 890ddd
        return 1;
Toshihiro Shimizu 890ddd
        }
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(v[1])) {
Toshihiro Shimizu 890ddd
		q = -v[0] / v[2];
Toshihiro Shimizu 890ddd
		if (q < 0)
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
		else if (isAlmostZero(q)) {
Toshihiro Shimizu 890ddd
			sol.push_back(0);
Toshihiro Shimizu 890ddd
			return 1;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		q = sqrt(q);
Toshihiro Shimizu 890ddd
		sol.push_back(-q);
Toshihiro Shimizu 890ddd
		sol.push_back(q);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return 2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delta = sq(v[1]) - 4.0 * v[0] * v[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (delta < 0.0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(v[2] != 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(delta)) {
Toshihiro Shimizu 890ddd
		sol.push_back(-v[1] / (v[2] * 2.0));
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	q = -0.5 * (v[1] + tsign(v[1]) * sqrt(delta));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(q != 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sol.push_back(v[0] / q);
Toshihiro Shimizu 890ddd
	sol.push_back(q / v[2]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return 2;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
    a x^3+b x^2 + c x + d
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
      Remark: 
Toshihiro Shimizu 890ddd
      poly[0] = d 
Toshihiro Shimizu 890ddd
      poly[1] = c
Toshihiro Shimizu 890ddd
      poly[2] = b 
Toshihiro Shimizu 890ddd
      poly[3] = a 
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
int rootForCubicEquation(const vector<double> &p,</double>
Toshihiro Shimizu 890ddd
						 vector<double> &sol)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
    if( isAlmostZero(p[3]) )
Toshihiro Shimizu 890ddd
    return rootForQuadraticEquation(p,sol);
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(p[0])) {
Toshihiro Shimizu 890ddd
		int numberOfSol;
Toshihiro Shimizu 890ddd
		vector<double> redPol(3);</double>
Toshihiro Shimizu 890ddd
		redPol[0] = p[1];
Toshihiro Shimizu 890ddd
		redPol[1] = p[2];
Toshihiro Shimizu 890ddd
		redPol[2] = p[3];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		numberOfSol = rootForQuadraticEquation(redPol, sol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int i = 0; i < numberOfSol; ++i)
Toshihiro Shimizu 890ddd
			if (0.0 == sol[i])
Toshihiro Shimizu 890ddd
				return numberOfSol;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// altrimenti devo contare la soluzione nulla
Toshihiro Shimizu 890ddd
		++numberOfSol;
Toshihiro Shimizu 890ddd
		sol.push_back(0);
Toshihiro Shimizu 890ddd
		return numberOfSol;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		inv_v3 = 1.0 / p[3],
Toshihiro Shimizu 890ddd
		a = p[2] * inv_v3,
Toshihiro Shimizu 890ddd
		b = p[1] * inv_v3,
Toshihiro Shimizu 890ddd
		c = p[0] * inv_v3;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static const double inv_3 = 1.0 / 3.0;
Toshihiro Shimizu 890ddd
	static const double inv_9 = 1.0 / 9.0;
Toshihiro Shimizu 890ddd
	static const double inv_54 = 1.0 / 54.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		Q = (sq(a) - 3.0 * b) * inv_9,
Toshihiro Shimizu 890ddd
		R = (2.0 * sq(a) * a - 9.0 * a * b + 27.0 * c) * inv_54;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		R_2 = sq(R),
Toshihiro Shimizu 890ddd
		Q_3 = sq(Q) * Q;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (R_2 < Q_3) {
Toshihiro Shimizu 890ddd
		double Q_sqrt = sqrt(Q);
Toshihiro Shimizu 890ddd
		double theta = acos(R / (Q * Q_sqrt));
Toshihiro Shimizu 890ddd
		sol.push_back(-2 * Q_sqrt * cos(theta * inv_3) - a * inv_3);
Toshihiro Shimizu 890ddd
		sol.push_back(-2 * Q_sqrt * cos((theta - TConsts::pi * 2.0) * inv_3) - a * inv_3);
Toshihiro Shimizu 890ddd
		sol.push_back(-2 * Q_sqrt * cos((theta + TConsts::pi * 2.0) * inv_3) - a * inv_3);
Toshihiro Shimizu 890ddd
		std::sort(sol.begin(), sol.end());
Toshihiro Shimizu 890ddd
		return 3;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double A = -tsign(R) * pow((fabs(R) + sqrt(R_2 - Q_3)), inv_3);
Toshihiro Shimizu 890ddd
	double B = A != 0 ? Q / A : 0;
Toshihiro Shimizu 890ddd
	sol.push_back((A + B) - a * inv_3);
Toshihiro Shimizu 890ddd
	return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int rootForGreaterThanThreeEquation(const vector<double> &p,</double>
Toshihiro Shimizu 890ddd
									vector<double> &sol)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	poly sseq[MAX_ORDER];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	convert(p, sseq[0]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int np = buildsturm(p.size() - 1, sseq);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int atmin, atmax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int nroot = numroots(np, sseq, atmin, atmax);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nroot == 0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double minVal = -1.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT i = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int nchanges = numchanges(np, sseq, minVal);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; nchanges != atmin && i != (UINT)MAXPOW; ++i) {
Toshihiro Shimizu 890ddd
		minVal *= 10.0;
Toshihiro Shimizu 890ddd
		nchanges = numchanges(np, sseq, minVal);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nchanges != atmin) {
Toshihiro Shimizu 890ddd
		atmin = nchanges;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double maxVal = 1.0;
Toshihiro Shimizu 890ddd
	nchanges = numchanges(np, sseq, maxVal);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; nchanges != atmax && i != (UINT)MAXPOW; ++i) {
Toshihiro Shimizu 890ddd
		maxVal *= 10.0;
Toshihiro Shimizu 890ddd
		nchanges = numchanges(np, sseq, maxVal);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nchanges != atmax) {
Toshihiro Shimizu 890ddd
		atmax = nchanges;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nroot = atmin - atmax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(nroot > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	poly outPoly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	outPoly.ord = nroot;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sbisect(np, sseq, minVal, maxVal, atmin, atmax, outPoly.coef);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	convert(outPoly, sol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return nroot < 0 ? -1 : nroot;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // end of unnamed namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tLUDecomposition(double *a, int n, int *indx, double &d)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, imax, j, k;
Toshihiro Shimizu 890ddd
	double big, dum, sum, temp;
Toshihiro Shimizu 890ddd
	std::vector<double> vv(n);</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	d = 1.0;
Toshihiro Shimizu 890ddd
	for (i = 1; i <= n; i++) {
Toshihiro Shimizu 890ddd
		big = 0.0;
Toshihiro Shimizu 890ddd
		for (j = 1; j <= n; j++)
Toshihiro Shimizu 890ddd
			if ((temp = fabs(a[getEl(i, j, n)])) > big)
Toshihiro Shimizu 890ddd
				big = temp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (big == 0.0)
Toshihiro Shimizu 890ddd
			throw TMathException("Singular matrix in routine tLUDecomposition\n");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vv[i - 1] = 1.0 / big;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = 1; j <= n; j++) {
Toshihiro Shimizu 890ddd
		for (i = 1; i < j; i++) {
Toshihiro Shimizu 890ddd
			sum = a[getEl(i, j, n)];
Toshihiro Shimizu 890ddd
			for (k = 1; k < i; k++)
Toshihiro Shimizu 890ddd
				sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)];
Toshihiro Shimizu 890ddd
			a[getEl(i, j, n)] = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		big = 0.0;
Toshihiro Shimizu 890ddd
		for (i = j; i <= n; i++) {
Toshihiro Shimizu 890ddd
			sum = a[getEl(i, j, n)];
Toshihiro Shimizu 890ddd
			for (k = 1; k < j; k++)
Toshihiro Shimizu 890ddd
				sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)];
Toshihiro Shimizu 890ddd
			a[getEl(i, j, n)] = sum;
Toshihiro Shimizu 890ddd
			if ((dum = vv[i - 1] * fabs(sum)) >= big) {
Toshihiro Shimizu 890ddd
				big = dum;
Toshihiro Shimizu 890ddd
				imax = i;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (j != imax) {
Toshihiro Shimizu 890ddd
			for (k = 1; k <= n; k++) {
Toshihiro Shimizu 890ddd
				dum = a[getEl(imax, k, n)];
Toshihiro Shimizu 890ddd
				a[getEl(imax, k, n)] = a[getEl(j, k, n)];
Toshihiro Shimizu 890ddd
				a[getEl(j, k, n)] = dum;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			d = -(d);
Toshihiro Shimizu 890ddd
			vv[imax - 1] = vv[j - 1];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		indx[j - 1] = imax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (a[getEl(j, j, n)] == 0.0)
Toshihiro Shimizu 890ddd
			a[getEl(j, j, n)] = TConsts::epsilon;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (j != n) {
Toshihiro Shimizu 890ddd
			dum = 1.0 / (a[getEl(j, j, n)]);
Toshihiro Shimizu 890ddd
			for (i = j + 1; i <= n; i++)
Toshihiro Shimizu 890ddd
				a[getEl(i, j, n)] *= dum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tbackSubstitution(double *a, int n, int *indx, double *b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, ii = 0, ip, j;
Toshihiro Shimizu 890ddd
	double sum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 1; i <= n; i++) {
Toshihiro Shimizu 890ddd
		ip = indx[i - 1];
Toshihiro Shimizu 890ddd
		sum = b[ip - 1];
Toshihiro Shimizu 890ddd
		b[ip - 1] = b[i - 1];
Toshihiro Shimizu 890ddd
		if (ii)
Toshihiro Shimizu 890ddd
			for (j = ii; j <= i - 1; j++)
Toshihiro Shimizu 890ddd
				sum -= a[getEl(i, j, n)] * b[j - 1];
Toshihiro Shimizu 890ddd
		else if (sum)
Toshihiro Shimizu 890ddd
			ii = i;
Toshihiro Shimizu 890ddd
		b[i - 1] = sum;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = n; i >= 1; i--) {
Toshihiro Shimizu 890ddd
		sum = b[i - 1];
Toshihiro Shimizu 890ddd
		for (j = i + 1; j <= n; j++)
Toshihiro Shimizu 890ddd
			sum -= a[getEl(i, j, n)] * b[j - 1];
Toshihiro Shimizu 890ddd
		b[i - 1] = sum / a[getEl(i, i, n)];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double tdet(double *LUa, int n, double d)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int i = 1; i <= n; ++i)
Toshihiro Shimizu 890ddd
		d *= LUa[getEl(i, i, n)];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double tdet(double *a, int n)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double d;
Toshihiro Shimizu 890ddd
	vector<int> indx(n);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tLUDecomposition(a, n, &indx[0], d);
Toshihiro Shimizu 890ddd
	for (int i = 1; i <= n; ++i)
Toshihiro Shimizu 890ddd
		d *= a[getEl(i, i, n)];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tsolveSistem(double *a, int n, double *res)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double d;
Toshihiro Shimizu 890ddd
	vector<int> indx(n);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tLUDecomposition(a, n, &indx[0], d);
Toshihiro Shimizu 890ddd
	assert(tdet(a, n, d) != 0);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  if( isAlmostZero(tdet(a, n, d)) )
Toshihiro Shimizu 890ddd
    throw TMathException("Singular matrix in routine tLUDecomposition\n");    
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	tbackSubstitution(a, n, &indx[0], res);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int rootFinding(const vector<double> &in_poly,</double>
Toshihiro Shimizu 890ddd
				vector<double> &sol)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// per ora risolvo solo i polinomi di grado al piu' pari a 3
Toshihiro Shimizu 890ddd
	assert((int)in_poly.size() <= MAX_ORDER);
Toshihiro Shimizu 890ddd
	if (in_poly.empty() || (int)in_poly.size() > MAX_ORDER)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<double> p;</double>
Toshihiro Shimizu 890ddd
	std::copy(in_poly.begin(), in_poly.end(), std::back_inserter(p));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// eat zero in poly
Toshihiro Shimizu 890ddd
	while (!p.empty() && isAlmostZero(p.back()))
Toshihiro Shimizu 890ddd
		p.pop_back();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sol.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!p.empty() && p.front() == 0) {
Toshihiro Shimizu 890ddd
		sol.push_back(0.0);
Toshihiro Shimizu 890ddd
		p.erase(p.begin()); //se i coefficienti bassi sono zero, ci sono soluzioni pari a 0.0. le metto,
Toshihiro Shimizu 890ddd
	}						//e abbasso il grado del polinomio(piu' veloce)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (p.size()) {
Toshihiro Shimizu 890ddd
	case 0:
Toshihiro Shimizu 890ddd
		if (sol.empty())
Toshihiro Shimizu 890ddd
			return INFINITE_SOLUTIONS;
Toshihiro Shimizu 890ddd
		CASE 1 : //no solutions
Toshihiro Shimizu 890ddd
				 CASE 2 : sol.push_back(-p[0] / p[1]);
Toshihiro Shimizu 890ddd
		CASE 3 : rootForQuadraticEquation(p, sol);
Toshihiro Shimizu 890ddd
		CASE 4 : rootForCubicEquation(p, sol);
Toshihiro Shimizu 890ddd
	DEFAULT:
Toshihiro Shimizu 890ddd
		rootForGreaterThanThreeEquation(p, sol);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return sol.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int numberOfRootsInInterval(int order, const double *polyH, double min, double max)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	poly sseq[MAX_ORDER];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int
Toshihiro Shimizu 890ddd
		i,
Toshihiro Shimizu 890ddd
		nchanges_0,
Toshihiro Shimizu 890ddd
		nchanges_1,
Toshihiro Shimizu 890ddd
		np;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (order > MAX_ORDER)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (polyH[order] == 0.0 && order > 0)
Toshihiro Shimizu 890ddd
		--order;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// init a sturm's sequence with our polynomious
Toshihiro Shimizu 890ddd
	for (i = order; i >= 0; --i)
Toshihiro Shimizu 890ddd
		sseq[0].coef[i] = polyH[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  build the Sturm sequence
Toshihiro Shimizu 890ddd
	np = buildsturm(order, sseq);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//compute number of variation on 0.0
Toshihiro Shimizu 890ddd
	nchanges_0 = numchanges(np, sseq, min);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nchanges_1 = numchanges(np, sseq, max);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (nchanges_0 - nchanges_1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double quadraticRoot(double a, double b, double c)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double bb, q;
Toshihiro Shimizu 890ddd
	// caso lineare
Toshihiro Shimizu 890ddd
	if (fabs(a) < epsilon) {
Toshihiro Shimizu 890ddd
		if (fabs(b) >= epsilon)
Toshihiro Shimizu 890ddd
			return -c / b;
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bb = b * b;
Toshihiro Shimizu 890ddd
	q = bb - 4.0 * a * c;
Toshihiro Shimizu 890ddd
	if (q < 0.0)
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	q = sqrt(q);
Toshihiro Shimizu 890ddd
	if (b < 0.0)
Toshihiro Shimizu 890ddd
		q = -q;
Toshihiro Shimizu 890ddd
	q = -0.5 * (b + q);
Toshihiro Shimizu 890ddd
	double root1 = -1;
Toshihiro Shimizu 890ddd
	double root2 = -1;
Toshihiro Shimizu 890ddd
	if (fabs(q) >= epsilon)
Toshihiro Shimizu 890ddd
		root1 = c / q;
Toshihiro Shimizu 890ddd
	if (fabs(a) >= epsilon)
Toshihiro Shimizu 890ddd
		root2 = q / a;
Toshihiro Shimizu 890ddd
	if (0.0 - epsilon <= root1 && root1 <= 1.0 + epsilon)
Toshihiro Shimizu 890ddd
		return root1;
Toshihiro Shimizu 890ddd
	if (0.0 - epsilon <= root2 && root2 <= 1.0 + epsilon)
Toshihiro Shimizu 890ddd
		return root2;
Toshihiro Shimizu 890ddd
	return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double cubicRoot(double a, double b, double c, double d)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double A, Q, R, QQQ, RR;
Toshihiro Shimizu 890ddd
	double theta;
Toshihiro Shimizu 890ddd
	/* Test for a quadratic or linear degeneracy			*/
Toshihiro Shimizu 890ddd
	if (fabs(a) < epsilon)
Toshihiro Shimizu 890ddd
		return quadraticRoot(b, c, d);
Toshihiro Shimizu 890ddd
	/* Normalize							*/
Toshihiro Shimizu 890ddd
	b /= a;
Toshihiro Shimizu 890ddd
	c /= a;
Toshihiro Shimizu 890ddd
	d /= a;
Toshihiro Shimizu 890ddd
	a = 1.0;
Toshihiro Shimizu 890ddd
	/* Compute discriminants						*/
Toshihiro Shimizu 890ddd
	Q = (b * b - 3.0 * c) / 9.0;
Toshihiro Shimizu 890ddd
	QQQ = Q * Q * Q;
Toshihiro Shimizu 890ddd
	R = (2.0 * b * b * b - 9.0 * b * c + 27.0 * d) / 54.0;
Toshihiro Shimizu 890ddd
	RR = R * R;
Toshihiro Shimizu 890ddd
	/* Three real roots							*/
Toshihiro Shimizu 890ddd
	if (RR < QQQ) {
Toshihiro Shimizu 890ddd
		theta = acos(R / sqrt(QQQ));
Toshihiro Shimizu 890ddd
		double root[3];
Toshihiro Shimizu 890ddd
		root[0] = root[1] = root[2] = -2.0 * sqrt(Q);
Toshihiro Shimizu 890ddd
		root[0] *= cos(theta / 3.0);
Toshihiro Shimizu 890ddd
		root[1] *= cos((theta + 2 * TConsts::pi) / 3.0);
Toshihiro Shimizu 890ddd
		root[2] *= cos((theta - 2 * TConsts::pi) / 3.0);
Toshihiro Shimizu 890ddd
		root[0] -= b / 3.0;
Toshihiro Shimizu 890ddd
		root[1] -= b / 3.0;
Toshihiro Shimizu 890ddd
		root[2] -= b / 3.0;
Toshihiro Shimizu 890ddd
		if (0.0 - epsilon < root[0] && root[0] < 1.0 + epsilon)
Toshihiro Shimizu 890ddd
			return root[0];
Toshihiro Shimizu 890ddd
		if (0.0 - epsilon < root[1] && root[1] < 1.0 + epsilon)
Toshihiro Shimizu 890ddd
			return root[1];
Toshihiro Shimizu 890ddd
		if (0.0 - epsilon < root[2] && root[2] < 1.0 + epsilon)
Toshihiro Shimizu 890ddd
			return root[2];
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* One real root							*/
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		double root = 0;
Toshihiro Shimizu 890ddd
		A = -pow(fabs(R) + sqrt(RR - QQQ), 1.0 / 3.0);
Toshihiro Shimizu 890ddd
		if (A != 0.0) {
Toshihiro Shimizu 890ddd
			if (R < 0.0)
Toshihiro Shimizu 890ddd
				A = -A;
Toshihiro Shimizu 890ddd
			root = A + Q / A;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		root -= b / 3.0;
Toshihiro Shimizu 890ddd
		if (0.0 - epsilon < root && root < 1.0 + epsilon)
Toshihiro Shimizu 890ddd
			return root;
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------