digitalmars.D - nextafter
- bearophile (65/65) Nov 22 2007 It seems nextafter doesn't work with DMD v1.023 on Win on real type, thi...
It seems nextafter doesn't work with DMD v1.023 on Win on real type, this is my implementation, it may be slow, but it seem to work (but lastbit_wrt_half must be changed if real changes its bit representation): /****************************************** Calculates the next representable value after x in the direction of y. If y > x, the result will be the next largest floating-point value; if y < x, the result will be the next smallest value. If x == y, the result is y. The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and the function result is infinite. The FE_INEXACT and FE_UNDERFLOW exceptions will be raised if the function value is subnormal, and x is not equal to y. */ Tyx nextNum(Tyx, Tyy)(Tyx x, Tyy y) { static if (is(Tyx == float)) return nextafterf(x, y); else static if (is(Tyx == double)) return nextafter(x, y); else static if (is(Tyx == real)) { const real lastbit_wrt_half = 5.42101086242752217e-20L; int exponent; real mantissa = frexp(x, exponent); if (y > x) return ldexp(mantissa + lastbit_wrt_half, exponent); else return ldexp(mantissa - lastbit_wrt_half, exponent); } else static assert(0, "nextNum(): x must be float, double or real."); } unittest { // Tests of nextNum() float f = 0.5; double d = 0.5; real r = 0.5; float largef = 1000.0; double larged = 1000.0; real larger = 1000.0; float smallf = 0.1; double smalld = 0.1; real smallr = 0.1; f = nextNum(f, larger); assert(format("%.20e", f) == "5.00000059604644775390e-01"); f = nextNum(f, larger); assert(format("%.20e", f) == "5.00000119209289550780e-01"); f = 0.5; f = nextNum(f, smallf); assert(format("%.20e", f) == "4.99999970197677612300e-01"); d = nextNum(d, larged); assert(format("%.20e", d) == "5.00000000000000111020e-01"); d = nextNum(d, larged); assert(format("%.20e", d) == "5.00000000000000222040e-01"); d = 0.5; d = nextNum(d, smalld); assert(format("%.20e", d) == "4.99999999999999944480e-01"); r = nextNum(r, larger); assert(format("%.19e", r) == "5.0000000000000000004e-01"); r = nextNum(r, larger); assert(format("%.19e", r) == "5.0000000000000000008e-01"); r = 0.5; r = nextNum(r, smallr); assert(format("%.19e", r) == "4.9999999999999999995e-01"); assert(format("%.19e", nextNum(-3.0, -5.0)) == "-3.0000000000000004440e+00"); assert(format("%.19e", nextNum(-3.0, 5.0)) == "-2.9999999999999995559e+00"); } // End tests of nextNum() The starting point was: http://mail.python.org/pipermail/python-list/2001-August/099152.html Bye, bearophile
Nov 22 2007