X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=moebius2.git;a=blobdiff_plain;f=interpolate.c;h=a2d1cafd48de65ad50b943f92afd6495a11de0c7;hp=f5d7c1bb9c727517e9bb3784f3cc5f64ac41d9b0;hb=ad8f9959ed7e147b88a57a7634c78faa69cefc6a;hpb=df4fafe44b168dc0e79489e558fc00b3a2b7da3f diff --git a/interpolate.c b/interpolate.c index f5d7c1b..a2d1caf 100644 --- a/interpolate.c +++ b/interpolate.c @@ -4,19 +4,21 @@ #include "mgraph.h" -#define OXBITS (XBITS-1) -#define OX (1< INT_MAX) fail("input file is not reasonable whole number of vertices\n"); - fprintf(stderr,"XBITS=%d XY=%d*%d=%d\n", XBITS, X,Y,N); - fprintf(stderr,"OXBITS=%d OXY=%d*%d=%d\n", OXBITS, OX,OY,ON); - fprintf(stderr,"sizeof(double)=%d st_size=%lu\n", - (int)sizeof(double), (unsigned long)stab.st_size); + printf("XBITS=%d XY=%d*%d=%d", XBITS, X,Y,N); + + oN= stab.st_size / (sizeof(double)*D3); + + for (shift=1, inc=2; + shift%2d", oy,y); - for (ox=x=0; x%2d", oy,y); + for (ox=0; ox>1))*inc + (y>>1) + X*2; + while (x>=X) { y= (Y-1)-y; x-=X; } errno= 0; - ov= (oy << OXBITS) | ox; + ov= (oy << oXBITS) | ox; v= (y << YSHIFT) | x; - fprintf(stderr, " 0%02o->0x%02x", ov, v); + printf(" 0%02o->0x%02x", ov, v); if (fread(all.a[v], sizeof(double), D3, stdin) != D3) diee("\nread input"); - computed_count[v]= -1; + computed_count[v]= D3*2; } - fputc('\n',stderr); + putchar('\n'); } } @@ -73,6 +95,10 @@ typedef struct { static void traverse_next(Traverse *t) { int v2; + + if (t->v<0) + return; + v2= EDGE_END2(t->v, t->e); if (v2>=0) { int e2= edge_reverse(t->v, t->e); @@ -81,112 +107,214 @@ static void traverse_next(Traverse *t) { } t->v= v2; } - -static void interpolate_line(int startvertex, - int direction /* edge number */, - int nmax) { + +static void interpolate_lin4point(void) { + /* four points P Q R S, although P and S may be missing + * interpolate in QR finding M. */ + int xq,yq,eqr, vp,vq,vm,vr,vs, k; + double pqtarg[D3], srtarg[D3]; + + if (inc != 2) fail("cannot do >2x lin4point interpolation\n"); + + for (eqr=1; eqr!=4; eqr+=5, eqr%=V6) { /* each old edge exactly once */ + printf("eqr=%d\n",eqr); + for (yq=0; yq>1)&1); xq=0); + + traverse_next(&trav); + traverse_next(&trav); + vs= trav.v; + + trav.v= vq; trav.e= EDGE_OPPOSITE(eqr); + traverse_next(&trav); + traverse_next(&trav); + vp= trav.v; + + printf(" 0x%02x-##-%02x-!%02x!-%02x-##-%02x", + vp&0xff,vq,vm,vr,vs&0xff); + + if (vp>=0) + K pqtarg[k]= all.a[vq][k]*2 - all.a[vp][k]; + else + K pqtarg[k]= all.a[vr][k]; + + if (vs>=0) + K srtarg[k]= all.a[vr][k]*2 - all.a[vs][k]; + else + K srtarg[k]= all.a[vq][k]; + + K { + const double alpha= 6; + all.a[vm][k]= 0.5 * (all.a[vq][k] + all.a[vr][k]); + pqtarg[k]= 0.5 * (pqtarg[k] + all.a[vm][k]); + srtarg[k]= 0.5 * (srtarg[k] + all.a[vm][k]); + all.a[vm][k]= (pqtarg[k] + srtarg[k] + alpha * all.a[vm][k]) + / (2 + alpha); + note_computed(vm,k); + } + } + putchar('\n'); + } + } +} + +static void interpolate_gsl_line + (int startvertex, int direction /* edge number */, int nmax, + const gsl_interp_type *aperiodic, const gsl_interp_type *periodic) { double xa[nmax], ya[D3][nmax]; + int vnew[nmax], xnew[nmax]; const gsl_interp_type *it; gsl_interp *interp; gsl_interp_accel *accel; - int i, k, nold, nnew; + int i, k, nold, nnew, x, skipped, realstart; Traverse traverse; -#define STARTV (traverse.v=startvertex, traverse.e=direction) -#define NEXTV (traverse_next(&traverse), fprintf(stderr,"-%02x",traverse.v)) - - fprintf(stderr,"interpolate_line 0x%02x,%d nmax=%d ", + printf("interpolate_line 0x%02x,%d nmax=%d ", startvertex,direction,nmax); - for (i=0, STARTV; - ; - ) { - assert(traverse.v>=0); - assert(i < nmax); - xa[i]= i; - K ya[k][i]= all.a[traverse.v][k]; - fputc('*',stderr); - if (i && traverse.v==startvertex) { fputc('@',stderr); break; } - i++; - NEXTV; - if (traverse.v<0) break; - NEXTV; + traverse.v=startvertex, traverse.e=direction; + skipped= 0; + while (!computed_count[traverse.v]) { + printf("-%02x~",traverse.v); + traverse_next(&traverse); + skipped++; + assert(skipped < nmax); } - if (traverse.v>=0) { - it= gsl_interp_akima_periodic; - nold= i+1; - nnew= i; - } else { - it= gsl_interp_akima; - nold= i; - nnew= i-1; + realstart= traverse.v; + + nold=0, nnew=0; + for (x=0; + ; + x++, traverse_next(&traverse)) { + printf("-%02x",traverse.v); + if (traverse.v<0) { + putchar('$'); + it= aperiodic; + assert(!skipped); + break; + } + if (computed_count[traverse.v]) { + assert(nold < nmax); + xa[nold]= x; + K ya[k][nold]= all.a[traverse.v][k]; + nold++; + putchar('*'); + } else { + assert(nnew < nmax); + xnew[nnew]= x; + vnew[nnew]= traverse.v; + nnew++; + putchar('#'); + } + if (x && traverse.v==realstart) { + putchar('@'); + it= periodic; + break; + } } - fprintf(stderr," n=%d->%d loop=0x%02x", nold,nnew,traverse.v); + printf(" n=%d->%d", nold,nnew); + if (!nnew) { printf(" nothing\n"); return; } + + assert(nold); + printf(" x=%g..%g->%d..%d", xa[0],xa[nold-1], xnew[0],xnew[nnew-1]); K { - fprintf(stderr,"\n k=%d ", k); + printf("\n k=%d ", k); interp= gsl_interp_alloc(it,nold); if (!interp) diee("gsl_interp_alloc"); accel= gsl_interp_accel_alloc(); if(!accel) diee("gsl_interp_accel_alloc"); GA( gsl_interp_init(interp,xa,ya[k],nold) ); - for (i=0, STARTV; - i=0); NEXTV; assert(traverse.v>=0); - fputc('#',stderr); - assert(computed_count[traverse.v] == k); - GA( gsl_interp_eval_e(interp,xa,ya[k], i+0.5, accel, - &all.a[traverse.v][k]) ); - computed_count[traverse.v]++; + for (i=0; i>1)&1), 0, X*2+1, + aperiodic, periodic); } } -static void write_output(void) { +static void write_output(const char *fn) { + FILE *f; + char *fn_new; int x, y, v, c, bad=0; + for (y=0; yOUTPUT.cfm\n",stderr); exit(8); } + if (argc!=4 || + strncmp(argv[1],"-a",2) || strlen(argv[1])!=3 || + argv[2][0]=='-' || + strncmp(argv[3],"-o",2)) { + fputs("usage: interpolate -aK INPUT.cfm -oOUTPUT.cfm\n",stderr); + exit(8); + } + if (!freopen(argv[2],"rb",stdin)) diee("open input"); characterise_input(); read_input(); - interpolate(); - write_output(); - if (fclose(stdout)) diee("fclose stdout"); + + switch (argv[1][2]) { + case '4': interpolate_lin4point(); break; + case 'a': interpolate_gsl(gsl_interp_akima, + gsl_interp_akima_periodic); break; + case 'c': interpolate_gsl(gsl_interp_cspline, + gsl_interp_cspline_periodic); break; + default: + fail("unknown interpolation algorithm\n"); + } + + write_output(argv[3]+2); return 0; }