Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 1 | #include "libm.h" |
nsz | 9560b6b | 2012-03-13 19:51:14 +0100 | [diff] [blame] | 2 | |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 3 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 |
| 4 | double nexttoward(double x, long double y) |
| 5 | { |
| 6 | return nextafter(x, y); |
| 7 | } |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 8 | #else |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 9 | double nexttoward(double x, long double y) |
| 10 | { |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 11 | union {double f; uint64_t i;} ux = {x}; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 12 | int e; |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 13 | |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 14 | if (isnan(x) || isnan(y)) |
| 15 | return x + y; |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 16 | if (x == y) |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 17 | return y; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 18 | if (x == 0) { |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 19 | ux.i = 1; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 20 | if (signbit(y)) |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 21 | ux.i |= 1ULL<<63; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 22 | } else if (x < y) { |
| 23 | if (signbit(x)) |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 24 | ux.i--; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 25 | else |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 26 | ux.i++; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 27 | } else { |
| 28 | if (signbit(x)) |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 29 | ux.i++; |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 30 | else |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 31 | ux.i--; |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 32 | } |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 33 | e = ux.i>>52 & 0x7ff; |
| 34 | /* raise overflow if ux.f is infinite and x is finite */ |
nsz | 6cf865d | 2012-05-06 13:08:59 +0200 | [diff] [blame] | 35 | if (e == 0x7ff) |
Szabolcs Nagy | 662ed20 | 2012-11-13 10:12:07 +0100 | [diff] [blame] | 36 | FORCE_EVAL(x+x); |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 37 | /* raise underflow if ux.f is subnormal or zero */ |
nsz | 6ab8136 | 2012-05-06 21:24:28 +0200 | [diff] [blame] | 38 | if (e == 0) |
Szabolcs Nagy | 8dba548 | 2013-09-04 17:36:00 +0000 | [diff] [blame] | 39 | FORCE_EVAL(x*x + ux.f*ux.f); |
| 40 | return ux.f; |
Rich Felker | b69f695 | 2012-03-13 01:17:53 -0400 | [diff] [blame] | 41 | } |
| 42 | #endif |