-- limits.e -- -- Defines some of the numerical limits for Euphoria atoms and integers -- include machine.e -- integer limits, 31 bits global constant INTEGER_MIN = -(power(2, 30)), INTEGER_MAX = (-INTEGER_MIN) - 1 -- hex representation of double precision numerical limits constant FLOAT64_MAX = {#FF, #FF, #FF, #FF, #FF, #FF, #EF, #7F}, FLOAT64_MIN = {#00, #00, #00, #00, #00, #00, #10, #00}, -- corresponds to DBL_MIN in C FLOAT64_MIN_DENORMAL = {#01, #00, #00, #00, #00, #00, #00, #00}, -- absolute minimum FLOAT64_NAN_Q = {#00, #00, #00, #00, #00, #00, #F8, #7F}, -- 0x7ff8000000 to 0x7fffffffff FLOAT64_NAN_S = {#01, #00, #00, #00, #00, #00, #F0, #7F}, -- 0x7ff0000001 to 0x7ff7ffffff FLOAT64_INF = {#00, #00, #00, #00, #00, #00, #F0, #7F} -- atom limits, double precision global constant ATOM_MAX = float64_to_atom(FLOAT64_MAX), -- 1.7976931348623160e+308 ATOM_MIN = float64_to_atom(FLOAT64_MIN), -- 2.2250738585072020e-308 ATOM_MIN_DENORMAL = float64_to_atom(FLOAT64_MIN_DENORMAL), -- 4.9406564584124650e-324 ATOM_NAN_Q = float64_to_atom(FLOAT64_NAN_Q), ATOM_NAN_S = float64_to_atom(FLOAT64_NAN_S), ATOM_INFINITY = float64_to_atom(FLOAT64_INF) -- We shouldn't compare directly to NAN or INF so use these functions to check. global function is_infinite(atom a) sequence s integer isinf isinf = 0 s = atom_to_float64(a) s[8] = and_bits(s[8], #7F) -- discard sign isinf = equal(s, FLOAT64_INF) return isinf end function -- is_infinite() global function is_nan(atom a) sequence s integer isnan isnan = 0 s = atom_to_float64(a) s[8] = and_bits(s[8], #7F) -- discard sign if s[7] >= #F0 then if s[8] = #7F then if not equal(s, FLOAT64_INF) then isnan = 1 end if else isnan = 0 end if end if return isnan end function -- is_nan() function get_exponent(atom a) sequence s integer exponent s = atom_to_float64(a) -- mask and shift exponent bits (52..63), and subtract the exponent bias s[8] = and_bits(s[8], #7F) * 16 s[7] = floor(s[7] / 16) exponent = (s[8] + s[7]) - 1023 return exponent end function -- get_exponent() -- epsilon is the smallest number that will cause a change in an atom value -- should these three functions be in scientific.e instead? global function get_epsilon(atom a) integer exp atom epsilon epsilon = 0.0 exp = get_exponent(a) if exp > 1023 then -- normalized, so implicit 1 in front epsilon = power(2, exp - 52) else -- denormalized, so no implicit 1 epsilon = power(2, exp - 51) end if return epsilon end function -- get_epsilon() global function next_higher_atom( atom a ) return a + get_epsilon( a ) end function -- next_higher_atom() global function next_lower_atom( atom a ) return a - get_epsilon( a ) end function -- next_lower_atom()