fmod-ieee: Work around test failures on OSF/1, mingw.
[gnulib.git] / lib / fmod.c
1 /* Remainder.
2    Copyright (C) 2011-2012 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include <math.h>
21
22 double
23 fmod (double x, double y)
24 {
25   if (isinf (y))
26     return x;
27   else
28     {
29       double q = - trunc (x / y);
30       double r = fma (q, y, x); /* = x + q * y, computed in one step */
31       /* Correct possible rounding errors in the quotient x / y.  */
32       if (y >= 0)
33         {
34           if (x >= 0)
35             {
36               /* Expect 0 <= r < y.  */
37               if (r < 0)
38                 q += 1, r = fma (q, y, x);
39               else if (r >= y)
40                 q -= 1, r = fma (q, y, x);
41             }
42           else
43             {
44               /* Expect - y < r <= 0.  */
45               if (r > 0)
46                 q -= 1, r = fma (q, y, x);
47               else if (r <= - y)
48                 q += 1, r = fma (q, y, x);
49             }
50         }
51       else
52         {
53           if (x >= 0)
54             {
55               /* Expect 0 <= r < - y.  */
56               if (r < 0)
57                 q -= 1, r = fma (q, y, x);
58               else if (r >= - y)
59                 q += 1, r = fma (q, y, x);
60             }
61           else
62             {
63               /* Expect y < r <= 0.  */
64               if (r > 0)
65                 q += 1, r = fma (q, y, x);
66               else if (r <= y)
67                 q -= 1, r = fma (q, y, x);
68             }
69         }
70       return r;
71     }
72 }