-
Notifications
You must be signed in to change notification settings - Fork 25
/
e_remainderl.c
100 lines (85 loc) · 2.52 KB
/
e_remainderl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* e_remainderl.c -- long double version of e_remainder.c.
* Conversion to long double by Ulrich Drepper,
* Cygnus Support, [email protected].
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_remainderl(x,p)
* Return :
* returns x REM p = x - [x/p]*p as if in infinite
* precise arithmetic, where [x/p] is the (infinite bit)
* integer nearest x/p (in half way case choose the even one).
* Method :
* Based on fmod() return x-[x/p]chopped*p exactlp.
*/
#ifndef __FDLIBM_H__
#include "fdlibm.h"
#endif
#ifndef __NO_LONG_DOUBLE_MATH
#ifndef __have_fpu_remainder
long double __ieee754_remainderl(long double x, long double p)
{
uint32_t sx, sex, sep, x0, x1, p0, p1;
long double p_half;
static const long double zero = 0.0;
GET_LDOUBLE_WORDS(sex, x0, x1, x);
GET_LDOUBLE_WORDS(sep, p0, p1, p);
sx = sex & IC(0x8000);
sep &= IEEE854_LONG_DOUBLE_MAXEXP;
sex &= IEEE854_LONG_DOUBLE_MAXEXP;
/* purge off exception values */
if ((sep | p0 | p1) == 0)
return (x * p) / (x * p); /* p = 0 */
if ((sex == IEEE854_LONG_DOUBLE_MAXEXP) || /* x not finite */
((sep == IEEE854_LONG_DOUBLE_MAXEXP) && /* p is NaN */
(((p0 & IC(0x7fffffff)) | p1) != 0)))
return (x * p) / (x * p);
if (sep < (IEEE854_LONG_DOUBLE_MAXEXP - 1))
x = __ieee754_fmodl(x, p + p); /* now x < 2p */
if (((sex - sep) | ((x0 - p0) & IC(0x7fffffff)) | (x1 - p1)) == 0)
return zero * x;
x = __ieee754_fabsl(x);
p = __ieee754_fabsl(p);
if (sep < 0x0002)
{
if (x + x > p)
{
x -= p;
if (x + x >= p)
x -= p;
}
} else
{
p_half = 0.5L * p;
if (x > p_half)
{
x -= p;
if (x >= p_half)
x -= p;
}
}
GET_LDOUBLE_EXP(sex, x);
SET_LDOUBLE_EXP(x, sex ^ sx);
return x;
}
#endif
/* wrapper remainder */
long double __remainderl(long double x, long double y)
{
if (((y == 0.0 && !isnan(x))
|| (isinf(x) && !isnan(y))) && _LIB_VERSION != _IEEE_)
return __kernel_standard_l(x, y, y, KMATHERRL_REMAINDER); /* remainder domain */
return __ieee754_remainderl(x, y);
}
__typeof(__remainderl) remainderl __attribute__((weak, alias("__remainderl")));
__typeof(__remainderl) __dreml __attribute__((alias("__remainderl")));
__typeof(remainderl) dreml __attribute__((weak, alias("__dreml")));
#endif