home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 247_01 / bncore.c < prev    next >
Text File  |  1989-04-19  |  14KB  |  698 lines

  1. /*
  2.  *   MIRACL Core module - contains initialisation code and general purpose 
  3.  *   utilities.
  4.  *   bncore.c
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "mirdef.h"
  9. #define abs(x)  ((x)<0? (-(x)) : (x))
  10. #define sign(x) ((x)<0? (-1) : 1)
  11.  
  12. #define NK      55
  13. #define NJ      24
  14. #define NV      21
  15.                    /* Constants for random number   *
  16.                     * generator. See Knuth Chapt. 3 */
  17. typedef small *big;
  18. typedef small *flash;
  19.  
  20. /* Declare global variables */
  21.  
  22. small base;        /* number base     */
  23. small apbase;      /* apparent base   */
  24. int pack;          /* packing density */
  25. int lg2b;          /* bits in base    */
  26. small base2;       /* 2^lg2b          */
  27. int nib;           /* length of bigs  */
  28. int workprec;
  29. int stprec;        /* start precision */
  30. int depth;         /* error tracing ..*/
  31. int trace[20];     /* .. mechanism    */
  32. bool check;        /* overflow check  */
  33. long ira[NK];      /* random number   */
  34. int rndptr;        /* array & pointer */
  35. char *names[] =
  36. {"your program","innum","otnum","cinbin","cotbin",
  37. "multiply","divide","incr","decr","premult",
  38. "subdiv","fdsize","gcd","cbase",
  39. "cinnum","cotnum","root","power",
  40. "powmod","bigdig","bigrand","nxprime","prime",
  41. "mirvar","mad","mirsys","putdig",
  42. "add","subtract","select","xgcd",
  43. "fpack","dconv","shift","round","fmul",
  44. "fdiv","fadd","fsub","fcomp","fconv",
  45. "frecip","fpmul","fincr","fsize","ftrunc",
  46. "frand","strongp","build","log2","exp2",
  47. "fpower","froot","fpi","fexp","flog","fpowf",
  48. "ftan","fatan","fsin","fasin","fcos","facos",
  49. "ftanh","fatanh","fsinh","fasinh","fcosh",
  50. "facosh","flop","gprime"}; /* 70 */
  51.  
  52. big w0;            /* workspace bigs  */
  53. big w1,w2,w3,w4;
  54. big w5,w6,w7;
  55. big w8,w9,w10,w11;
  56. big w12,w13,w14,w15;
  57.  
  58. unsigned char IBUFF[IBSIZ+1]; /* input buffer    */
  59. unsigned char OBUFF[OBSIZ+1]; /* output buffer   */
  60. bool ERCON;        /* error control   */
  61. int  ERNUM;        /* last error code */
  62. bool STROUT;       /* redirect output */
  63. int  LINE;         /* Output line length */
  64. int  IOBASE;       /* base for input and output */
  65. bool WRAP;         /* =ON for wrapround on output, otherwise =OFF       */
  66. bool EXACT;        /* exact flag      */
  67. bool POINT;        /* =ON for radix point, =OFF for fractions in output */
  68. int  NTRY;         /* no. of tries for probablistic primality testing   */
  69. bool TRACER;       /* turns trace tracker on/off */
  70. int  INPLEN;       /* input length               */
  71.  
  72. extern char *calloc();
  73.  
  74. void berror(nerr)
  75. int nerr;
  76. {  /*  Big number error routine  */
  77. int i;
  78. if (ERCON)
  79. {
  80.     ERNUM=nerr;
  81.     return;
  82. }
  83. printf("MIRACL error from routine %s\n",
  84. names[trace[depth]]);
  85. for (i=depth-1;i>=0;i--)
  86. printf("              called from %s\n",
  87. names[trace[i]]);
  88. switch (nerr)
  89. {
  90. case 1 :
  91. printf("Number base too big for representation\n");
  92. exit(0);
  93. case 2 :
  94. printf("Division by zero attempted\n");
  95. exit(0);
  96. case 3 : 
  97. printf("Overflow\n");
  98. exit(0);
  99. case 4 :
  100. printf("Internal result is negative\n");
  101. exit(0);
  102. case 5 : 
  103. printf("Input format error\n");
  104. exit(0);
  105. case 6 :
  106. printf("Illegal number base\n");
  107. exit(0);
  108. case 7 : 
  109. printf("Illegal parameter usuage\n");
  110. exit(0);
  111. case 8 :
  112. printf("Out of space\n");
  113. exit(0);
  114. case 9 :
  115. printf("Even root of a negative number\n");
  116. exit(0);
  117. case 10:
  118. printf("Raising integer to negative power\n");
  119. exit(0);
  120. case 11:
  121. printf("Attempt to take illegal root\n");
  122. exit(0);
  123. case 12:
  124. printf("Integer operation attempted on Flash number\n");
  125. exit(0);
  126. case 13:
  127. printf("Flash overflow\n");
  128. exit(0);
  129. case 14:
  130. printf("Numbers too big\n");
  131. exit(0);
  132. case 15:
  133. printf("Log of a non-positive number\n");
  134. exit(0);
  135. case 16:
  136. printf("Double to flash conversation failure\n");
  137. exit(0);
  138. case 17:
  139. printf("I/O buffer overflow\n");
  140. exit(0);
  141. }
  142. }
  143.  
  144. void track()
  145. { /* track course of program execution *
  146.    * through the MIRACL routines       */
  147.     int i;
  148.     for (i=0;i<depth;i++) putchar('-');
  149.     putchar('>');
  150.     printf("%s\n",names[trace[depth]]);
  151. }
  152.  
  153. small brand()
  154. { /* random number generator - uses Knuth's *
  155.    * subtractive method                     */
  156.     int i;
  157.     small t;
  158.     long k;   
  159.     rndptr++;
  160.     t=(small)ira[rndptr];
  161.     if (rndptr<NK) return abs(t);
  162.     rndptr=0;
  163.     for (i=0;i<NJ;i++)
  164.     {
  165.         k=ira[i]-ira[i+NK-NJ];
  166.         if (k<0) k+=MAXNUM;
  167.         ira[i]=k;
  168.     }
  169.     for (i=NJ;i<NK;i++)
  170.     {
  171.         k=ira[i]-ira[i-NJ];
  172.         if (k<0) k+=MAXNUM;
  173.         ira[i]=k;
  174.     }
  175.     t=(small)ira[0];
  176.     return abs(t);
  177. }
  178.  
  179. void irand(seed)
  180. long seed;
  181. { /* initialise random number system */
  182.     int i,in;
  183.     long k;
  184.     k=1L;
  185.     ira[0]=seed;
  186.     for (i=1;i<NK;i++)
  187.     {
  188.         in=(NV*i)%NK;
  189.         ira[in]=k;
  190.         k=seed-k;
  191.         if (k<0) k+=MAXNUM;
  192.         seed=ira[in];
  193.     }
  194.     for (i=1;i<4;i++)
  195.     { /* warm-up the generator */
  196.         rndptr=NK;
  197.         brand();
  198.     }
  199. }
  200.  
  201. void setbase(nb)
  202. small nb;
  203. {  /* set base. Pack as many digits as  *
  204.     * possible into each computer word  */
  205.     small temp;
  206.     apbase=nb;
  207.     pack=1;
  208.     base=nb;
  209.     temp=MAXBASE/nb;
  210.     while (temp>=nb)
  211.     {
  212.         temp/=nb;
  213.         base*=nb;
  214.         pack++;
  215.     }
  216. }
  217.  
  218. bool fit(x,y,f)
  219. big x,y;
  220. int f;
  221. { /* returns TRUE if x/y would fit flash format of length f */
  222.     int n,d;
  223.     n=abs(x[0]);
  224.     d=abs(y[0]);
  225.     if (n==1 && x[1]==1) n=0;
  226.     if (d==1 && y[1]==1) d=0;
  227.     if (n+d<=f) return TRUE;
  228.     return FALSE;
  229. }
  230.  
  231. int lent(x)
  232. flash x;
  233. { /* return length of big or flash in words */
  234.     small lx;
  235.     lx=abs(x[0]);
  236.     return (int)((lx&MSK)+((lx>>BTS)&MSK));
  237. }
  238.  
  239. void zero(x)
  240. flash x;
  241. { /* set big/flash number to zero */
  242.     int i,n;
  243.     if (ERNUM) return;
  244.     n=lent(x);
  245.     for (i=0;i<=n;i++)
  246.         x[i]=0;
  247. }
  248.  
  249. void convert(n,x)
  250. big x;
  251. small n;
  252. {  /*  convert integer n to big number format  */
  253.     int m,s;
  254.     zero(x);
  255.     if (n==0) return;
  256.     s=sign(n);
  257.     n=abs(n);
  258.     m=0;
  259.     while (n>0)
  260.     {
  261.         m++;
  262.         x[m]=n%base;
  263.         n/=base;
  264.     }
  265.     x[0]=m*s;
  266. }
  267.  
  268. void lconv(n,x)
  269. big x;
  270. long n;
  271. { /* convert long integer to big number format */
  272.     int m,s;
  273.     zero(x);
  274.     if (n==0) return;
  275.     s=sign(n);
  276.     n=abs(n);
  277.     m=0;
  278.     while (n>0)
  279.     {
  280.         m++;
  281.         x[m]=n%base;
  282.         n/=base;
  283.     }
  284.     x[0]=m*s;
  285. }
  286.  
  287. flash mirvar(iv)
  288. small iv;
  289. { /* initialize big/flash number */
  290.     flash x;
  291.     if (ERNUM) return x;
  292.     depth++;
  293.     trace[depth]=23;
  294.     if (TRACER) track();
  295.     x=(small *)calloc(nib+1,sizeof(small));
  296.     if (x==NULL)
  297.     {
  298.         berror(8);
  299.         depth--;
  300.         return x;
  301.     }
  302.     convert(iv,x);
  303.     depth--;
  304.     return x;
  305. }
  306.  
  307. void mirsys(nd,nb)
  308. int nd;
  309. small nb;
  310. {  /*  Initialize MIRACL system to   *
  311.     *  use numbers to base nb, and   *
  312.     *  nd digits or (-nd) bytes long */
  313.     small b;
  314.     depth=0;
  315.     trace[0]=0;
  316.     depth++;
  317.     trace[depth]=25;
  318.     if (nb<2 || nb>MAXBASE)
  319.     {
  320.         berror(6);
  321.         depth--;
  322.         return;
  323.     }
  324.     setbase(nb);
  325.     b=base;
  326.     lg2b=0;
  327.     base2=1;
  328.     while (b>1)
  329.     {
  330.         b/=2;
  331.         lg2b++;
  332.         base2*=2;
  333.     }
  334.     if (nd>0)
  335.         nib=(nd-1)/pack+1;
  336.     else
  337.         nib=(lg2b-8*nd-1)/lg2b;
  338.     if (nib<2) nib=2;
  339.     workprec=nib;
  340.     stprec=nib;
  341.     while (stprec>WPERD) stprec=(stprec+1)/2;
  342.     check=ON;
  343.     IOBASE=10;   /* defaults */
  344.     WRAP=ON;
  345.     STROUT=FALSE;
  346.     ERCON=FALSE;
  347.     ERNUM=0;
  348.     POINT=OFF;
  349.     NTRY=6;           /* <=27 */
  350.     EXACT=TRUE;
  351.     IBUFF[0]='\0';
  352.     TRACER=OFF;
  353.     LINE=80;
  354.     INPLEN=0;
  355.     irand(0L);     /* start rand number generator */
  356.     nib*=2;
  357.     if (nib!=(nib&MSK) || nib>TOOBIG)
  358.     {
  359.         berror(14);
  360.         nib/=2;
  361.         depth--;
  362.         return;
  363.     }
  364.     w0=mirvar((small)0); /* w0 is double length  */
  365.     nib/=2;
  366.     w1=mirvar((small)0); /* initialize workspace */
  367.     w2=mirvar((small)0);
  368.     w3=mirvar((small)0);
  369.     w4=mirvar((small)0);
  370.     nib*=2;              /* double length */
  371.     w5=mirvar((small)0);
  372.     w6=mirvar((small)0);
  373.     w7=mirvar((small)0);
  374.     nib/=2;
  375.     w8=mirvar((small)0);
  376.     w9=mirvar((small)0);
  377.     w10=mirvar((small)0);
  378.     w11=mirvar((small)0);
  379.     w12=mirvar((small)0);
  380.     w13=mirvar((small)0);
  381.     w14=mirvar((small)0);
  382.     w15=mirvar((small)0); /* used to store pi */
  383.     depth--;
  384.  
  385. int exsign(x)
  386. flash x;
  387. { /* extract sign of big/flash number */
  388.     return sign(x[0]);
  389. }
  390.  
  391. void insign(s,x)
  392. flash x;
  393. int s;
  394. {  /* assert sign of big/flash number */
  395.     x[0]=s*abs(x[0]);
  396. }   
  397.  
  398. void lzero(x)
  399. big x;
  400. {  /*  strip leading zeros from big number  */
  401.     int m;
  402.     bool neg;
  403.     if (x[0]<0)
  404.     {
  405.         m=(-x[0]);
  406.         neg=TRUE;
  407.     }
  408.     else
  409.     {
  410.         m=x[0];
  411.         neg=FALSE;
  412.     }
  413.     while (m>0 && x[m]==0)
  414.         m--;
  415.     if (neg) x[0]=(-m);
  416.     else     x[0]=m;
  417. }
  418.  
  419. int getdig(x,i)
  420. big x;
  421. int i;
  422. {  /* extract a packed digit */
  423.     int k;
  424.     small n;
  425.     i--;
  426.     n=x[i/pack+1];
  427.     k=i%pack;
  428.     for (i=1;i<=k;i++)
  429.         n/=apbase;
  430.     return n%apbase;
  431. }
  432.  
  433. int numdig(x)
  434. big x;
  435. {  /* returns number of digits in x */
  436.     int nd;
  437.     nd=abs(x[0])*pack;
  438.     while (getdig(x,nd)==0)
  439.         nd--;
  440.     return nd;
  441.  
  442. void putdig(n,x,i)  
  443. big x;
  444. int i;
  445. int n;
  446. {  /* insert a digit into a packed word */
  447.     int j,k,lx;
  448.     small m,p;
  449.     if (ERNUM) return;
  450.     depth++;
  451.     trace[depth]=26;
  452.     if (TRACER) track();
  453.     lx=abs(x[0]);
  454.     m=getdig(x,i);
  455.     p=n;
  456.     i--;
  457.     j=i/pack+1;
  458.     k=i%pack;
  459.     for (i=1;i<=k;i++)
  460.     {
  461.         m*=apbase;
  462.         p*=apbase;
  463.     }
  464.     if (check && j>nib)
  465.     {
  466.         berror(3);
  467.         depth--;
  468.         return;
  469.     }
  470.     x[j]=x[j]-m+p;
  471.     if (j>lx) x[0]=j*exsign(x);
  472.     lzero(x);
  473.     depth--;
  474. }
  475.  
  476. void copy(x,y)
  477. flash x;
  478. flash y;
  479. {  /* copy x to y: y=x  */
  480.     int i,nx,ny;
  481.     if (ERNUM || x==y) return;
  482.     ny=lent(y);
  483.     nx=lent(x);
  484.     for (i=nx+1;i<=ny;i++)
  485.         y[i]=0;
  486.     for (i=0;i<=nx;i++)
  487.         y[i]=x[i];
  488. }
  489.  
  490. void negate(x,y)
  491. flash x;
  492. flash y;
  493. { /* negate a big/flash variable: y=-x */
  494.     copy(x,y);
  495.     y[0]=(-y[0]);
  496. }
  497.  
  498. void absol(x,y)
  499. flash x;
  500. flash y;
  501. { /* y=abs(x) */
  502.     copy(x,y);
  503.     y[0]=abs(y[0]);
  504. }
  505.  
  506. bool notint(x)
  507. flash x;
  508. { /* returns TRUE if x is Flash */
  509.     if (((abs(x[0])>>BTS)&MSK)!=0) return TRUE;
  510.     return FALSE;
  511. }
  512.  
  513. void shift(x,n,w)
  514. big x,w;
  515. int n;
  516. { /* set w=x.(base^n) by shifting */
  517.     int i,bl;
  518.     copy(x,w);
  519.     if (ERNUM || w[0]==0 || n==0) return;
  520.     depth++;
  521.     trace[depth]=33;
  522.     if (TRACER) track();
  523.     if (notint(w)) berror(12);
  524.     bl=abs(w[0])+n;
  525.     if (check && bl>nib) berror(3);
  526.     if (ERNUM)
  527.     {
  528.        depth--;
  529.        return;
  530.     }
  531.     if (n>0)
  532.     {
  533.         for (i=bl;i>n;i--)
  534.             w[i]=w[i-n];
  535.         for (i=1;i<=n;i++)
  536.             w[i]=0;
  537.     }
  538.     else
  539.     {
  540.         n=(-n);
  541.         for (i=1;i<=bl;i++)
  542.             w[i]=w[i+n];
  543.         for (i=1;i<=n;i++)
  544.             w[bl+i]=0;
  545.     }
  546.     w[0]=bl*exsign(w);
  547.     depth--;
  548. }
  549.  
  550. int size(x)
  551. big x;
  552. {  /*  get size of big number;  convert to *
  553.     *  integer - if possible               */
  554.     int s;
  555.     small m;
  556.     s=sign(x[0]);
  557.     m=abs(x[0]);
  558.     if (m==0) return 0;
  559.     if (m==1 && x[1]<TOOBIG) return s*x[1];
  560.     return s*TOOBIG;
  561. }
  562.  
  563. int compare(x,y)
  564. big x;
  565. big y;
  566. {  /* compare x and y: =1 if x>y  =-1 if x<y *
  567.     *  =0 if x=y                             */
  568.     int m,s;
  569.     if (x==y) return 0;
  570.     if (x[0]>y[0]) return 1;
  571.     if (x[0]<y[0]) return -1;
  572.     s=sign(x[0]);
  573.     m=abs(x[0]);
  574.     while (m>0)
  575.     { /* check digit by digit */
  576.         if (x[m]>y[m]) return s;
  577.         if (x[m]<y[m]) return -s;
  578.         m--;
  579.     }
  580.     return 0;
  581. }
  582.  
  583. void fpack(n,d,x)
  584. big n,d;
  585. flash x;
  586. { /* create floating-slash number x=n/d from *
  587.    * big integer numerator and denominator   */
  588.     int i,s,ld,ln;
  589.     if (ERNUM) return;
  590.     depth++;
  591.     trace[depth]=31;
  592.     if (TRACER) track();
  593.     ld=abs(d[0]);
  594.     if (ld==0) berror(13);
  595.     if (x==d) berror(7);
  596.     if (notint(n) || notint(d)) berror(12);
  597.     s=exsign(n);
  598.     ln=abs(n[0]);
  599.     if (abs(size(n))==1) ln=0;
  600.     if (ld+ln>nib) berror(13);
  601.     if (ERNUM)
  602.     {
  603.        depth--;
  604.        return;
  605.     }
  606.     copy(n,x);
  607.     if (size(n)==0)
  608.     {
  609.         depth--;
  610.         return;
  611.     }
  612.     s*=exsign(d);
  613.     if (abs(size(d))==1)
  614.     {
  615.         insign(s,x);
  616.         depth--;
  617.         return;
  618.     }
  619.     for (i=1;i<=ld;i++)
  620.         x[ln+i]=d[i];
  621.     x[0]=s*(ln+((small)ld<<BTS));
  622.     depth--;
  623. }
  624.  
  625. void numer(x,y)
  626. flash x;
  627. big y;
  628. { /* extract numerator of x */
  629.     int i,s,ln,ld;
  630.     small ly;
  631.     if (ERNUM) return;
  632.     copy(x,y);
  633.     if (notint(y))
  634.     {
  635.         s=exsign(y);
  636.         ly=abs(y[0]);
  637.         ln=(ly&MSK);
  638.         if (ln==0)
  639.         {
  640.             convert((small)s,y);
  641.             return;
  642.         }
  643.         ld=((ly>>BTS)&MSK);
  644.         for (i=1;i<=ld;i++)
  645.             y[ln+i]=0;
  646.         y[0]=ln*s;
  647.     }
  648. }
  649.  
  650. void denom(x,y)
  651. flash x;
  652. big y;
  653. { /* extract denominator of x */
  654.     int i,ln,ld;
  655.     small ly;
  656.     if (ERNUM) return;
  657.     if (!notint(x))
  658.     {
  659.         convert((small)1,y);
  660.         return;
  661.     }
  662.     copy(x,y);
  663.     ly=abs(y[0]);
  664.     ln=(ly&MSK);
  665.     ld=((ly>>BTS)&MSK);
  666.     y[0]=ld;
  667.     if (ln==0) return;
  668.     for (i=1;i<=ld;i++)
  669.         y[i]=y[ln+i];
  670.     for (i=1;i<=ln;i++)
  671.         y[ld+i]=0;
  672. }
  673.  
  674. small igcd(x,y)
  675. small x,y;
  676. { /* integer GCD, returns GCD of x and y */
  677.     small r;
  678.     if (y==0) return x;
  679.     while ((r=x%y)!=0)
  680.         x=y,y=r;
  681.     return y;
  682. }
  683.  
  684. small isqrt(num,guess)
  685. small num,guess;
  686. { /* square root of an integer */
  687.     small sqr;
  688.     forever
  689.     { /* Newtons iteration */
  690.         sqr=guess+(((num/guess)-guess)/2);
  691.         if (sqr==guess) return sqr;
  692.         guess=sqr;
  693.     }
  694. }
  695.  
  696.