home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_02 / 1002074a < prev    next >
Text File  |  1991-12-10  |  22KB  |  857 lines

  1. Frederick W. Hegeman
  2. 1022 South St.
  3. Rapid City, SD 57701
  4. (605) 343-7014
  5.  
  6. Code to accompany article on factorial-base math
  7. ARITHMETIC IN FACTORIAL-BASE
  8.  
  9. /* Listing 1. */
  10. /* facbase.c -- arithmetic in factorial-base */
  11.  
  12. #include <stdio.h>
  13.  
  14. #ifndef TRUE
  15. #define TRUE 1
  16. #endif
  17. #ifndef FALSE
  18. #define FALSE 0
  19. #endif
  20.  
  21. #define DEBUG TRUE  /* include RPN calculator */
  22. #define PLUS FALSE  /* sign values */
  23. #define MINUS TRUE
  24. #define MAXFBINTEGER 100    /* <= 180 for arrays of ints */
  25. #define MAXFBFRACTION 100   /* <= 180 for arrays of ints */
  26. #define HIGHGUARD MAXFBINTEGER + 1
  27. #define LOWGUARD MAXFBFRACTION + 1
  28. #define ARRAYSIZE 1 + HIGHGUARD + LOWGUARD
  29.  
  30. /* two constants in the proper format */
  31. int zero[ARRAYSIZE] = { PLUS, 0 };  /* signed 0 */
  32. int one[ARRAYSIZE] = { PLUS, 1, 0 };
  33.  
  34. /* a flag set by divide() while "estimating" */
  35. int nowarning = FALSE;
  36. /* assign the value of one array to a second array */
  37. assignto(dest, source)
  38. int *dest;
  39. int *source;
  40. {
  41.     int i;
  42.  
  43.     for(i = 0; i < ARRAYSIZE; i++)
  44.         dest[i] = source[i];
  45. }
  46.  
  47. /* z = abs(x) */
  48. absolute(x, z)
  49. int *x;
  50. int *z;
  51. {
  52.     if(z != x)      /* if not changing in place */
  53.         assignto(z, x); /* copy */
  54.     z[0] = PLUS;    /* force positive */
  55. }
  56.  
  57. /* Assign unary negative of x to z */
  58. negative(x, z)
  59. int *x;
  60. int *z;
  61. {
  62.     int sign;
  63.  
  64.     sign = (x[0] == PLUS) ? MINUS : PLUS;
  65.     if(z != x)      /*if not changing in place */
  66.         assignto(z, x); /* copy */
  67.     z[0] = sign;    /* change sign */
  68. }
  69.  
  70. /* compare 2 factorial-base numbers for |x| > |y| */
  71. int greaterthan(x, y)
  72. int *x;
  73. int *y;
  74. {
  75.     int i, j;
  76.  
  77.     /*
  78.      * check the integer part first,
  79.      * largest subscript to smallest
  80.      */
  81.     for(i = MAXFBINTEGER; (x[i] == y[i]) && (i > 1); --i)
  82.         ;
  83.     if(i != 0)
  84.     {
  85.         if(x[i] > y[i])
  86.             return(TRUE);
  87.         if(x[i] < y[i])
  88.             return(FALSE);
  89.     }
  90.     /*
  91.      * The integer portions are equal,
  92.      * continue with the fractional part,
  93.      * smallest subscript to largest.
  94.      */
  95.     for(i = HIGHGUARD + 1, j = 1;
  96.         (x[i] == y[i]) && (j < MAXFBFRACTION - 1);
  97.         i++, j++)
  98.             ;
  99.     return((x[i] > y[i]) ? TRUE : FALSE);
  100. }
  101.  
  102. /* Compare 2 factorial-base numbers for |x| < |y| */
  103. int lessthan(x, y)
  104. int *x;
  105. int *y;
  106. {
  107.     int i, j;
  108.  
  109.     /*
  110.      * check the integer part first,
  111.      * largest subscript to smallest
  112.      */
  113.     for(i = MAXFBINTEGER; (x[i] == y[i]) && (i > 1); --i)
  114.         ;
  115.     if(i != 0)
  116.     {
  117.         if(x[i] < y[i])
  118.             return(TRUE);
  119.         if(x[i] > y[i])
  120.             return(FALSE);
  121.     }
  122.     /*
  123.      * The integer portions are equal,
  124.      * continue with the fractional part,
  125.      * smallest subscript to largest.
  126.      */
  127.     for(i = HIGHGUARD + 1, j = 1;
  128.         (x[i] == y[i]) && (j < MAXFBFRACTION - 1);
  129.         i++, j++)
  130.             ;
  131.     return((x[i] < y[i]) ? TRUE : FALSE);
  132. }
  133.  
  134. /* Compare 2 factorial-base numbers for |x| == |y| */
  135. int equalto(x, y)
  136. int *x;
  137. int *y;
  138. {
  139.     int i;
  140.  
  141.     /*
  142.      * Check the whole array except the sign
  143.      * -- order doesn't matter.
  144.      */
  145.     for(i = ARRAYSIZE-1; (x[i] == y[i]) && (i > 1); --i)
  146.         ;
  147.     return((x[i] == y[i]) ? TRUE : FALSE);
  148. }
  149.  
  150. /*
  151.  * "Normalize" a factorial-base number.  All of the
  152.  * arithmetic functions call this routine to handle
  153.  * carrys and borrows.  A factorial-base number has a
  154.  * proper form where every factorial position in its
  155.  * integer part has a value between 0 and the the
  156.  * magnitude of its position and every factorial position
  157.  * in its fractional part has a value between 0 and one
  158.  * less than the magnitude of its position.
  159.  */
  160. normalize(n)
  161. int *n;
  162. {
  163.     int i, j;
  164.     int *x;
  165.  
  166.     x = &n[HIGHGUARD];
  167.     /*
  168.      * First, check for loss of precision
  169.      * during multiplication or division.
  170.      */
  171.     if(x[LOWGUARD])
  172.     {
  173.         if(nowarning != TRUE)
  174.             fputs("UNDERFLOW\n", stderr);
  175.         x[LOWGUARD] = 0;
  176.     }
  177.     /*
  178.      * Now, work the fractional part first,
  179.      * largest subscript to smallest.
  180.      * The subscript j is the factorial position
  181.      * being put into proper form.
  182.      */
  183.     for(j = MAXFBFRACTION, i = j - 1; i >= 1; --i, --j)
  184.     {
  185.         /* if(x[j] >= j) carry */
  186.         x[i] += (x[j] / j);
  187.         x[j] %= j;
  188.         if(x[j] < 0)    /* borrow */
  189.         {
  190.             x[i] -= 1;
  191.             /* modulo= j */
  192.             x[j] += j;  /* make positive */
  193.         }
  194.     }
  195.     /* shift any carry to integer part & clear carry */
  196.     n[1] += x[1];
  197.     x[1] = 0;
  198.     /*
  199.      * Now, normalize the integer part,
  200.      * working from smallest subscript to largest.
  201.      * The subscript i is the factorial position
  202.      * being put into proper form.
  203.      */
  204.     x = n;
  205.     for(i = 1, j = 2; i <= MAXFBINTEGER; i++, j++)
  206.     {
  207.         /* if(x[i] >= j) carry */
  208.         x[j] += (x[i] / j);
  209.         x[i] %= j;
  210.         if(x[i] < 0)    /* borrow */
  211.         {
  212.             x[j] -= 1;
  213.             x[i] += j;
  214.         }
  215.     }
  216.     if(x[i])    /* if an entry in x[HIGHGUARD] */
  217.     {
  218.         fputs("OVERFLOW\n", stderr);
  219.         x[i] = 0;
  220.     }
  221. }
  222.  
  223. /* Add y to x, put result in z */
  224. add(x, y, z)
  225. int *x;
  226. int *y;
  227. int *z;
  228. {
  229.     int sign, i;
  230.     int copy[ARRAYSIZE];
  231.  
  232.     if(x[0] != y[0])    /* if different signs */
  233.     {
  234.         if(y[0] == MINUS)
  235.         {
  236.             /*
  237.              * Change the sign of y
  238.              * and subtract y from x.
  239.              */
  240.             negative(y, copy);
  241.             subtract(x, copy, z);
  242.         }
  243.         else
  244.         {
  245.             /*
  246.              * Change the sign of x
  247.              * and subtract x from y.
  248.              */
  249.             negative(x, copy);
  250.             subtract(y, copy, z);
  251.         }
  252.     }
  253.     else
  254.     {
  255.         sign = x[0];    /* save the sign */
  256.         for(i = ARRAYSIZE - 1; i > 0; --i)
  257.             z[i] = x[i] + y[i];
  258.         z[0] = sign;
  259.         normalize(z);
  260.     }
  261. }
  262.  
  263. /* Subtract y from x, put result in z */
  264. subtract(x, y, z)
  265. int *x;
  266. int *y;
  267. int *z;
  268. {
  269.     int sign, i;
  270.     int copy[ARRAYSIZE];
  271.  
  272.     if(x[0] != y[0])    /* if signs are different */
  273.     {
  274.         negative(y, copy);  /* change sign of y */
  275.         sign = x[0];        /* save sign of x */
  276.         add(x, copy, z);
  277.         z[0] = sign;
  278.         return;
  279.     }
  280.     else if(y[0] == MINUS)  /* (-x) - (-y) */
  281.     {
  282.         /* if(abs(y) < abs(x)) sign = MINUS */
  283.         sign = lessthan(y, x);
  284.     }
  285.     else
  286.     {
  287.         /* if(x < y) sign = MINUS */
  288.         sign = lessthan(x, y);
  289.     }
  290.     /* Subtract based on the absolute values */
  291.     if(lessthan(x, y))
  292.     {
  293.         for(i = ARRAYSIZE - 1; i > 0; --i)
  294.             z[i] = y[i] - x[i];
  295.     }
  296.     else
  297.     {
  298.         for(i = ARRAYSIZE - 1; i > 0; --i)
  299.             z[i] = x[i] - y[i];
  300.     }
  301.     z[0] = sign;
  302.     normalize(z);
  303. }
  304.  
  305. /*
  306.  * Multiply factorial-base x by integer y, result in z.
  307.  * Utility routine called by multiply(), divide(),
  308.  * atofact(), fractoa(), and facttoa(), and always
  309.  * with a positive value for y
  310.  */
  311. multfbyi(x, y, z)
  312. int *x;
  313. int y;
  314. int *z;
  315. {
  316.     int i;
  317.  
  318.     for(i = ARRAYSIZE - 1; i > 0; --i)
  319.         z[i] = x[i] * y;
  320.     normalize(z);
  321. }
  322.  
  323. /*
  324.  * Divide factorial-base x by integer y, result in z.
  325.  * Utility routine called by multiply(), divide(),
  326.  * and facttoa(), and always with a positive y
  327.  */
  328. divfbyi(x, y, z)
  329. int *x;
  330. int y;
  331. int *z;
  332. {
  333.     int i, j, carry, part;
  334.  
  335.     carry = 0;
  336.     /*
  337.      * Work the integer part first,
  338.      * from the largest subscript to smallest
  339.      */
  340.     for(i = MAXFBINTEGER, j = i + 1; i >= 1; --i, --j)
  341.     {
  342.         part = x[i] + carry * j;
  343.         carry = part % y;
  344.         z[i] = part / y;
  345.     }
  346.     /*
  347.      * Now, work the fractional part,
  348.      * from the smallest subscript to largest
  349.      */
  350.     for(i = HIGHGUARD + 1, j = 1;
  351.         j <= MAXFBFRACTION; i++, j++)
  352.     {
  353.         part = x[i] + carry * j;
  354.         carry = part % y;
  355.         z[i] = part / y;
  356.     }
  357.     /*
  358.      * propogate any carry into z[LOWGUARD]
  359.      * to mark underflow and loss of precision
  360.      */
  361.     z[i] = carry * j;
  362.     normalize(z);
  363. }
  364.  
  365. /*
  366.  * Multiply factorial-base x by factorial-base y,
  367.  * assign result to z.  Uses the identity
  368.  * number * (integer + fraction)
  369.  *  == (number * integer) + (number * fraction)
  370.  */
  371. multiply(x, y, z)
  372. int *x;
  373. int *y;
  374. int *z;
  375. {
  376.     int i, j, k, sign;
  377.     int partial[ARRAYSIZE];
  378.     int temp[ARRAYSIZE];
  379.     int copy[ARRAYSIZE];
  380.  
  381.     if(x[0] != y[0])    /* if signs different */
  382.         sign = MINUS;
  383.     else
  384.         sign = PLUS;
  385.  
  386.     assignto(partial, zero);    /* Initialize result */
  387.     /*
  388.      * Work the integer portion first,
  389.      * from smallest subscript to largest
  390.      */
  391.     absolute(x, copy);  /* copy = abs(x) */
  392.     /* first, find largest subscript k where y[k] != 0 */
  393.     for(k = MAXFBINTEGER; (k > 0) && (y[k] == 0); --k)
  394.         ;
  395.     for(i = 1; i <= k; i++)
  396.     {
  397.         /* first shift copy by factorial position */
  398.         multfbyi(copy, i, copy);
  399.         if(y[i])    /* don't bother multiplying by 0 */
  400.         {
  401.             /* multiply by factorial digit */
  402.             multfbyi(copy, y[i], temp);
  403.             add(partial, temp, partial);
  404.         }
  405.     }
  406.  
  407.     /* now work fraction part */
  408.     assignto(copy, x);  /* reset copy */
  409.     /* find largest subscript k where y[k] != 0 */
  410.     for(k = ARRAYSIZE - 1; (k > HIGHGUARD + 1) && (y[k] == 0); --k)
  411.         ;
  412.     for(i = HIGHGUARD + 2, j = 2; i <= k; i++, j++)
  413.     {
  414.         /* first shift copy by factorial position */
  415.         divfbyi(copy, j, copy);
  416.         if(y[i])    /* don't bother multiplying by zero */
  417.         {
  418.             /* multiply by factorial digit */
  419.             multfbyi(copy, y[i], temp);
  420.             add(partial, temp, partial);
  421.         }
  422.     }
  423.     partial[0] = sign;
  424.     assignto(z, partial);
  425. }
  426.  
  427. /*
  428.  * Divide factorial-base x by factorial-base y, store
  429.  * result in z.  Uses blackboard style long division.
  430.  */
  431. divide(x, y, z)
  432. int *x;
  433. int *y;
  434. int *z;
  435. {
  436.     int i, j, sign;
  437.     int estimate;
  438.     int copyx[ARRAYSIZE];
  439.     int copyy[ARRAYSIZE];
  440.     int temp[ARRAYSIZE];
  441.     int partial[ARRAYSIZE];
  442.  
  443.     if(x[0] != y[0])    /* if signs different */
  444.         sign = MINUS;
  445.     else
  446.         sign = PLUS;
  447.     absolute(x, copyx);
  448.     absolute(y, copyy);
  449.     assignto(partial, copyx);
  450.     assignto(temp, copyy);
  451.     /*
  452.      * First, estimate the integer part of result by
  453.      * driving y to 1.xxx.  Division is VERY slow, so
  454.      * the extra time spent to identify special cases
  455.      * is well worth it.
  456.      */
  457.     if(equalto(temp, zero))
  458.     {
  459.         /* division by zero fault */
  460.         /* not handled here */
  461.         return;
  462.     }
  463.     else if(lessthan(partial, temp))
  464.     {
  465.         assignto(partial, zero);    /* integer part 0 */
  466.     }
  467.     else if(lessthan(one, temp))
  468.     {
  469.         /*
  470.          * This could cause a spurious UNDERFLOW
  471.          * message even though the final result
  472.          * would be exact, so we set a flag to
  473.          * suppress the warning.
  474.          */
  475.         nowarning = TRUE;
  476.         while(lessthan(one, temp))
  477.         {
  478.             divfbyi(partial, 2, partial);
  479.             divfbyi(temp, 2, temp);
  480.         }
  481.         multfbyi(partial, 2, partial);
  482.         nowarning = FALSE;  /* reset flag */
  483.     }
  484.     else if(lessthan(temp, one))
  485.     {
  486.         while(lessthan(temp, one))
  487.         {
  488.             multfbyi(partial, 2, partial);
  489.             multfbyi(temp, 2, temp);
  490.         }
  491.     }
  492.     else    /* division by 1 or -1 */
  493.     {
  494.         assignto(z, x);
  495.         z[0] = sign;
  496.         return;
  497.     }
  498.     /* Now, delete fractional part of estimate */
  499.     for(i = HIGHGUARD + 1; i < ARRAYSIZE; i++)
  500.         partial[i] = 0;
  501.     multiply(copyy, partial, temp);
  502.     while(greaterthan(temp, copyx))
  503.     {
  504.         subtract(partial, one partial);
  505.         subtract(temp, copyy, temp);
  506.     }
  507.     subtract(copyx, temp, copyx);
  508.     multfbyi(copyx, 2, copyx);
  509.     /* partial now holds integer part of result */
  510.  
  511.     /*
  512.      * Now, proceed by long division to divide by
  513.      * the fractional part -- using the subscript
  514.      * (less 1) as the estimate at each position
  515.      */
  516.     for(i = HIGHGUARD + 2, j = 2;
  517.         !equalto(copyx, zero) && (i < ARRAYSIZE);
  518.         i++)
  519.     {
  520.         estimate = j - 1;
  521.         do {
  522.             multfbyi(copyy, estimate--, temp);
  523.         } while(greaterthan(temp, copyx));
  524.         subtract(copyx, temp, copyx);
  525.         partial[i] = ++estimate;
  526.         multfbyi(copyx, ++j, copyx);
  527.     }
  528.     normalize(partial);
  529.     if(sign == MINUS)
  530.         partial[0] = MINUS;
  531.     assignto(z, partial);
  532. }
  533.  
  534. /*
  535.  * ASCII to factorial-base conversion
  536.  * Just like ASCII to binary conversion!
  537.  */
  538. atofact(s, z)
  539. char s[];
  540. int *z;
  541. {
  542.     int i, j, sign;
  543.     int ipart[ARRAYSIZE];
  544.     int fpart[ARRAYSIZE];
  545.  
  546.     assignto(ipart, zero);
  547.     assignto(fpart, zero);
  548.     i = 0;
  549.     sign = PLUS;
  550.     while(s[i] == ' ' || s[i] == '\t')
  551.         i++;
  552.     if(s[i] == '-' || s[i] == '+')
  553.     {
  554.         if(s[i++] == '-')
  555.             sign = MINUS;
  556.     }
  557.     for( ; s[i] >= '0' && s[i] <= '9'; i++)
  558.     {
  559.         multfbyi(ipart, 10, ipart);
  560.         ipart[1] = s[i] - '0';
  561.         normalize(ipart);
  562.     }
  563.     if(s[i] == '.')
  564.     {
  565.         i++;
  566.         j = 0;
  567.         for( ; s[i] >= '0' && s[i] <= '9'; i++)
  568.         {
  569.             multfbyi(fpart, 10, fpart);
  570.             ++j;
  571.             fpart[1] = s[i] - '0';
  572.             normalize(fpart);
  573.         }
  574.         while(j--)
  575.             divfbyi(fpart, 10, fpart);
  576.         add(ipart, fpart, ipart);
  577.     }
  578.     ipart[0] = sign;
  579.     assignto(z, ipart);
  580. }
  581.  
  582. /*
  583.  * Convert the fractional part of x to ASCII.
  584.  * Up to count characters go to stdout.
  585.  */
  586. fractoa(x, count)
  587. int *x;
  588. int count;
  589. {
  590.     int i;
  591.     int temp[ARRAYSIZE];
  592.  
  593.     assignto(temp, x);
  594.     for(i = 1; i <= MAXFBINTEGER; i++)
  595.         temp[i] = 0;    /* erase integer part */
  596.     temp[0] = PLUS;     /* always positive */
  597.     if(equalto(temp, zero))
  598.         return; /* no fractional part to print out */
  599.     putchar('.');
  600.     while(count-- && !equalto(temp, zero))
  601.     {
  602.         multfbyi(temp, 10, temp);
  603.         putchar('0' + 6 * temp[3] + 2 * temp[2] + temp[1]);
  604.         /* Now erase the integer part */
  605.         temp[3] = temp[2] = temp[1] = 0;
  606.     }
  607. }
  608.  
  609. /*
  610.  * CAUTION -- altering the size of outbuff requires
  611.  * some art.  If MAXFBINTEGER == 100, it must be
  612.  * large enough to hold the 160 decimal digit integer
  613.  * 9.4259 * 10^159.  If MAXFBINTEGER == 180, it must
  614.  * be large enough for the 332 decimal digit integer
  615.  * 3.6362 * 10^331.  If you want to deal with really
  616.  * big numbers and increase MAXFBINTEGER, you'll have
  617.  * to give some thought as to how large the conversion
  618.  * buffer is going to have to be.
  619.  */
  620. /* Allow a little slack */
  621. char outbuff[MAXFBINTEGER*2] = { 0 };
  622. int outptr; /* Actually an index and not a "ptr" */
  623.  
  624. /*
  625.  * Factorial-base to ASCII conversion, integer
  626.  * part and up to count characters of fractional
  627.  * portion go to stdout.
  628.  */
  629. facttoa(x, count)
  630. int *x;
  631. int count;
  632. {
  633.     int i, j, sign;
  634.     int temp[ARRAYSIZE];
  635.     int val[ARRAYSIZE];
  636.  
  637.     outptr = 0;
  638.     assignto(val, zero);
  639.     assignto(temp, x);
  640.     if((sign = temp[0]) == MINUS)
  641.     {
  642.         temp[0] = PLUS;
  643.         putchar('-');
  644.     }
  645.     for(i = ARRAYSIZE - 1; i > HIGHGUARD; --i)
  646.         temp[i] = 0;    /* erase fractional part */
  647.     while(!equalto(temp, zero))
  648.     {
  649.         divbyi(temp, 10, temp);
  650.         for(i = HIGHGUARD + 2, j = 1; j <= 4; i++, j++)
  651.         {
  652.             val[i] = temp[i];
  653.         }
  654.         multfbyi(val, 10, val);
  655.         outbuff[outptr++] =
  656.             '0' + 6 * val[3] + 2 * val[2] + val[1];
  657.         val[3] = val[2] = val[1] = 0;
  658.         /* Now erase fractional portion of temp */
  659.         temp[i-1] = temp[i-2] = temp[i-3] = temp[i-4] = 0;
  660.     }
  661.     if(outptr == 0) /* if no integer part */
  662.         putchar('0');
  663.     else
  664.     {
  665.         while(outptr--)
  666.             putchar(outbuff[outptr]);
  667.     }
  668.     fractoa(x, count);  /* to print fractional portion */
  669.     putchar('\n');
  670. }
  671.  
  672. /* Remainder of file is RPN calculator & display */
  673. #ifdef DEBUG
  674. /*
  675.  * Print a factorial-base number in factorial-base.
  676.  * "digits" are printed between '<' and '>',
  677.  * output goes to stdout.
  678.  */
  679. facprint(x)
  680. int *x;
  681. {
  682.     int i, j;
  683.  
  684.     if(x[0] == MINUS)
  685.         printf("-");
  686.     /* Delete any leading zeroes */
  687.     for(i = MAXFBINTEGER; i >= 1; i--)
  688.     {
  689.         if(x[i] != 0)
  690.             break;
  691.     }
  692.     /* Print any integer portion */
  693.     for( ; i >= 2; )
  694.         printf("<%d>", x[i--]);
  695.     /* Make sure to print at least one digit */
  696.     printf("<%d>", x[1]);
  697.     printf(".");
  698.     /*
  699.      * Print fractional part, deleting any trailing
  700.      * zeroes but printing at least one digit
  701.      */
  702.     i = HIGHGUARD + 2;  /* start at 2! */
  703.     printf("<%d>", x[i++]);
  704.     for(j = 0; i < ARRAYSIZE; i++)
  705.     {
  706.         if(x[i] == 0)
  707.             j += 1;
  708.         else
  709.         {
  710.             while(j)
  711.             {
  712.                 printf("<0>");
  713.                 --j;
  714.             }
  715.             printf("<%d>", x[i]);
  716.         }
  717.     }
  718.     printf("\n");
  719. }
  720.  
  721. /*
  722.  * A simple but VERY slow reverse Polish calculator.
  723.  * Commands +, -, *, /, D to print in decimal,
  724.  * F to print in factorial, C to clear the stack,
  725.  * S to display the whole stack in decimal,
  726.  * a decimal number to use as an operand,
  727.  * only 1 operator or operand per line!!
  728.  */
  729.  
  730. #define IPSIZE 256
  731. char input[IPSIZE];
  732. #define STACKSIZE 8
  733. int stack[STACKSIZE][ARRAYSIZE];
  734.  
  735. main(argc, argv)
  736. int argc;
  737. char *argv[];
  738. {
  739.     int x, i, prompt, depth;
  740.  
  741.     prompt = (argc > 1) ? TRUE : FALSE;
  742.     depth = 0;
  743.     for( ; ; )
  744.     {
  745.         if(prompt)
  746.             printf(%d> ", depth);
  747.         if(fgets(input, IPSIZE, stdin) == NULL)
  748.             break;
  749.         switch(x = input[0])
  750.         {
  751.         case 'c':   /* clear the stack */
  752.         case 'C':   depth = 0;
  753.                     continue;
  754.         case 'f':   /* print top of stack in factorial */
  755.         case 'F':   if(depth < 1)
  756.                     {
  757.                         printf("empty stack\n");
  758.                         continue;
  759.                     }
  760.                     printf("%d: ", depth - 1);
  761.                     facprint(&stack[depth-1][0]);
  762.                     continue;
  763.         case'd':    /* print top of stack in decimal */
  764.         case 'D':   if(depth < 1)
  765.                     {
  766.                         printf("empty stack\n");
  767.                         continue;
  768.                     }
  769.                     printf("%d: ", depth - 1);
  770.                     facttoa(&stack[depth-1][0], 50);
  771.                     continue;
  772.         case 's':   /* display contents of stack */
  773.         case 'S':   if(depth < 1)
  774.                     {
  775.                         printf("empty stack\n");
  776.                         continue;
  777.                     }
  778.                     for(i = 0; i < depth; i++)
  779.                     {
  780.                         printf("%d: ", i);
  781.                         facttoa(&stack[i][0], 50);
  782.                     }
  783.                     continue;
  784.         case '+':   if(depth < 2)
  785.                     {
  786.                         printf("stack will underflow\n");
  787.                         continue;
  788.                     }
  789.                     add(&stack[depth-2][0],
  790.                         &stack[depth-1][0],
  791.                         &stack[depth-2][0]);
  792.                     --depth;
  793.                     continue;
  794.         case '/':   if(depth < 2)
  795.                     {
  796.                         printf("stack will underflow\n");
  797.                         continue;
  798.                     }
  799.                     if(equalto(&stack[depth-1][0], zero))
  800.                     {
  801.                         printf("division by zero\n");
  802.                         /* allow the 0 to be discarded */
  803.                     }
  804.                     else
  805.                     {
  806.                         divide(&stack[depth-2][0],
  807.                             &stack[depth-1][0],
  808.                             &stack[depth-2][0]);
  809.                     }
  810.                     --depth;
  811.                     continue;
  812.         case '*':   if(depth < 2)
  813.                     {
  814.                         printf("stack will underflow\n");
  815.                         continue;
  816.                     }
  817.                     multiply(&stack[depth-2][0],
  818.                         &stack[depth-1][0],
  819.                         &stack[depth-2][0]);
  820.                     --depth;
  821.                     continue;
  822.         case '-':   if(input[1] == '\n')
  823.                     {
  824.                         if(depth < 2)
  825.                         {
  826.                             printf(
  827.                              "stack will underflow\n");
  828.                             continue;
  829.                         }
  830.                         subtract(&stack[depth-2][0],
  831.                             &stack[depth-1][0],
  832.                             &stack[depth-2][0]);
  833.                         --depth;
  834.                         continue;
  835.                     }   /* else a negative number */
  836.                     else
  837.                         break;
  838.         default:    if(x != '-' && x != '.' &&
  839.                         (x < '0' || x > '9'))
  840.                     {
  841.                         printf("invalid entry\n");
  842.                         continue;
  843.                     }
  844.                     break;
  845.                     /* to convert and stack a number */
  846.         }
  847.         if(depth >= STACKSIZE)
  848.         {
  849.             printf("stack will overflow\n");
  850.             continue;
  851.         }
  852.         atofact(input, &stack[depth++][0]);
  853.         continue;
  854.     }
  855. }
  856. #endif
  857.