]>
Commit | Line | Data |
---|---|---|
bc9f6000 UD |
1 | /* Compute remainder and a congruent to the quotient. |
2 | Copyright (C) 1997 Free Software Foundation, Inc. | |
3 | This file is part of the GNU C Library. | |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include <math.h> | |
22 | ||
23 | #include "math_private.h" | |
24 | ||
25 | ||
26 | static const double zero = 0.0; | |
27 | ||
28 | ||
29 | double | |
30 | __remquo (double x, double y, int *quo) | |
31 | { | |
34b402e5 UD |
32 | int32_t hx,hy; |
33 | u_int32_t sx,lx,ly; | |
34 | int cquo, qs; | |
bc9f6000 UD |
35 | |
36 | EXTRACT_WORDS (hx, lx, x); | |
34b402e5 | 37 | EXTRACT_WORDS (hy, ly, y); |
bc9f6000 | 38 | sx = hx & 0x80000000; |
34b402e5 UD |
39 | qs = sx ^ (hy & 0x80000000); |
40 | hy &= 0x7fffffff; | |
bc9f6000 UD |
41 | hx &= 0x7fffffff; |
42 | ||
43 | /* Purge off exception values. */ | |
34b402e5 UD |
44 | if ((hy | ly) == 0) |
45 | return (x * y) / (x * y); /* y = 0 */ | |
bc9f6000 | 46 | if ((hx >= 0x7ff00000) /* x not finite */ |
34b402e5 UD |
47 | || ((hy >= 0x7ff00000) /* p is NaN */ |
48 | && (((hy - 0x7ff00000) | ly) != 0))) | |
49 | return (x * y) / (x * y); | |
bc9f6000 | 50 | |
34b402e5 | 51 | if (hy <= 0x7fbfffff) |
63551311 | 52 | x = __ieee754_fmod (x, 8 * y); /* now x < 8y */ |
bc9f6000 | 53 | |
34b402e5 | 54 | if (((hx - hy) | (lx - ly)) == 0) |
bc9f6000 UD |
55 | { |
56 | *quo = qs ? -1 : 1; | |
57 | return zero * x; | |
58 | } | |
59 | ||
60 | x = fabs (x); | |
34b402e5 | 61 | y = fabs (y); |
bc9f6000 UD |
62 | cquo = 0; |
63 | ||
63551311 | 64 | if (x >= 4 * y) |
bc9f6000 | 65 | { |
34b402e5 | 66 | x -= 4 * y; |
63551311 UD |
67 | cquo += 4; |
68 | } | |
69 | if (x >= 2 * y) | |
70 | { | |
71 | x -= 2 * y; | |
bc9f6000 UD |
72 | cquo += 2; |
73 | } | |
34b402e5 | 74 | if (x >= y) |
bc9f6000 | 75 | { |
63551311 | 76 | x -= y; |
bc9f6000 UD |
77 | ++cquo; |
78 | } | |
79 | ||
34b402e5 | 80 | if (hy < 0x00200000) |
bc9f6000 | 81 | { |
34b402e5 | 82 | if (x + x > y) |
bc9f6000 | 83 | { |
34b402e5 | 84 | x -= y; |
d705269e | 85 | ++cquo; |
34b402e5 | 86 | if (x + x >= y) |
63551311 UD |
87 | { |
88 | x -= y; | |
89 | ++cquo; | |
90 | } | |
bc9f6000 UD |
91 | } |
92 | } | |
93 | else | |
94 | { | |
34b402e5 | 95 | double y_half = 0.5 * y; |
63551311 | 96 | if (x > y_half) |
bc9f6000 | 97 | { |
34b402e5 | 98 | x -= y; |
d705269e | 99 | ++cquo; |
34b402e5 | 100 | if (x >= y_half) |
63551311 UD |
101 | { |
102 | x -= y; | |
103 | ++cquo; | |
104 | } | |
bc9f6000 UD |
105 | } |
106 | } | |
107 | ||
108 | *quo = qs ? -cquo : cquo; | |
109 | ||
63551311 UD |
110 | if (sx) |
111 | x = -x; | |
bc9f6000 UD |
112 | return x; |
113 | } | |
114 | weak_alias (__remquo, remquo) | |
5649a1d6 UD |
115 | #ifdef NO_LONG_DOUBLE |
116 | strong_alias (__remquo, __remquol) | |
117 | weak_alias (__remquo, remquol) | |
118 | #endif |