├── src ├── AdjacentFloat.jl └── adjacentFloats.jl ├── README.md └── LICENSE /src/AdjacentFloat.jl: -------------------------------------------------------------------------------- 1 | module AdjacentFloat 2 | 3 | export prevFloat, nextFloat, nFloatsSeparate, nextNearerToZero, nextAwayFromZero 4 | 5 | include("adjacentFloats.jl") 6 | 7 | end # module 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AdjacentFloat 2 | fast versions of nextfloat(), prevfloat(), and closely related functions 3 | ```ruby 4 | Jeffrey Sarnoff © 2016-Mar-22 at New York 5 | 2016-Jun-25 at v"0.1.0" 6 | ``` 7 | 8 | ### Use 9 | ```julia 10 | using AdjacentFloat 11 | 12 | nextFloat(Float16(1)), nextFloat(1.0f0), nextFloat(1.0) 13 | Float16(1.001), 1.0000001f0, 1.0000000000000002 14 | 15 | prevfloat(prevfloat(1.0f0)) == prevFloat(1.0f0, 2) 16 | true 17 | 18 | nFloatsSeparate(1.0, nextFloat(1.0,100)) 19 | 100 20 | 21 | ``` 22 | 23 | ### Exports 24 | ``` 25 | prevFloat, nextFloat, 26 | nextNearerToZero, nextAwayFromZero, 27 | nFloatsSeparate 28 | ``` 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jeffrey Sarnoff 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/adjacentFloats.jl: -------------------------------------------------------------------------------- 1 | #= 2 | These routines return +/-Inf when given +/-Inf. 3 | That differs from nextfloat(-Inf) == -realmax(), prevfloat(Inf) == realmax() 4 | (prevfloat(Inf)==Inf makes more sense to me, and likely is more helpful). 5 | And steps twice when given values of very small magnitude (see paper). 6 | The alternative implementation, converting to [U]Int and adding/subtracting 1, 7 | returns NaN when given +/-Inf -- and checking for Inf adds branching. 8 | ref: 9 | 'Predecessor and Successor In Rounding To Nearest' by Siegried M. Rump 10 | "The routines deliver the exact answer except for a small range near underflow, 11 | in which case the true result is overestimated by eta [the value added/subtracted below]." 12 | =# 13 | # exact for |x| > 8.900295434028806e-308 14 | nextNearerToZero(x::Float64) = (0.9999999999999999*x)-5.0e-324 # (x-1.1102230246251568e-16*x)-5.0e-324 15 | nextAwayFromZero(x::Float64) = (1.0000000000000002*x)+5.0e-324 # (x+1.1102230246251568e-16*x)+5.0e-324 16 | # exact for |x| > 4.814825f-35 17 | nextNearerToZero(x::Float32) = (0.99999994f0*x)-1.435f-42 # (x-5.960465f-8*x)-1.435f-42 18 | nextAwayFromZero(x::Float32) = (1.00000010f0*x)+1.435f-42 # (x+5.960465f-8*x)+1.435f-42 19 | # the multiplicative formulation for Float16 is exact for |x| > Float16(0.25) 20 | # which is quite coarse, we do not use that here 21 | nextNearerToZero(x::Union{BigFloat,Float16}) = signbit(x) ? nextfloat(x) : prevfloat(x) 22 | nextAwayFromZero(x::Union{BigFloat,Float16}) = signbit(x) ? prevfloat(x) : nextfloat(x) 23 | 24 | @inline nextFloat{T<:AbstractFloat}(x::T) = signbit(x) ? nextNearerToZero(x) : nextAwayFromZero(x) 25 | @inline prevFloat{T<:AbstractFloat}(x::T) = signbit(x) ? nextAwayFromZero(x) : nextNearerToZero(x) 26 | 27 | @inline nextFloat(x::Union{BigFloat,Float16}) = nextfloat(x) 28 | @inline prevFloat(x::Union{BigFloat,Float16}) = prevfloat(x) 29 | 30 | function nextFloat{T<:AbstractFloat}(x::T, n::Int) 31 | if !signbit(n) 32 | for i in 1:n 33 | x = nextFloat(x) 34 | end 35 | else 36 | x = prevFloat(x,-n) 37 | end 38 | x 39 | end 40 | 41 | function prevFloat{T<:AbstractFloat}(x::T, n::Int) 42 | if !signbit(n) 43 | for i in 1:n 44 | x = prevFloat(x) 45 | end 46 | else 47 | x = nextFloat(x,-n) 48 | end 49 | x 50 | end 51 | 52 | for (F,U,I) in ((:Float16,:UInt16,:Int16), (:Float32,:UInt32,:Int32), (:Float64,:UInt64,:Int64)) 53 | @eval begin 54 | function nFloatsSeparate{T<:$F}(a::T, b::T) 55 | isneg = (a > b) 56 | a,b = minmax(a,b) 57 | 58 | if signbit(a) == signbit(b) 59 | if signbit(a) 60 | z = reinterpret($U,abs(a))-reinterpret($U,abs(b)) 61 | else 62 | z = reinterpret($U,b)-reinterpret($U,a) 63 | end 64 | else 65 | z = reinterpret($U,b)+reinterpret($U,-a)+one($U) 66 | end 67 | 68 | if z > reinterpret($U, typemax($I)) 69 | throw(ArgumentError(string("separation exceeds typemax(",$I,")"))) 70 | else 71 | isneg ? -reinterpret($I,z) : reinterpret($I,z) 72 | end 73 | end 74 | end 75 | end 76 | 77 | #= presumes xpa == frexp(a)[2] == frexp(b)[2] 78 | function nFloatsSeparate{T<:Float64}(a::T, b::T,xpa::Int) 79 | isneg = a > b 80 | x,y = minmax(a,b) 81 | z = floor(Int64, ((y-x)/2^xpa)*2^53) 82 | isneg ? -z : z 83 | end 84 | =# 85 | --------------------------------------------------------------------------------