huangcm
2025-08-14 5d6606c55520a76d5bb8297d83fd9bbf967e5244
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
 
/* @(#)s_nextafter.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.
 * ====================================================
 */
 
/* IEEE functions
 *    nextafter(x,y)
 *    return the next machine floating-point number of x in the
 *    direction toward y.
 *   Special cases:
 */
 
#include "fdlibm.h"
 
#ifdef __STDC__
   double ieee_nextafter(double x, double y)
#else
   double ieee_nextafter(x,y)
   double x,y;
#endif
{
   int    hx,hy,ix,iy;
   unsigned lx,ly;
 
   hx = __HI(x);        /* high word of x */
   lx = __LO(x);        /* low  word of x */
   hy = __HI(y);        /* high word of y */
   ly = __LO(y);        /* low  word of y */
   ix = hx&0x7fffffff;        /* |x| */
   iy = hy&0x7fffffff;        /* |y| */
 
   if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */ 
      ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */ 
      return x+y;                
   if(x==y) return x;        /* x=y, return x */
   if((ix|lx)==0) {            /* x == 0 */
       __HI(x) = hy&0x80000000;    /* return +-minsubnormal */
       __LO(x) = 1;
       y = x*x;
       if(y==x) return y; else return x;    /* raise underflow flag */
   } 
   if(hx>=0) {                /* x > 0 */
       if(hx>hy||((hx==hy)&&(lx>ly))) {    /* x > y, x -= ulp */
       if(lx==0) hx -= 1;
       lx -= 1;
       } else {                /* x < y, x += ulp */
       lx += 1;
       if(lx==0) hx += 1;
       }
   } else {                /* x < 0 */
       if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
       if(lx==0) hx -= 1;
       lx -= 1;
       } else {                /* x > y, x += ulp */
       lx += 1;
       if(lx==0) hx += 1;
       }
   }
   hy = hx&0x7ff00000;
   if(hy>=0x7ff00000) return x+x;    /* overflow  */
   if(hy<0x00100000) {        /* underflow */
       y = x*x;
       if(y!=x) {        /* raise underflow flag */
       __HI(y) = hx; __LO(y) = lx;
       return y;
       }
   }
   __HI(x) = hx; __LO(x) = lx;
   return x;
}