home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fontutils-0.6-base.tgz / fontutils-0.6-base.tar / fsf / fontutils / lib / fmod.c < prev    next >
C/C++ Source or Header  |  1992-03-25  |  4KB  |  146 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)fmod.c    5.2 (Berkeley) 6/1/90";
  22. #endif /* not lint */
  23.  
  24. /* fmod.c
  25.  *
  26.  * SYNOPSIS
  27.  *
  28.  *    #include <math.h>
  29.  *    double fmod(double x, double y)
  30.  *
  31.  * DESCRIPTION
  32.  *
  33.  *    The fmod function computes the floating-point remainder of x/y.
  34.  *
  35.  * RETURNS
  36.  *
  37.  *    The fmod function returns the value x-i*y, for some integer i
  38.  * such that, if y is nonzero, the result has the same sign as x and
  39.  * magnitude less than the magnitude of y.
  40.  *
  41.  * On a VAX or CCI,
  42.  *
  43.  *    fmod(x,0) traps/faults on floating-point divided-by-zero.
  44.  *
  45.  * On IEEE-754 conforming machines with "isnan()" primitive,
  46.  *
  47.  *    fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned.
  48.  *
  49.  */
  50. #include <math.h> /* changed from "mathimpl.h" --karl */
  51.  
  52. #if !defined(vax) && !defined(tahoe)
  53. extern int isnan(),finite();
  54. #endif    /* !defined(vax) && !defined(tahoe) */
  55. extern double frexp(),ldexp(),fabs();
  56.  
  57. #ifdef TEST_FMOD
  58. static double
  59. _fmod(x,y)
  60. #else    /* TEST_FMOD */
  61. double
  62. fmod(x,y)
  63. #endif    /* TEST_FMOD */
  64. double x,y;
  65. {
  66.     int ir,iy;
  67.     double r,w;
  68.  
  69.     if (y == (double)0
  70. #if 0 /* removed this --karl */
  71. #if !defined(vax) && !defined(tahoe)    /* per "fmod" manual entry, SunOS 4.0 */
  72.         || isnan(y) || !finite(x)
  73. #endif    /* !defined(vax) && !defined(tahoe) */
  74. #endif
  75.             )
  76.         return (x*y)/(x*y);
  77.  
  78.     r = fabs(x);
  79.     y = fabs(y);
  80.     (void)frexp(y,&iy);
  81.     while (r >= y) {
  82.         (void)frexp(r,&ir);
  83.         w = ldexp(y,ir-iy);
  84.         r -= w <= r ? w : w*(double)0.5;
  85.     }
  86.     return x >= (double)0 ? r : -r;
  87. }
  88.  
  89. #ifdef TEST_FMOD
  90. extern long random();
  91. extern double fmod();
  92.  
  93. #define    NTEST    10000
  94. #define    NCASES    3
  95.  
  96. static int nfail = 0;
  97.  
  98. static void
  99. doit(x,y)
  100. double x,y;
  101. {
  102.     double ro = fmod(x,y),rn = _fmod(x,y);
  103.     if (ro != rn) {
  104.         (void)printf(" x    = 0x%08.8x %08.8x (%24.16e)\n",x,x);
  105.         (void)printf(" y    = 0x%08.8x %08.8x (%24.16e)\n",y,y);
  106.         (void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro);
  107.         (void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn);
  108.         (void)printf("\n");
  109.     }
  110. }
  111.  
  112. main()
  113. {
  114.     register int i,cases;
  115.     double x,y;
  116.  
  117.     srandom(12345);
  118.     for (i = 0; i < NTEST; i++) {
  119.         x = (double)random();
  120.         y = (double)random();
  121.         for (cases = 0; cases < NCASES; cases++) {
  122.             switch (cases) {
  123.             case 0:
  124.                 break;
  125.             case 1:
  126.                 y = (double)1/y; break;
  127.             case 2:
  128.                 x = (double)1/x; break;
  129.             default:
  130.                 abort(); break;
  131.             }
  132.             doit(x,y);
  133.             doit(x,-y);
  134.             doit(-x,y);
  135.             doit(-x,-y);
  136.         }
  137.     }
  138.     if (nfail)
  139.         (void)printf("Number of failures: %d (out of a total of %d)\n",
  140.             nfail,NTEST*NCASES*4);
  141.     else
  142.         (void)printf("No discrepancies were found\n");
  143.     exit(0);
  144. }
  145. #endif    /* TEST_FMOD */
  146.