static int /* convert columns to power series */ cols(projUV **c, projUV **d, int nu, int nv) { projUV *sv, **dd; int j, k; dd = (projUV **)vector2(nu, nv, sizeof(projUV)); if (!dd) return 0; sv = (projUV *)vector1(nv, sizeof(projUV)); if (!sv) { freev2((void **)dd, nu); return 0; } bclear(d, nu, nv); bclear(dd, nu, nv); bmove(d[0], c[nu-1], nv); for (j = nu-2; j >= 1; --j) { for (k = nu-j; k >= 1; --k) { bmove(sv, d[k], nv); submop(d[k], 2., d[k-1], dd[k], nv); bmove(dd[k], sv, nv); } bmove(sv, d[0], nv); subop(d[0], c[j], dd[0], nv); bmove(dd[0], sv, nv); } for (j = nu-1; j >= 1; --j) subop(d[j], d[j-1], dd[j], nv); submop(d[0], .5, c[0], dd[0], nv); freev2((void **) dd, nu); pj_dalloc(sv); return 1; }
static void /* convert columns to power series */ cols(UV **c, UV **d, int nu, int nv) { UV *sv, **dd; int j, k; dd = (UV **)vector2(nu, nv, sizeof(UV)); sv = (UV *)vector1(nv, sizeof(UV)); bclear(d, nu, nv); bclear(dd, nu, nv); bmove(d[0], c[nu-1], nv); for (j = nu-2; j >= 1; --j) { for (k = nu-j; k >= 1; --k) { bmove(sv, d[k], nv); submop(d[k], 2., d[k-1], dd[k], nv); bmove(dd[k], sv, nv); } bmove(sv, d[0], nv); subop(d[0], c[j], dd[0], nv); bmove(dd[0], sv, nv); } for (j = nu-1; j >= 1; --j) subop(d[j], d[j-1], dd[j], nv); submop(d[0], .5, c[0], dd[0], nv); freev2(dd, nu); pj_dalloc(sv); }
int /* entry point */ bch2bps(projUV a, projUV b, projUV **c, int nu, int nv) { projUV **d; int i; if (nu < 1 || nv < 1 || !(d = (projUV **)vector2(nu, nv, sizeof(projUV)))) return 0; /* do rows to power series */ for (i = 0; i < nu; ++i) { rows(c[i], d[i], nv); rowshft(a.v, b.v, d[i], nv); } /* do columns to power series */ cols(d, c, nu, nv); colshft(a.u, b.u, c, nu, nv); freev2((void **) d, nu); return 1; }
Tseries * mk_cheby(projUV a, projUV b, double res, projUV *resid, projUV (*func)(projUV), int nu, int nv, int power) { int j, i, nru, nrv, *ncu, *ncv; Tseries *Ts = 0; projUV **w; double cutres; if (!(w = (projUV **)vector2(nu, nv, sizeof(projUV))) || !(ncu = (int *)vector1(nu + nv, sizeof(int)))) return 0; ncv = ncu + nu; if (!bchgen(a, b, nu, nv, w, func)) { projUV *s; double *p; /* analyse coefficients and adjust until residual OK */ cutres = res; for (i = 4; i ; --i) { eval(w, nu, nv, cutres, resid); if (resid->u < res && resid->v < res) break; cutres *= 0.5; } if (i <= 0) /* warn of too many tries */ resid->u = - resid->u; /* apply cut resolution and set pointers */ nru = nrv = 0; for (j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; /* clear column maxes */ for (s = w[j], i = 0; i < nv; ++i, ++s) { if (fabs(s->u) < cutres) /* < resolution ? */ s->u = 0.; /* clear coefficient */ else ncu[j] = i + 1; /* update column max */ if (fabs(s->v) < cutres) /* same for v coef's */ s->v = 0.; else ncv[j] = i + 1; } if (ncu[j]) nru = j + 1; /* update row max */ if (ncv[j]) nrv = j + 1; } if (power) { /* convert to bivariate power series */ if (!bch2bps(a, b, w, nu, nv)) goto error; /* possible change in some row counts, so readjust */ nru = nrv = 0; for (j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; /* clear column maxes */ for (s = w[j], i = 0; i < nv; ++i, ++s) { if (s->u) ncu[j] = i + 1; /* update column max */ if (s->v) ncv[j] = i + 1; } if (ncu[j]) nru = j + 1; /* update row max */ if (ncv[j]) nrv = j + 1; } Ts = makeT(nru, nrv); if (Ts) { Ts->a = a; Ts->b = b; Ts->mu = nru - 1; Ts->mv = nrv - 1; Ts->power = 1; for (i = 0; i < nru; ++i) /* store coefficient rows for u */ Ts->cu[i].m = ncu[i]; if (Ts->cu[i].m) { if ((p = Ts->cu[i].c = (double *)pj_malloc(sizeof(double) * ncu[i]))) { for (j = 0; j < ncu[i]; ++j) { *p++ = (w[i] + j)->u; } } else { goto error; } } for (i = 0; i < nrv; ++i) /* same for v */ Ts->cv[i].m = ncv[i]; if (Ts->cv[i].m) { if ((p = Ts->cv[i].c = (double *)pj_malloc(sizeof(double) * ncv[i]))) { for (j = 0; j < ncv[i]; ++j) { *p++ = (w[i] + j)->v; } } else { goto error; } } } } else if ((Ts = makeT(nru, nrv))) { /* else make returned Chebyshev coefficient structure */ Ts->mu = nru - 1; /* save row degree */ Ts->mv = nrv - 1; Ts->a.u = a.u + b.u; /* set argument scaling */ Ts->a.v = a.v + b.v; Ts->b.u = 1. / (b.u - a.u); Ts->b.v = 1. / (b.v - a.v); Ts->power = 0; for (i = 0; i < nru; ++i) /* store coefficient rows for u */ Ts->cu[i].m = ncu[i]; if (Ts->cu[i].m) { if ((p = Ts->cu[i].c = (double *)pj_malloc(sizeof(double) * ncu[i]))) { for (j = 0; j < ncu[i]; ++j) *p++ = (w[i] + j)->u; } else { goto error; } } for (i = 0; i < nrv; ++i) /* same for v */ Ts->cv[i].m = ncv[i]; if (Ts->cv[i].m) { if ((p = Ts->cv[i].c = (double *)pj_malloc(sizeof(double) * ncv[i]))) { for (j = 0; j < ncv[i]; ++j) *p++ = (w[i] + j)->v; } else { goto error; } } } else goto error; } goto gohome; error: if (Ts) { /* pj_dalloc up possible allocations */ for (i = 0; i <= Ts->mu; ++i) if (Ts->cu[i].c) pj_dalloc(Ts->cu[i].c); for (i = 0; i <= Ts->mv; ++i) if (Ts->cv[i].c) pj_dalloc(Ts->cv[i].c); pj_dalloc(Ts); } Ts = 0; gohome: freev2((void **) w, nu); pj_dalloc(ncu); return Ts; }