home *** CD-ROM | disk | FTP | other *** search
- /*
- * MIRACL flash number builder: uses generator of
- * regular continued fraction expansion to create
- * a flash number, rounded if necessary.
- * bnbuild.c
- */
-
- #include <stdio.h>
- #include "miracl.h"
- #define abs(x) ((x)<0? (-(x)) : (x))
-
- /* Access global variables */
-
- extern int depth; /* error tracing .. */
- extern int trace[]; /* .. mechanism */
- extern int check; /* error checking */
- extern small base; /* number base */
- extern int nib; /* no. ints in big */
- extern int workprec;
-
- extern big w0;
- extern big w1; /* workspace variables */
- extern big w2;
- extern big w3;
- extern big w4;
- extern big w7;
-
- void build(x,gen)
- flash x;
- int (*gen)();
- { /* Build x from its regular c.f. *
- * generated by gen() */
- small a,b,c,d,rm,ex1,ex2,ex;
- int q,n,prc,lw2,lw4,lz;
- bool finoff,last;
- big t;
- if (ERNUM) return;
- depth++;
- trace[depth]=48;
- if (TRACER) track();
- zero(w1);
- convert((small)1,w2);
- convert((small)1,w3);
- zero(w4);
- finoff=FALSE;
- last=FALSE;
- n=0;
- q=(*gen)(x,n); /* Note - first quotient may be zero */
- ex=base;
- if (nib==workprec) prc=nib;
- else prc=workprec+1;
- while (!ERNUM && q>=0)
- {
- if (q==TOOBIG || n==0 || finoff)
- {
- if (q!=TOOBIG) convert((small)q,x);
- else last=FALSE;
- check=OFF;
- multiply(w2,x,w0);
- subtract(w1,w0,w7);
- check=ON;
- if (abs(w7[0])>nib) break;
- copy(w7,w1);
- t=w1,w1=w2,w2=t; /* swap(w1,w2) */
- check=OFF;
- multiply(w4,x,w0);
- subtract(w3,w0,w7);
- check=ON;
- if (abs(w7[0])>nib) break;
- copy(w7,w3);
- t=w3,w3=w4,w4=t; /* swap(w3,w4) */
- n++;
- }
- lw2=abs(w2[0]);
- lw4=abs(w4[0]);
- lz=lw2+lw4;
- if (lz > prc) break; /* too big - exit */
- if (last)
- {
- if (finoff) break;
- finoff=TRUE;
- q=(*gen)(x,n);
- continue;
- }
- if (lz>=prc-1)
- { /* nearly finished - so be careful not to overshoot */
- ex1=base/(w2[lw2]+1);
- ex2=base/(w4[lw4]+1);
- if (ex2>ex1) ex=ex1,ex1=ex2,ex2=ex;
- if (lz==prc) ex=ex2;
- else ex=ex1;
- last=TRUE;
- }
- a=1;
- b=0;
- c=0;
- d=1;
- forever
- {
- q=(*gen)(x,n);
- if (q<0 || q==TOOBIG || q>=MAXBASE/abs(d)) break;
- rm=b-q*d;
- b=d;
- d=rm;
- rm=a-q*c;
- a=c;
- c=rm;
- n++;
- if (abs(c-d)>ex) break;
- }
- premult(w1,c,w7);
- premult(w1,a,w1);
- premult(w2,b,w0);
- premult(w2,d,w2);
- add(w1,w0,w1);
- add(w2,w7,w2);
- premult(w3,c,w7);
- premult(w3,a,w3);
- premult(w4,b,w0);
- premult(w4,d,w4);
- add(w3,w0,w3);
- add(w4,w7,w4);
- }
- if (abs(w2[0]-w4[0]) <= nib) fpack(w2,w4,x);
- else fpack(w1,w3,x);
- negate (x,x);
- if (q!=(-1)) EXACT=FALSE;
- depth--;
- }