Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename eps -> ulp #28301

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ function /(z::ComplexF64, w::ComplexF64)
cd = max(abs(c), abs(d))
ov = realmax(a)
un = realmin(a)
ϵ = eps(Float64)
ϵ = ulp(Float64)
bs = two/(ϵ*ϵ)
s = 1.0
ab >= half*ov && (a=half*a; b=half*b; s=two*s ) # scale down a,b
Expand Down Expand Up @@ -399,7 +399,7 @@ function inv(w::ComplexF64)
cd = max(abs(c), abs(d))
ov = realmax(c)
un = realmin(c)
ϵ = eps(Float64)
ϵ = ulp(Float64)
bs = two/(ϵ*ϵ)
s = 1.0
cd >= half*ov && (c=half*c; d=half*d; s=s*half) # scale down c,d
Expand All @@ -424,7 +424,7 @@ function ssqs(x::T, y::T) where T<:AbstractFloat
ρ = x*x + y*y
if !isfinite(ρ) && (isinf(x) || isinf(y))
ρ = convert(T, Inf)
elseif isinf(ρ) || (ρ==0 && (x!=0 || y!=0)) || ρ<nextfloat(zero(T))/(2*eps(T)^2)
elseif isinf(ρ) || (ρ==0 && (x!=0 || y!=0)) || ρ<nextfloat(zero(T))/(2*ulp(T)^2)
m::T = max(abs(x), abs(y))
k = m==0 ? m : exponent(m)
xk, yk = ldexp(x,-k), ldexp(y,-k)
Expand Down
2 changes: 2 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1770,6 +1770,8 @@ end
# PR #28223
@deprecate code_llvm_raw(f, types=Tuple) code_llvm(f, types; raw=true)

@deprecate eps ulp

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
2 changes: 1 addition & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export
denominator,
div,
divrem,
eps,
ulp,
exp,
exp10,
exp2,
Expand Down
48 changes: 24 additions & 24 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
end
end
else
# Here `eps(Tf(typemin(Ti))) > 1`, so the only value which can be truncated to
# Here `ulp(Tf(typemin(Ti))) > 1`, so the only value which can be truncated to
# `Tf(typemin(Ti)` is itself. Similarly, `Tf(typemax(Ti))` is inexact and will
# be rounded up. This assumes that `Tf(typemin(Ti)) > -Inf`, which is true for
# these types, but not for `Float16` or larger integer types.
Expand Down Expand Up @@ -732,11 +732,11 @@ end
realmax(::Type{Float32}) = $(bitcast(Float32, 0x7f7fffff))
realmax(::Type{Float64}) = $(bitcast(Float64, 0x7fefffffffffffff))

eps(x::AbstractFloat) = isfinite(x) ? abs(x) >= realmin(x) ? ldexp(eps(typeof(x)), exponent(x)) : nextfloat(zero(x)) : oftype(x, NaN)
eps(::Type{Float16}) = $(bitcast(Float16, 0x1400))
eps(::Type{Float32}) = $(bitcast(Float32, 0x34000000))
eps(::Type{Float64}) = $(bitcast(Float64, 0x3cb0000000000000))
eps() = eps(Float64)
ulp(x::AbstractFloat) = isfinite(x) ? abs(x) >= realmin(x) ? ldexp(ulp(typeof(x)), exponent(x)) : nextfloat(zero(x)) : oftype(x, NaN)
ulp(::Type{Float16}) = $(bitcast(Float16, 0x1400))
ulp(::Type{Float32}) = $(bitcast(Float32, 0x34000000))
ulp(::Type{Float64}) = $(bitcast(Float64, 0x3cb0000000000000))
ulp() = ulp(Float64)
end

"""
Expand Down Expand Up @@ -767,74 +767,74 @@ realmin() = realmin(Float64)
realmax() = realmax(Float64)

"""
eps(::Type{T}) where T<:AbstractFloat
eps()
ulp(::Type{T}) where T<:AbstractFloat
ulp()

Return the *machine epsilon* of the floating point type `T` (`T = Float64` by
Copy link
Contributor

@waldyrious waldyrious Jul 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't "machine epsilon" be changed (or adjusted to also mention ULP) here as well?

default). This is defined as the gap between 1 and the next largest value representable by
`typeof(one(T))`, and is equivalent to `eps(one(T))`. (Since `eps(T)` is a
`typeof(one(T))`, and is equivalent to `ulp(one(T))`. (Since `ulp(T)` is a
bound on the *relative error* of `T`, it is a "dimensionless" quantity like [`one`](@ref).)

# Examples
```jldoctest
julia> eps()
julia> ulp()
2.220446049250313e-16

julia> eps(Float32)
julia> ulp(Float32)
1.1920929f-7

julia> 1.0 + eps()
julia> 1.0 + ulp()
1.0000000000000002

julia> 1.0 + eps()/2
julia> 1.0 + ulp()/2
1.0
```
"""
eps(::Type{<:AbstractFloat})
ulp(::Type{<:AbstractFloat})

"""
eps(x::AbstractFloat)
ulp(x::AbstractFloat)

Return the *unit in last place* (ulp) of `x`. This is the distance between consecutive
representable floating point values at `x`. In most cases, if the distance on either side
of `x` is different, then the larger of the two is taken, that is

eps(x) == max(x-prevfloat(x), nextfloat(x)-x)
ulp(x) == max(x-prevfloat(x), nextfloat(x)-x)

The exceptions to this rule are the smallest and largest finite values
(e.g. `nextfloat(-Inf)` and `prevfloat(Inf)` for [`Float64`](@ref)), which round to the
smaller of the values.

The rationale for this behavior is that `eps` bounds the floating point rounding
The rationale for this behavior is that `ulp` bounds the floating point rounding
error. Under the default `RoundNearest` rounding mode, if ``y`` is a real number and ``x``
is the nearest floating point number to ``y``, then

```math
|y-x| \\leq \\operatorname{eps}(x)/2.
|y-x| \\leq \\operatorname{ulp}(x)/2.
```

# Examples
```jldoctest
julia> eps(1.0)
julia> ulp(1.0)
2.220446049250313e-16

julia> eps(prevfloat(2.0))
julia> ulp(prevfloat(2.0))
2.220446049250313e-16

julia> eps(2.0)
julia> ulp(2.0)
4.440892098500626e-16

julia> x = prevfloat(Inf) # largest finite Float64
1.7976931348623157e308

julia> x + eps(x)/2 # rounds up
julia> x + ulp(x)/2 # rounds up
Inf

julia> x + prevfloat(eps(x)/2) # rounds down
julia> x + prevfloat(ulp(x)/2) # rounds down
1.7976931348623157e308
```
"""
eps(::AbstractFloat)
ulp(::AbstractFloat)


## byte order swaps for arbitrary-endianness serialization/deserialization ##
Expand Down
6 changes: 3 additions & 3 deletions base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,14 @@ end

# isapprox: approximate equality of numbers
"""
isapprox(x, y; rtol::Real=atol>0 ? 0 : √eps, atol::Real=0, nans::Bool=false, norm::Function)
isapprox(x, y; rtol::Real=atol>0 ? 0 : √ulp, atol::Real=0, nans::Bool=false, norm::Function)

Inexact equality comparison: `true` if `norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))`. The
default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. The keyword
argument `nans` determines whether or not NaN values are considered equal (defaults to false).

For real or complex floating-point values, if an `atol > 0` is not specified, `rtol` defaults to
the square root of [`eps`](@ref) of the type of `x` or `y`, whichever is bigger (least precise).
the square root of [`ulp`](@ref) of the type of `x` or `y`, whichever is bigger (least precise).
This corresponds to requiring equality of about half of the significand digits. Otherwise,
e.g. for integer arguments or if an `atol > 0` is supplied, `rtol` defaults to zero.

Expand Down Expand Up @@ -281,7 +281,7 @@ This is equivalent to `!isapprox(x,y)` (see [`isapprox`](@ref)).
≉(args...; kws...) = !≈(args...; kws...)

# default tolerance arguments
rtoldefault(::Type{T}) where {T<:AbstractFloat} = sqrt(eps(T))
rtoldefault(::Type{T}) where {T<:AbstractFloat} = sqrt(ulp(T))
rtoldefault(::Type{<:Real}) = 0
function rtoldefault(x::Union{T,Type{T}}, y::Union{S,Type{S}}, atol::Real) where {T<:Number,S<:Number}
rtol = max(rtoldefault(real(T)),rtoldefault(real(S)))
Expand Down
4 changes: 2 additions & 2 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ function (::Type{T})(n::BigInt, ::RoundingMode{:Nearest}) where T<:CdoubleMax
x = T(n,RoundToZero)
if maxintfloat(T) <= abs(x) < T(Inf)
r = n-BigInt(x)
h = eps(x)/2
h = ulp(x)/2
if iseven(reinterpret(Unsigned,x)) # check if last bit is odd/even
if r < -h
return prevfloat(x)
Expand Down Expand Up @@ -623,7 +623,7 @@ function ndigits0zpb(x::BigInt, b::Integer)
lb = log2(b) # assumed accurate to <1ulp (true for openlibm)
q,r = divrem(n,lb)
iq = Int(q)
maxerr = q*eps(lb) # maximum error in remainder
maxerr = q*ulp(lb) # maximum error in remainder
if r-1.0 < maxerr
abs(x) >= big(b)^iq ? iq+1 : iq
elseif lb-r < maxerr
Expand Down
4 changes: 2 additions & 2 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ julia> mod(9, 3)
julia> mod(8.9, 3)
2.9000000000000004

julia> mod(eps(), 3)
julia> mod(ulp(), 3)
2.220446049250313e-16

julia> mod(-eps(), 3)
julia> mod(-ulp(), 3)
3.0
```
"""
Expand Down
2 changes: 1 addition & 1 deletion base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x))
setprecision(BigFloat, p)
bx = BigFloat(x)
r = rationalize(T, bx, tol=0)
if abs(BigFloat(r) - bx) > eps(bx)
if abs(BigFloat(r) - bx) > ulp(bx)
setprecision(BigFloat, o)
return r
end
Expand Down
4 changes: 2 additions & 2 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import
nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show, float,
sum, sqrt, string, print, trunc, precision, exp10, expm1,
log1p,
eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
ulp, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh,
cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
Expand Down Expand Up @@ -879,7 +879,7 @@ function prevfloat(x::BigFloat)
return z
end

eps(::Type{BigFloat}) = nextfloat(BigFloat(1)) - BigFloat(1)
ulp(::Type{BigFloat}) = nextfloat(BigFloat(1)) - BigFloat(1)

realmin(::Type{BigFloat}) = nextfloat(zero(BigFloat))
realmax(::Type{BigFloat}) = prevfloat(BigFloat(Inf))
Expand Down
4 changes: 2 additions & 2 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat}
widen(::Type{Rational{T}}) where {T} = Rational{widen(T)}

"""
rationalize([T<:Integer=Int,] x; tol::Real=eps(x))
rationalize([T<:Integer=Int,] x; tol::Real=ulp(x))

Approximate floating point number `x` as a [`Rational`](@ref) number with components
of the given integer type. The result will differ from `x` by no more than `tol`.
Expand Down Expand Up @@ -184,7 +184,7 @@ function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer
return p // q
end
end
rationalize(::Type{T}, x::AbstractFloat; tol::Real = eps(x)) where {T<:Integer} = rationalize(T, x, tol)::Rational{T}
rationalize(::Type{T}, x::AbstractFloat; tol::Real = ulp(x)) where {T<:Integer} = rationalize(T, x, tol)::Rational{T}
rationalize(x::AbstractFloat; kvs...) = rationalize(Int, x; kvs...)

"""
Expand Down
2 changes: 1 addition & 1 deletion base/special/rem_pio2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ end

fn = round(x*(2/pi)) # round to integer
# on older systems, the above could be faster with
# rf = 1.5/eps(Float64)
# rf = 1.5/ulp(Float64)
# fn = (x*(2/pi)+rf)-rf

r = muladd(-fn, pio2_1, x) # x - fn*pio2_1
Expand Down
8 changes: 4 additions & 4 deletions base/special/trig.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ end
function sin(x::T) where T<:Union{Float32, Float64}
absx = abs(x)
if absx < T(pi)/4 #|x| ~<= pi/4, no need for reduction
if absx < sqrt(eps(T))
if absx < sqrt(ulp(T))
return x
end
return sin_kernel(x)
Expand Down Expand Up @@ -99,7 +99,7 @@ end
function cos(x::T) where T<:Union{Float32, Float64}
absx = abs(x)
if absx < T(pi)/4
if absx < sqrt(eps(T)/T(2.0))
if absx < sqrt(ulp(T)/T(2.0))
return T(1.0)
end
return cos_kernel(x)
Expand Down Expand Up @@ -214,7 +214,7 @@ sincos(x) = _sincos(float(x))
function tan(x::T) where T<:Union{Float32, Float64}
absx = abs(x)
if absx < T(pi)/4
if absx < sqrt(eps(T))/2 # first order dominates, but also allows tan(-0)=-0
if absx < sqrt(ulp(T))/2 # first order dominates, but also allows tan(-0)=-0
return x
end
return tan_kernel(x)
Expand Down Expand Up @@ -360,7 +360,7 @@ sincos_kernel(x::Real) = sincos(x)
# Inverse trigonometric functions
# asin methods
ASIN_X_MIN_THRESHOLD(::Type{Float32}) = 2.0f0^-12
ASIN_X_MIN_THRESHOLD(::Type{Float64}) = sqrt(eps(Float64))
ASIN_X_MIN_THRESHOLD(::Type{Float64}) = sqrt(ulp(Float64))

arc_p(t::Float64) =
t*@horner(t,
Expand Down
4 changes: 2 additions & 2 deletions doc/src/base/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ Base.typemax
Base.realmin
Base.realmax
Base.maxintfloat
Base.eps(::Type{<:AbstractFloat})
Base.eps(::AbstractFloat)
Base.ulp(::Type{<:AbstractFloat})
Base.ulp(::AbstractFloat)
Base.instances
```

Expand Down
53 changes: 28 additions & 25 deletions doc/src/manual/integers-and-floating-point-numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,47 +420,50 @@ julia> (typemin(Float64),typemax(Float64))
### Machine epsilon

Most real numbers cannot be represented exactly with floating-point numbers, and so for many purposes
it is important to know the distance between two adjacent representable floating-point numbers,
which is often known as [machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon).
it is important to know the distance between two adjacent representable floating-point numbers.

Julia provides [`eps`](@ref), which gives the distance between `1.0` and the next larger representable
floating-point value:

```jldoctest
julia> eps(Float32)
1.1920929f-7

julia> eps(Float64)
2.220446049250313e-16

julia> eps() # same as eps(Float64)
2.220446049250313e-16
```

These values are `2.0^-23` and `2.0^-52` as [`Float32`](@ref) and [`Float64`](@ref) values,
respectively. The [`eps`](@ref) function can also take a floating-point value as an
The [`ulp`](@ref) function takes a floating-point value as an
argument, and gives the absolute difference between that value and the next representable
floating point value. That is, `eps(x)` yields a value of the same type as `x` such that
`x + eps(x)` is the next representable floating-point value larger than `x`:
floating point value. That is, `ulp(x)` yields a value of the same type as `x` such that
`x + ulp(x)` is the next representable floating-point value larger than `x`:

```jldoctest
julia> eps(1.0)
julia> ulp(1.0)
2.220446049250313e-16

julia> eps(1000.)
julia> ulp(1000.)
1.1368683772161603e-13

julia> eps(1e-27)
julia> ulp(1e-27)
1.793662034335766e-43

julia> eps(0.0)
julia> ulp(0.0)
5.0e-324
```

For convenience, if the argument value is omitted, it defaults to `1.0`,
and if the argument is a type `T`, it defaults to `one(T)`. For a given floating
point type, this value which is commonly known as the
[machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon).

```jldoctest
julia> ulp(Float32) # same as ulp(1.0f0)
1.1920929f-7

julia> ulp(Float64) # same as ulp(1.0)
2.220446049250313e-16

julia> ulp() # same as ulp(Float64) == ulp(1.0)
2.220446049250313e-16
```

These values are `2.0^-23` and `2.0^-52` as [`Float32`](@ref) and [`Float64`](@ref) values,
respectively.

The distance between two adjacent representable floating-point numbers is not constant, but is
smaller for smaller values and larger for larger values. In other words, the representable floating-point
numbers are densest in the real number line near zero, and grow sparser exponentially as one moves
farther away from zero. By definition, `eps(1.0)` is the same as `eps(Float64)` since `1.0` is
farther away from zero. By definition, `ulp(1.0)` is the same as `ulp(Float64)` since `1.0` is
a 64-bit floating-point value.

Julia also provides the [`nextfloat`](@ref) and [`prevfloat`](@ref) functions which return
Expand Down
Loading