lin
2025-08-14 dae8bad597b6607a449b32bf76c523423f7720ed
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
 
/* @(#)e_remainder.c 1.3 95/01/18 */
/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunSoft, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice 
 * is preserved.
 * ====================================================
 */
 
/* __ieee754_remainder(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 ieee_fmod() return x-[x/p]chopped*p exactlp.
 */
 
#include "fdlibm.h"
 
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
 
 
#ifdef __STDC__
   double __ieee754_remainder(double x, double p)
#else
   double __ieee754_remainder(x,p)
   double x,p;
#endif
{
   int hx,hp;
   unsigned sx,lx,lp;
   double p_half;
 
   hx = __HI(x);        /* high word of x */
   lx = __LO(x);        /* low  word of x */
   hp = __HI(p);        /* high word of p */
   lp = __LO(p);        /* low  word of p */
   sx = hx&0x80000000;
   hp &= 0x7fffffff;
   hx &= 0x7fffffff;
 
    /* purge off exception values */
   if((hp|lp)==0) return (x*p)/(x*p);     /* p = 0 */
   if((hx>=0x7ff00000)||            /* x not finite */
     ((hp>=0x7ff00000)&&            /* p is NaN */
     (((hp-0x7ff00000)|lp)!=0)))
       return (x*p)/(x*p);
 
 
   if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p);    /* now x < 2p */
   if (((hx-hp)|(lx-lp))==0) return zero*x;
   x  = ieee_fabs(x);
   p  = ieee_fabs(p);
   if (hp<0x00200000) {
       if(x+x>p) {
       x-=p;
       if(x+x>=p) x -= p;
       }
   } else {
       p_half = 0.5*p;
       if(x>p_half) {
       x-=p;
       if(x>=p_half) x -= p;
       }
   }
   __HI(x) ^= sx;
   return x;
}