1 | |
---|
2 | /* @(#)s_nextafter.c 5.1 93/09/24 */ |
---|
3 | /* |
---|
4 | * ==================================================== |
---|
5 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
---|
6 | * |
---|
7 | * Developed at SunPro, a Sun Microsystems, Inc. business. |
---|
8 | * Permission to use, copy, modify, and distribute this |
---|
9 | * software is freely granted, provided that this notice |
---|
10 | * is preserved. |
---|
11 | * ==================================================== |
---|
12 | */ |
---|
13 | |
---|
14 | /* |
---|
15 | FUNCTION |
---|
16 | <<nextafter>>, <<nextafterf>>---get next number |
---|
17 | |
---|
18 | INDEX |
---|
19 | nextafter |
---|
20 | INDEX |
---|
21 | nextafterf |
---|
22 | |
---|
23 | SYNOPSIS |
---|
24 | #include <math.h> |
---|
25 | double nextafter(double <[val]>, double <[dir]>); |
---|
26 | float nextafterf(float <[val]>, float <[dir]>); |
---|
27 | |
---|
28 | DESCRIPTION |
---|
29 | <<nextafter>> returns the double-precision floating-point number |
---|
30 | closest to <[val]> in the direction toward <[dir]>. <<nextafterf>> |
---|
31 | performs the same operation in single precision. For example, |
---|
32 | <<nextafter(0.0,1.0)>> returns the smallest positive number which is |
---|
33 | representable in double precision. |
---|
34 | |
---|
35 | RETURNS |
---|
36 | Returns the next closest number to <[val]> in the direction toward |
---|
37 | <[dir]>. |
---|
38 | |
---|
39 | PORTABILITY |
---|
40 | Neither <<nextafter>> nor <<nextafterf>> is required by ANSI C |
---|
41 | or by the System V Interface Definition (Issue 2). |
---|
42 | */ |
---|
43 | |
---|
44 | /* IEEE functions |
---|
45 | * nextafter(x,y) |
---|
46 | * return the next machine floating-point number of x in the |
---|
47 | * direction toward y. |
---|
48 | * Special cases: |
---|
49 | */ |
---|
50 | |
---|
51 | #include "fdlibm.h" |
---|
52 | |
---|
53 | #ifndef _DOUBLE_IS_32BITS |
---|
54 | |
---|
55 | #ifdef __STDC__ |
---|
56 | double nextafter(double x, double y) |
---|
57 | #else |
---|
58 | double nextafter(x,y) |
---|
59 | double x,y; |
---|
60 | #endif |
---|
61 | { |
---|
62 | __int32_t hx,hy,ix,iy; |
---|
63 | __uint32_t lx,ly; |
---|
64 | |
---|
65 | EXTRACT_WORDS(hx,lx,x); |
---|
66 | EXTRACT_WORDS(hy,ly,y); |
---|
67 | ix = hx&0x7fffffff; /* |x| */ |
---|
68 | iy = hy&0x7fffffff; /* |y| */ |
---|
69 | |
---|
70 | if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ |
---|
71 | ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ |
---|
72 | return x+y; |
---|
73 | if(x==y) return x; /* x=y, return x */ |
---|
74 | if((ix|lx)==0) { /* x == 0 */ |
---|
75 | INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */ |
---|
76 | y = x*x; |
---|
77 | if(y==x) return y; else return x; /* raise underflow flag */ |
---|
78 | } |
---|
79 | if(hx>=0) { /* x > 0 */ |
---|
80 | if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ |
---|
81 | if(lx==0) hx -= 1; |
---|
82 | lx -= 1; |
---|
83 | } else { /* x < y, x += ulp */ |
---|
84 | lx += 1; |
---|
85 | if(lx==0) hx += 1; |
---|
86 | } |
---|
87 | } else { /* x < 0 */ |
---|
88 | if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ |
---|
89 | if(lx==0) hx -= 1; |
---|
90 | lx -= 1; |
---|
91 | } else { /* x > y, x += ulp */ |
---|
92 | lx += 1; |
---|
93 | if(lx==0) hx += 1; |
---|
94 | } |
---|
95 | } |
---|
96 | hy = hx&0x7ff00000; |
---|
97 | if(hy>=0x7ff00000) return x+x; /* overflow */ |
---|
98 | if(hy<0x00100000) { /* underflow */ |
---|
99 | y = x*x; |
---|
100 | if(y!=x) { /* raise underflow flag */ |
---|
101 | INSERT_WORDS(y,hx,lx); |
---|
102 | return y; |
---|
103 | } |
---|
104 | } |
---|
105 | INSERT_WORDS(x,hx,lx); |
---|
106 | return x; |
---|
107 | } |
---|
108 | |
---|
109 | #endif /* _DOUBLE_IS_32BITS */ |
---|