///|
/// Return next representable double-precision floating-point value after argument `x` in the direction of `y`.
///
/// # Special cases
///
/// 1. nextafter(x, y) = y if x equals y.
/// 2. nextafter(x, y) = NaN if either x or y are NaN.
pub fn nextafter(x : Double, y : Double) -> Double {
if isnan(x) || isnan(y) {
return @double.not_a_number
}
if x == y {
return x
}
let mut hx = __hi(x).reinterpret_as_int()
let mut lx = __low(x).reinterpret_as_int()
let hy = __hi(y).reinterpret_as_int()
let ly = __low(y).reinterpret_as_int()
if x == 0 {
let x = if y < 0 { 0x80000000_00000001UL } else { 0x1 }
let x = x.reinterpret_as_double()
let y = x * x
if y == x {
return y
} else {
return x
}
}
if x > 0 {
if hx > hy || (hx == hy && lx > ly) {
if lx == 0 {
hx -= 1
}
lx -= 1
} else {
lx += 1
if lx == 0 {
hx += 1
}
}
} else if hy >= 0 || hx > hy || (hx == hy && lx > ly) {
if lx == 0 {
hx -= 1
}
lx -= 1
} else {
lx += 1
if lx == 0 {
hx += 1
}
}
let hy = hx & 0x7ff00000
if hy >= 0x7ff00000 {
return x + x
}
if hy < 0x00100000 {
let y = x * x
if y != x {
let y = __combineW(hx.reinterpret_as_uint(), lx.reinterpret_as_uint())
return y
}
}
__combineW(hx.reinterpret_as_uint(), lx.reinterpret_as_uint())
}