35 QDPIO::cout << __func__ <<
": approximation bounds are ["
36 << (double)
apstrt <<
" , " << (
double)
apend <<
"]"<< std::endl;
44 if (
sizeof(Real)==
sizeof(double)) {
46 }
else if (
sizeof(Real)==
sizeof(float)) {
59 param.resize(num_degree+den_degree+1);
60 roots.resize(num_degree);
61 poles.resize(den_degree);
62 xx.resize(num_degree+den_degree+3);
63 mm.resize(num_degree+den_degree+2);
90 unsigned long pnum,
unsigned long pden)
95 if (num_degree !=
n || den_degree !=
d)
allocate(num_degree,den_degree);
97 step.resize(num_degree+den_degree+2);
116 QDPIO::cout << __func__ <<
": Iteration " <<
iter-1
117 <<
" spread " <<
spread <<
" delta " <<
delta << std::endl;
123 QDPIO::cerr << __func__ <<
":Delta too small, try increasing precision" << std::endl;;
132 Real error = (Real)
getErr(
mm[0],sign);
133 QDPIO::cout << __func__ <<
" Converged at " <<
iter <<
" iterations, error = " << error << std::endl;
138 QDPIO::cerr << __func__ <<
": Root finding failed" << std::endl;
155 QDPIO::cerr << __func__ <<
": Cannot handle case: Numerator degree neq Denominator degree" << std::endl;
161 QDPIO::cerr << __func__ <<
": Approximation not yet generated" << std::endl;
167 coeff.
pole.resize(
d);
169 multi1d<bigfloat>
r(
n);
170 multi1d<bigfloat>
p(
d);
180 for (
int i=0;
i<
n;
i++) coeff.
res[
i] = (
double)
r[
i];
181 for (
int i=0;
i<
d;
i++) coeff.
pole[
i] = (
double)
p[
i];
195 QDPIO::cerr << __func__ <<
": Approximation not yet generated" << std::endl;
201 coeff.
pole.resize(
d);
203 multi1d<bigfloat>
r(
d);
204 multi1d<bigfloat>
p(
n);
207 for (
int i=0;
i<
n;
i++) {
217 for (
int i=0;
i<
n;
i++) {
218 coeff.
res[
i] = (double)
r[
i];
240 for (
long i = 1;
i < ncheb;
i++) {
241 r = 0.5 * (1 - cos((
M_PI *
i)/(
double)
a));
243 r = (exp((
double)
r)-1.0)/(exp(1.0)-1.0);
249 for (
long i = 0;
i <= ncheb;
i++) {
250 r = 0.5 * (1 - cos(
M_PI * (2*
i+1)/(
double)
a));
252 r = (exp((
double)
r)-1.0)/(exp(1.0)-1.0);
264 if (
step.size() == 0)
281 if (
step.size() == 0)
285 int i,
j, meq, emsign, ensign, steps;
288 multi1d<bigfloat> yy(meq);
296 for (
i = 0;
i < meq;
i++) {
299 if (
i == meq-1) xx1 =
apend;
304 if (xn < xx0 || xn >= xx1) {
320 if (++steps > 10)
break;
325 if (
a == xm || a <= xx0 || a >= xx1)
break;
333 if (eclose > ym) eclose = ym;
334 if (farther < ym) farther = ym;
339 q = (farther - eclose);
340 if (eclose != 0.0)
q /= eclose;
344 for (
i = 0;
i <
neq;
i++) {
354 for (
i = 0;
i <
neq;
i++) {
356 if (xm <=
apstrt)
continue;
357 if (xm >=
apend)
continue;
375 multi1d<bigfloat> AA(
neq*
neq);
376 multi1d<bigfloat> BB(
neq);
378 for (
i = 0;
i <
neq;
i++) {
385 for (
j = 0;
j <=
n;
j++) {
391 for (
j = 0;
j <
d;
j++) {
401 QDPIO::cerr << __func__ <<
": simq failed" << std::endl;
468 int RemezGMP::simq(multi1d<bigfloat>&
A, multi1d<bigfloat>& B, multi1d<bigfloat>& X,
int n)
472 if (
A.size() == 0 || B.size() == 0)
475 int i,
j, ij, ip, ipj, ipk, ipn;
477 int k, kp, kp1, kpk, kpn;
482 multi1d<int> IPS(
neq);
488 for (
i = 0;
i <
n;
i++) {
491 for(
j = 0;
j <
n;
j++) {
493 if(rownrm <
q) rownrm =
q;
498 QDPIO::cout <<
"simq rownrm=0\n" << std::endl;
504 for (
k = 0;
k < nm1;
k++) {
508 for (
i =
k;
i <
n;
i++) {
511 size = abs_bf(
A[ipk]) * X[ip];
520 QDPIO::cout <<
"simq big=0" << std::endl;
525 IPS[
k] = IPS[idxpiv];
532 for (
i = kp1;
i <
n;
i++) {
535 em = -
A[ipk] / pivot;
540 for (
j = kp1;
j <
n;
j++) {
542 A[ipj] =
A[ipj] + em * *aa++;
546 kpn =
n * IPS[
n-1] +
n - 1;
549 QDPIO::cout <<
"simq A[kpn]=0" << std::endl;
556 for (
i = 1;
i <
n;
i++) {
560 for (
j = 0;
j <
i;
j++) {
561 sum +=
A[ipj] * X[
j];
567 ipn =
n * IPS[
n-1] +
n - 1;
568 X[
n-1] = X[
n-1] /
A[ipn];
570 for (iback = 1; iback <
n; iback++) {
577 for (
j=
i + 1;
j <
n;
j++)
579 X[
i] = (X[
i] -
sum) /
A[nip+
i];
597 multi1d<bigfloat> poly(
neq+1);
601 for (
i=
n-1;
i>=0;
i--) {
605 QDPIO::cerr << __func__ <<
": Failure to converge on root" << std::endl;
608 poly[0] = -poly[0]/
roots[
i];
609 for (
j=1;
j<=
i;
j++) poly[
j] = (poly[
j-1] - poly[
j])/
roots[
i];
615 for (
i=
d-1;
i>=0;
i--) {
618 QDPIO::cerr << __func__ <<
": Failure to converge on root" << std::endl;
621 poly[0] = -poly[0]/
poles[
i];
622 for (
j=1;
j<=
i;
j++) poly[
j] = (poly[
j-1] - poly[
j])/
poles[
i];
626 QDPIO::cout << __func__ <<
": Normalisation constant is " << (double)
norm << std::endl;
628 QDPIO::cout <<
"root[" <<
i <<
"] = " << (
double)
roots[
i] << std::endl;
630 QDPIO::cout <<
"pole[" <<
i <<
"] = " << (
double)
poles[
i] << std::endl;
641 for (
int i=size-1;
i>=0;
i--) f = f*
x + poly[
i];
649 for (
int i=size-1;
i>0;
i--)
670 if ((x1-rtn)*(rtn-x2) < (
bigfloat)0.0)
671 QDPIO::cerr << __func__ <<
": Jumped out of brackets in rtnewt" << std::endl;
672 if (abs_bf(dx) < xacc)
return rtn;
674 QDPIO::cerr << __func__ <<
": Maximum number of iterations exceeded in rtnewt" << std::endl;
689 if (res.size() == 0 ||
poles.size() == 0)
694 multi1d<bigfloat> numerator(
n);
695 multi1d<bigfloat> denominator(
d);
698 for (
i=1;
i<
n;
i++) {
705 for (
j=0;
j<
n;
j++) {
706 for (
i=
n-1;
i>=0;
i--) {
707 numerator[
i] *= -res[
j];
710 numerator[
i] += numerator[
i-1];
711 denominator[
i] += denominator[
i-1];
718 for (
i=0;
i<
n;
i++) numerator[
i] -= denominator[
i];
722 for (
i=0;
i<
n;
i++) {
724 for (
j=
n-1;
j>=0;
j--) {
727 for (
j=
n-1;
j>=0;
j--) {
741 for (
i=
j+1;
i<
n;
i++) {
752 QDPIO::cout << __func__ <<
": Residue = " << (double)res[
j] <<
" Pole = " << (
double)
poles[
j] << std::endl;
764 if ((coeff.
res.size() != coeff.
pole.size()) || coeff.
res.size() == 0)
766 QDPIO::cerr << __func__ <<
": invalid res and pole" << std::endl;
771 for (
int i=0;
i < coeff.
res.size(); ++
i)
bigfloat polyDiff(const bigfloat &x, const multi1d< bigfloat > &poly, long size)
Evaluate the differential of the polynomial.
bigfloat getErr(const bigfloat &x, int &sign)
Compute size and sign of the approximation error at x.
bool alloc
Flag to determine whether the arrays have been allocated.
int simq(multi1d< bigfloat > &A, multi1d< bigfloat > &B, multi1d< bigfloat > &X, int n)
Solve the system AX=B.
bigfloat func(const bigfloat &x)
Calculate function required for the approximation.
void allocate(int num_degree, int den_degree)
Free memory and reallocate as necessary.
int neq
The number of equations we must solve at each iteration (n+d+1)
bigfloat approx(const bigfloat &x)
void initialGuess()
Initial values of maximal and minmal errors.
bigfloat rtnewt(const multi1d< bigfloat > &poly, long i, const bigfloat &x1, const bigfloat &x2, const bigfloat &xacc)
Newton's method to calculate roots.
RemezCoeff_t getIPFE()
Return the partial fraction expansion of the approximation x^(-pnum/pden)
Real evalPFE(const Real &x, const RemezCoeff_t &coeff)
Given a partial fraction expansion, evaluate it at x.
multi1d< bigfloat > roots
int n
The numerator and denominator degree (n=d)
void stpini(multi1d< bigfloat > &step)
Initialise step sizes.
multi1d< bigfloat > poles
void pfe(multi1d< bigfloat > &res, multi1d< bigfloat > &poles, const bigfloat &norm)
bigfloat polyEval(const bigfloat &x, const multi1d< bigfloat > &poly, long size)
Evaluate the polynomial.
multi1d< bigfloat > param
RemezGMP()
Default constructor.
RemezCoeff_t getPFE()
Return the partial fraction expansion of the approximation x^(pnum/pden)
unsigned long power_num
the numerator and denominator of the power we are approximating
bigfloat apstrt
The bounds of the approximation.
void search(multi1d< bigfloat > &step)
Search for error maxima and minima.
void setBounds(const Real &lower, const Real &upper)
Reset the bounds of the approximation.
long prec
The precision of the GNU MP library.
int root()
Calculate the roots of the approximation.
Real generateApprox(int num_degree, int den_degree, unsigned long power_num, unsigned long power_den)
Generate the rational approximation x^(pnum/pden)
void equations()
Solve the equations.
static void setDefaultPrecision(unsigned long dprec)
Asqtad Staggered-Dirac operator.
QDP_error_exit("too many BiCG iterations", n_count, rsd_sq, cp, c, re_rvr, im_rvr, re_a, im_a, re_b, im_b)
Remez algorithm for finding nth roots.
Convenient structure to package Remez coeffs.