2 #define VERSION Source Time-stamp: <19-OCT-2004 09:33:22.00 adk@MISSCONTRARY>
22 #define MAX(a,b) ((a) > (b) ? (a) : (b))
23 #define MIN(a,b) ((a) < (b) ? (a) : (b))
25 #ifndef INTERNAL_PRECISION
26 #define INTERNAL_PRECISION long double
30 #define ZOLOTAREV_INTERNAL
32 #define ZOLOTAREV_DATA izd
34 #define ZPRECISION INTERNAL_PRECISION
36 #undef ZOLOTAREV_INTERNAL
41 #define M_PI ((INTERNAL_PRECISION) 3.141592653589793238462643383279502884197\
42 169399375105820974944592307816406286208998628034825342117068)
45 #define ZERO ((INTERNAL_PRECISION) 0)
46 #define ONE ((INTERNAL_PRECISION) 1)
47 #define TWO ((INTERNAL_PRECISION) 2)
48 #define THREE ((INTERNAL_PRECISION) 3)
49 #define FOUR ((INTERNAL_PRECISION) 4)
50 #define HALF (ONE/TWO)
56 #define PP1(a,b,c) a ## b(c)
57 #define STRINGIFY(name) PP1(PP,2,name)
63 int dn =
z -> dn, dd =
z -> dd, type =
z -> type;
64 int j,
k, da = dd + 1 + type;
67 for (
j = 0;
j < dd;
j++)
72 for (
k = 0,
alpha[dd] =
A * (dn > dd ? -
a[dd] :
ONE);
k < dd;
k++) {
92 for (
i = 0;
i <
d;
i++) {
158 int dp =
z -> dn, dq =
z -> dd, type =
z -> type;
160 z -> db = 2 * dq + 1 + type;
169 free(
p); free(
q); free(
r);
182 quot = dp == dq ?
ZERO :
p[dp] /
q[dq];
184 for (
j = 1;
j <= dp;
j++)
r[
j] =
p[
j] - quot *
q[
j-1];
186 printf(
"%s: Continued Fraction form: deg p = %2d, deg q = %2d, beta = %g\n",
187 __FUNCTION__, dp, dq, (
float) quot);
188 for (
j = 0;
j <= dq + 1;
j++)
189 printf(
"\tp[%2d] = %14.6g\tq[%2d] = %14.6g\tr[%2d] = %14.6g\n",
191 j, (
float) (
j == 0 ?
ZERO :
q[
j-1]),
192 j, (
float) (
j == dp ?
ZERO :
r[
j]));
207 quot = dp == dq ?
p[dp] /
q[dq] :
ZERO;
208 for (
j = 0;
j < dq;
j++)
r[
j] =
p[
j] - quot *
q[
j];
210 printf(
"%s: Continued Fraction form: deg p = %2d, deg q = %2d, beta = %g\n",
211 __FUNCTION__, dp, dq, (
float) quot);
212 for (
j = 0;
j <= dq;
j++)
213 printf(
"\tp[%2d] = %14.6g\tq[%2d] = %14.6g\tr[%2d] = %14.6g\n",
216 j, (
float) (
j == dq ?
ZERO :
r[
j]));
263 return 2*
a*xi / (
d +
c*xi*xi);
278 sgn = ((int) (fabs(
u) /
K)) % 4;
280 sgn = 1 - ((sgn & 1) << 1);
282 *dn = sqrt(
ONE -
k*
k* *sn * *sn);
295 INTERNAL_PRECISION A,
c,
cp, kp, ksq, sn, cn, dn, Kp, Kj,
z, z0,
t, M,
F,
296 l, invlambda, xi, xisq, *tv,
s, opl;
299 izd *
d = (izd*) malloc(
sizeof(izd));
305 d -> dn =
d -> dd - 1 +
n % 2;
306 d -> deg_denom = 2 *
d -> dd;
307 d -> deg_num = 2 *
d -> dn + 1;
314 kp = sqrt(
ONE - ksq);
325 for (
m = 0;
m <
d -> dd;
m++) {
326 czero = 2 * (
m + 1) ==
n;
332 if (!czero) (
d ->
a)[
d -> dn - 1 -
m] = ksq /
c;
338 (
d -> ap)[
d -> dd - 1 -
m] = ksq /
cp;
342 invlambda *= (
ONE -
c*xisq) / (
ONE -
cp*xisq);
346 d -> Delta = (invlambda -
ONE) / (invlambda +
ONE);
355 ), sqrt(
ONE -
l*
l), &sn, &cn, &dn, &
F, &Kj);
357 for (
m = 0;
m <
d ->
n;
m++) {
366 if (
d -> type == 1) {
367 d ->
A = (
ONE -
d -> Delta *
d -> Delta) /
d ->
A;
368 tv =
d ->
a;
d ->
a =
d -> ap;
d -> ap = tv;
369 ts =
d -> dn;
d -> dn =
d -> dd;
d -> dd = ts;
370 ts =
d -> deg_num;
d -> deg_num =
d -> deg_denom;
d -> deg_denom = ts;
378 zd = (zolotarev_data*) malloc(
sizeof(zolotarev_data));
383 zd -> type =
d -> type;
388 zd -> deg_num =
d -> deg_num;
389 zd -> deg_denom =
d -> deg_denom;
419 izd *
d = (izd*) malloc(
sizeof(izd));
425 d -> dn =
d -> dd - 1 +
n % 2;
426 d -> deg_denom = 2 *
d -> dd;
427 d -> deg_num = 2 *
d -> dn + 1;
439 for (
m = 0;
m <
d -> dd;
m++) {
440 czero = 2 * (
m + 1) ==
n;
446 (
d ->
a)[
d -> dn - 1 -
m] =
c;
453 (
d -> ap)[
d -> dd - 1 -
m] =
cp;
459 for (
m = 0;
m <
d ->
n;
m++)
d -> gamma[
m] =
ONE;
462 d -> Delta =
ONE - M;
469 zd = (zolotarev_data*) malloc(
sizeof(zolotarev_data));
474 zd -> type =
d -> type;
479 zd -> deg_num =
d -> deg_num;
480 zd -> deg_denom =
d -> deg_denom;
512 free( rdata->alpha );
514 free( rdata->gamma );
522 #define ZERO ((PRECISION) 0)
524 #define ONE ((PRECISION) 1)
526 #define TWO ((PRECISION) 2)
534 if (rdata -> type == 0) {
536 for (
m = 0;
m < rdata -> deg_denom/2;
m++)
537 R *= (2*(
m+1) > rdata -> deg_num ?
ONE :
x*
x - rdata ->
a[
m]) /
538 (
x*
x - rdata -> ap[
m]);
541 for (
m = 0;
m < rdata -> deg_num/2;
m++)
542 R *= (
x*
x - rdata ->
a[
m]) /
543 (2*(
m+1) > rdata -> deg_denom ?
ONE :
x*
x - rdata -> ap[
m]);
553 for (
m = 0;
m < rdata -> dd;
m++)
554 R += rdata ->
alpha[
m] / (
x *
x - rdata -> ap[
m]);
555 if (rdata -> type == 1) R += rdata ->
alpha[rdata -> dd] / (
x *
x);
570 for (
m = 1;
m < rdata -> db;
m++) R = rdata ->
beta[
m] *
x +
ONE / R;
580 T = rdata -> type == 0 ?
ONE : -
ONE;
581 for (
m = 0;
m < rdata ->
n;
m++)
582 T *= (rdata -> gamma[
m] -
x) / (rdata -> gamma[
m] +
x);
601 int main(
int argc,
char** argv) {
603 int m,
n, plotpts = 5000, type = 0;
604 float eps,
x, ypferr, ycferr, ycaylerr, maxypferr, maxycferr, maxycaylerr;
605 zolotarev_data *rdata;
607 FILE *plot_function, *plot_error,
608 *plot_partfrac, *plot_contfrac, *plot_cayley;
610 if (argc < 3 || argc > 4) {
611 fprintf(stderr,
"Usage: %s epsilon n [type]\n", *argv);
614 sscanf(argv[1],
"%g", &
eps);
615 sscanf(argv[2],
"%d", &
n);
616 if (argc == 4) sscanf(argv[3],
"%d", &type);
618 if (type < 0 || type > 2) {
619 fprintf(stderr,
"%s: type must be 0 (Zolotarev R(0) = 0),\n"
620 "\t\t1 (Zolotarev R(0) = Inf, or 2 (Higham)\n", *argv);
628 printf(
"Zolotarev Test: R(epsilon = %g, n = %d, type = %d)\n\t"
632 "\n\n\tRational approximation of degree (%d,%d), %s at x = 0\n"
633 "\tDelta = %g (maximum error)\n\n"
634 "\tA = %g (overall factor)\n",
635 (
float) rdata ->
epsilon, rdata ->
n, type,
636 rdata -> deg_num, rdata -> deg_denom,
637 rdata -> type == 1 ?
"infinite" :
"zero",
638 (
float) rdata -> Delta, (
float) rdata ->
A);
639 for (
m = 0;
m <
MIN(rdata -> dd, rdata -> dn);
m++)
640 printf(
"\ta[%2d] = %14.8g\t\ta'[%2d] = %14.8g\n",
641 m + 1, (
float) rdata ->
a[
m],
m + 1, (float) rdata -> ap[
m]);
642 if (rdata -> dd > rdata -> dn)
643 printf(
"\t\t\t\t\ta'[%2d] = %14.8g\n",
644 rdata -> dn + 1, (
float) rdata -> ap[rdata -> dn]);
645 if (rdata -> dd < rdata -> dn)
646 printf(
"\ta[%2d] = %14.8g\n",
647 rdata -> dd + 1, (
float) rdata ->
a[rdata -> dd]);
649 printf(
"\n\tPartial fraction coefficients\n");
650 printf(
"\talpha[ 0] = %14.8g\n",
651 (
float) rdata ->
alpha[rdata -> da - 1]);
652 for (
m = 0;
m < rdata -> dd;
m++)
653 printf(
"\talpha[%2d] = %14.8g\ta'[%2d] = %14.8g\n",
654 m + 1, (
float) rdata ->
alpha[
m],
m + 1, (
float) rdata -> ap[
m]);
655 if (rdata -> type == 1)
656 printf(
"\talpha[%2d] = %14.8g\ta'[%2d] = %14.8g\n",
657 rdata -> dd + 1, (
float) rdata ->
alpha[rdata -> dd],
658 rdata -> dd + 1, (
float)
ZERO);
660 printf(
"\n\tContinued fraction coefficients\n");
661 for (
m = 0;
m < rdata -> db;
m++)
662 printf(
"\tbeta[%2d] = %14.8g\n",
m, (
float) rdata ->
beta[
m]);
664 printf(
"\n\tCayley transform coefficients\n");
665 for (
m = 0;
m < rdata ->
n;
m++)
666 printf(
"\tgamma[%2d] = %14.8g\n",
m, (
float) rdata -> gamma[
m]);
669 plot_function = fopen(
"zolotarev-fn.dat",
"w");
670 plot_error = fopen(
"zolotarev-err.dat",
"w");
672 plot_partfrac = fopen(
"zolotarev-partfrac.dat",
"w");
673 plot_contfrac = fopen(
"zolotarev-contfrac.dat",
"w");
674 plot_cayley = fopen(
"zolotarev-cayley.dat",
"w");
676 for (
m = 0, maxypferr = maxycferr = maxycaylerr = 0.0;
m <= plotpts;
m++) {
677 x = 2.4 * (float)
m / plotpts - 1.2;
678 if (rdata -> type == 0 || fabs(
x) * (float) plotpts > 1.0) {
681 fprintf(plot_function,
"%g %g\n",
x, (
float)
y);
682 fprintf(plot_error,
"%g %g\n",
683 x, (
float)((
y - ((
x > 0.0 ?
ONE : -
ONE))) / rdata -> Delta));
684 ypferr = (float)((zolotarev_partfrac_eval((
PRECISION)
x, rdata) -
y)
686 ycferr = (float)((zolotarev_contfrac_eval((
PRECISION)
x, rdata) -
y)
688 ycaylerr = (float)((zolotarev_cayley_eval((
PRECISION)
x, rdata) -
y)
690 if (fabs(
x) < 1.0 && fabs(
x) > rdata ->
epsilon) {
691 maxypferr =
MAX(maxypferr, fabs(ypferr));
692 maxycferr =
MAX(maxycferr, fabs(ycferr));
693 maxycaylerr =
MAX(maxycaylerr, fabs(ycaylerr));
696 fprintf(plot_partfrac,
"%g %g\n",
x, ypferr);
697 fprintf(plot_contfrac,
"%g %g\n",
x, ycferr);
698 fprintf(plot_cayley,
"%g %g\n",
x, ycaylerr);
704 fclose(plot_contfrac);
705 fclose(plot_partfrac);
708 fclose(plot_function);
710 printf(
"\n\tMaximum PF error = %g (relative to Delta)\n", maxypferr);
711 printf(
"\tMaximum CF error = %g (relative to Delta)\n", maxycferr);
712 printf(
"\tMaximum Cayley error = %g (relative to Delta)\n", maxycaylerr);
717 free(rdata ->
alpha);
719 free(rdata -> gamma);
GTEST_API_ int main(int argc, char **argv)
int epsilon(int i, int j, int k)
static const LatticeInteger & beta(const int dim)
static const LatticeInteger & alpha(const int dim)
static multi1d< LatticeColorMatrix > u
LinOpSysSolverMGProtoClover::T T
multi1d< LatticeFermion > r(Ncb)
multi1d< LatticeColorMatrix > U
#define INTERNAL_PRECISION
static INTERNAL_PRECISION K
static INTERNAL_PRECISION U
zolotarev_data * higham(PRECISION epsilon, int n)
static INTERNAL_PRECISION * contfrac_B(INTERNAL_PRECISION *, INTERNAL_PRECISION *, INTERNAL_PRECISION *, INTERNAL_PRECISION *, int, int)
static void sncndnFK(INTERNAL_PRECISION u, INTERNAL_PRECISION k, INTERNAL_PRECISION *sn, INTERNAL_PRECISION *cn, INTERNAL_PRECISION *dn, INTERNAL_PRECISION *elF, INTERNAL_PRECISION *elK)
static INTERNAL_PRECISION * contfrac_A(INTERNAL_PRECISION *, INTERNAL_PRECISION *, INTERNAL_PRECISION *, INTERNAL_PRECISION *, int, int)
static INTERNAL_PRECISION * poly_factored_to_dense(INTERNAL_PRECISION A, INTERNAL_PRECISION *a, int d)
void zolotarev_free(zolotarev_data *rdata)
static INTERNAL_PRECISION F
zolotarev_data * zolotarev(PRECISION epsilon, int n, int type)
static void construct_contfrac(izd *z)
static INTERNAL_PRECISION AGM(INTERNAL_PRECISION a, INTERNAL_PRECISION b, INTERNAL_PRECISION s)
static void construct_partfrac(izd *z)