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

  1. /*
  2.  *   MIRACL arithmetic routines 0 - Add and subtract routines 
  3.  *   bnarth0.c
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "miracl.h"
  8. #define sign(x) ((x)<0? (-1) : 1)
  9.  
  10. /* Access global variables */
  11.  
  12. extern small base;   /* number base      */  
  13. extern int nib;      /* length of bigs   */
  14. extern int depth;    /* error tracing .. */
  15. extern int trace[];  /* ... mechanism    */
  16. extern big w0;       /* workspace big    */
  17. extern bool check;   /* overflow check   */
  18.  
  19. void padd(x,y,z)
  20. big x;
  21. big y;
  22. big z;
  23. { /*  add two  big numbers, z=x+y where   *
  24.    *  x and y are positive and  x>=y      */
  25.     int lx,ly,i;
  26.     small carry,psum;
  27.     lx = x[0];
  28.     ly = y[0];
  29.     if (y!=z) copy(x,z);
  30.     else ly=lx;
  31.     carry=0;
  32.     z[0]=lx;
  33.     if (lx<nib || (!check && lx<2*nib)) z[0]++;
  34.     for (i=1;i<=ly || carry>0;i++)
  35.     { /* add by columns */
  36.         if (i>nib && check)
  37.         {
  38.             berror(3);
  39.             return;
  40.         }
  41.         psum=x[i]+y[i]+carry;
  42.         carry=0;
  43.         if (psum>=base)
  44.         { /* set carry */
  45.             carry=1;
  46.             psum-=base;
  47.         }
  48.         z[i]=psum;
  49.     }
  50.     if (z[z[0]]==0) z[0]--;
  51. }
  52.  
  53. void psub(x,y,z)
  54. big x;
  55. big y;
  56. big z;
  57. {  /*  subtract two big numbers z=x-y      *
  58.     *  where x and y are positive and x>y  */
  59.     int lx,ly,i;
  60.     small borrow,pdiff;
  61.     lx = x[0];
  62.     ly = y[0];
  63.     if (ly>lx)
  64.     {
  65.         berror(4);
  66.         return;
  67.     }
  68.     if (y!=z) copy(x,z);
  69.     else ly=lx;
  70.     z[0]=lx;
  71.     borrow=0;
  72.     for (i=1;i<=ly || borrow>0;i++)
  73.     { /* subtract by columns */
  74.         if (i>lx)
  75.         {
  76.             berror(4);
  77.             return;
  78.         }
  79.         pdiff=x[i]-y[i]-borrow;
  80.         borrow=0;
  81.         if (pdiff<0)
  82.         { /* set borrow */
  83.             pdiff+=base;
  84.             borrow=1;
  85.         }
  86.         z[i]=pdiff;
  87.     }
  88.     lzero(z);
  89. }
  90.  
  91. void select(x,d,y,z)
  92. big x;
  93. int d;
  94. big y;
  95. big z;
  96. { /* perform required add or subtract operation */
  97.     int sx,sy,sz,jf,xgty;
  98.     if (notint(x) || notint(y))
  99.     {
  100.         berror(12);
  101.         return;
  102.     }
  103.     sx=sign(x[0]);
  104.     sy=sign(y[0]);
  105.     if (x[0]<0) x[0]=(-x[0]);  /* force operands to be positive */
  106.     if (y[0]<0) y[0]=(-y[0]);
  107.     xgty=compare(x,y);
  108.     jf=(1+sx)+(1+d*sy)/2;
  109.     switch (jf)
  110.     { /* branch according to signs of operands */
  111.     case 0:
  112.         if (xgty>=0)
  113.             padd(x,y,z);
  114.         else
  115.             padd(y,x,z);
  116.         sz=MINUS;
  117.         break;
  118.     case 1:
  119.         if (xgty<=0)
  120.         {
  121.             psub(y,x,z);
  122.             sz=PLUS;
  123.         }
  124.         else
  125.         {
  126.             psub(x,y,z);
  127.             sz=MINUS;
  128.         }
  129.         break;
  130.     case 2:
  131.         if (xgty>=0)
  132.         {
  133.             psub(x,y,z);
  134.             sz=PLUS;
  135.         }
  136.         else
  137.         {
  138.             psub(y,x,z);
  139.             sz=MINUS;
  140.         }
  141.         break;
  142.     case 3:
  143.         if (xgty>=0)
  144.             padd(x,y,z);
  145.         else
  146.             padd(y,x,z);
  147.         sz=PLUS;
  148.         break;
  149.     }
  150.     if (sz<0) z[0]=(-z[0]);         /* set sign of result         */
  151.     if (x!=z && sx<0) x[0]=(-x[0]); /* restore signs to operands  */
  152.     if (y!=z && y!=x && sy<0) y[0]=(-y[0]);
  153. }
  154.  
  155. void add(x,y,z)
  156. big x;
  157. big y;
  158. big z;
  159. {  /* add two signed big numbers together z=x+y */
  160.     if (ERNUM) return;
  161.     depth++;
  162.     trace[depth]=27;
  163.     if (TRACER) track();
  164.     select(x,PLUS,y,z);
  165.     depth--;
  166. }
  167.  
  168. void subtract(x,y,z)
  169. big x;
  170. big y;
  171. big z;
  172. { /* subtract two big signed numbers z=x-y */
  173.     if (ERNUM) return;
  174.     depth++;
  175.     trace[depth]=28;
  176.     if (TRACER) track();
  177.     select(x,MINUS,y,z);
  178.     depth--;
  179. }
  180.  
  181. void incr(x,n,z)
  182. big x;
  183. big z;
  184. small n;
  185. {  /* add int to big number: z=x+n */
  186.     if (ERNUM) return;
  187.     depth++;
  188.     trace[depth]=7;
  189.     if (TRACER) track();
  190.     convert(n,w0);
  191.     select(x,PLUS,w0,z);
  192.     depth--;
  193. }
  194.  
  195. void decr(x,n,z)
  196. big x;
  197. big z;
  198. small n;
  199. {  /* subtract int from big number: z=x-n */   
  200.     if (ERNUM) return;
  201.     depth++;
  202.     trace[depth]=8;
  203.     if (TRACER) track();
  204.     convert(n,w0);
  205.     select(x,MINUS,w0,z);
  206.     depth--;
  207. }
  208.