home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / yabbawhap / part03 / percent.c < prev    next >
C/C++ Source or Header  |  1991-10-09  |  2KB  |  72 lines

  1. /* Placed into the public domain by Daniel J. Bernstein. */
  2.  
  3. #include "percent.h"
  4.  
  5. #define MAXULONG ((unsigned long) (-1))
  6.  
  7. #define HENCE(x) ;
  8.  
  9. #define ENOUGH(a) { long p = (a); if (q) { \
  10. if (q - 1 > limit / 100) return limit; \
  11. if ((q - 1) * 100 > limit - 100) return limit; \
  12. if (q * 100 > limit - p) return limit; \
  13. return (long) (p + q*100); } else if (p > limit) return limit; else return p; }
  14.  
  15. long percent(a,b,limit)
  16. unsigned long a;
  17. unsigned long b;
  18. long limit;
  19. {
  20.  unsigned long q;
  21.  unsigned long s;
  22.  unsigned long t;
  23.  
  24.  q = 0;
  25.  
  26.  if (b == 0)
  27.    ENOUGH(100)
  28.  HENCE(b > 0);
  29.  
  30.  if (b < MAXULONG - 200)
  31.    if (a < (MAXULONG / 200) - (b / 200) - 1) /* cannot go below 0 */
  32.      ENOUGH((100 * a + (b / 2)) / b) /* cannot overflow */
  33.  HENCE(a + (b / 200) + 1 >= MAXULONG / 200);
  34.  /* How often will a and b be more than 21 million on a 32-bit machine? */
  35.  
  36.  if (a < b / 200)
  37.    ENOUGH(0)
  38.  HENCE(a >= b / 200);
  39.  HENCE(a + a + 1 >= MAXULONG / 200);
  40.  
  41.  if (a >= b)
  42.   {
  43.    q = a / b;
  44.    HENCE(a - q * b < b);
  45.    a -= q * b;
  46.   }
  47.  HENCE(a < b);
  48.  
  49.  t = 0; s = a;
  50.  /* now s is a mod b, t is floor(a/b) */
  51.  if (s >= b - a) { t += 1; s -= b - a; } else { s += a; }
  52.  /* now s is 2a mod b, t is floor(2a/b) */
  53.  if (s >= b - a) { t += 1; s -= b - a; } else { s += a; }
  54.  /* now s is 3a mod b, t is floor(3a/b) */
  55.  if (s >= b - s) { t += t + 1; s -= b - s; } else { t += t; s += s; }
  56.  /* now s is 6a mod b, t is floor(6a/b) */
  57.  if (s >= b - s) { t += t + 1; s -= b - s; } else { t += t; s += s; }
  58.  /* now s is 12a mod b, t is floor(12a/b) */
  59.  if (s >= b - s) { t += t + 1; s -= b - s; } else { t += t; s += s; }
  60.  /* now s is 24a mod b, t is floor(24a/b) */
  61.  if (s >= b - a) { t += 1; s -= b - a; } else { s += a; }
  62.  /* now s is 25a mod b, t is floor(25a/b) */
  63.  if (s >= b - s) { t += t + 1; s -= b - s; } else { t += t; s += s; }
  64.  /* now s is 50a mod b, t is floor(50a/b) */
  65.  if (s >= b - s) { t += t + 1; s -= b - s; } else { t += t; s += s; }
  66.  /* now s is 100a mod b, t is floor(100a/b) */
  67.  if (s >= b - (b/2)) { t += 1; s -= b - (b/2); } else { s += (b/2); }
  68.  
  69.  ENOUGH(t)
  70.  /* whew. */
  71. }
  72.