Skip to content

Commit

Permalink
Add nextfloat(::BigFloat, n), prevfloat(::BigFloat, n) (JuliaLang#31310)
Browse files Browse the repository at this point in the history
  • Loading branch information
narendrakpatel authored and rfourquet committed Apr 1, 2019
1 parent cc516ab commit 4c2e570
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 14 deletions.
8 changes: 7 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ New language features
`findall`, `findfirst`, `argmin`/`argmax` and `findmin`/`findmax` to work with these
objects, returning the index of matching non-missing elements in the parent ([#31008]).

* `inv(::Missing)` has now been added and returns `missing` ([#31408]).
* `inv(::Missing)` has now been added and returns `missing` ([#31451]).

* `nextfloat(::BigFloat, n::Integer)` and `prevfloat(::BigFloat, n::Integer)` methods
have been added ([#31310]).

Multi-threading changes
-----------------------
Expand Down Expand Up @@ -49,6 +52,9 @@ Standard library changes
* A no-argument construct to `Ptr{T}` has been added which constructs a null pointer ([#30919])
* `strip` now accepts a function argument in the same manner as `lstrip` and `rstrip` ([#31211])
* `mktempdir` now accepts a `prefix` keyword argument to customize the file name ([#31230], [#22922])
* `nextfloat(::BigFloat)` and `prevfloat(::BigFloat)` now returns a value with the same precision
as their argument, which means that (in particular) `nextfloat(prevfloat(x)) == x` whereas
previously this could result in a completely different value with a different precision ([#31310])

#### LinearAlgebra

Expand Down
2 changes: 1 addition & 1 deletion base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ uabs(x::BitSigned) = unsigned(abs(x))


"""
nextfloat(x::IEEEFloat, n::Integer)
nextfloat(x::AbstractFloat, n::Integer)
The result of `n` iterative applications of `nextfloat` to `x` if `n >= 0`, or `-n`
applications of `prevfloat` if `n < 0`.
Expand Down
35 changes: 23 additions & 12 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::I
end
end

function _duplicate(x::BigFloat)
z = BigFloat(;precision=precision(x))
ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, 0)
return z
end

# convert to BigFloat
for (fJ, fC) in ((:si,:Clong), (:ui,:Culong))
Expand Down Expand Up @@ -889,22 +894,25 @@ isone(x::BigFloat) = x == Clong(1)
@eval typemax(::Type{BigFloat}) = $(BigFloat(Inf))
@eval typemin(::Type{BigFloat}) = $(BigFloat(-Inf))

function nextfloat(x::BigFloat)
z = BigFloat()
ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode),
z, x, ROUNDING_MODE[])
ccall((:mpfr_nextabove, :libmpfr), Int32, (Ref{BigFloat},), z) != 0
return z
function nextfloat!(x::BigFloat, n::Integer=1)
signbit(n) && return prevfloat!(x, abs(n))
for i = 1:n
ccall((:mpfr_nextabove, :libmpfr), Int32, (Ref{BigFloat},), x)
end
return x
end

function prevfloat(x::BigFloat)
z = BigFloat()
ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode),
z, x, ROUNDING_MODE[])
ccall((:mpfr_nextbelow, :libmpfr), Int32, (Ref{BigFloat},), z) != 0
return z
function prevfloat!(x::BigFloat, n::Integer=1)
signbit(n) && return nextfloat!(x, abs(n))
for i = 1:n
ccall((:mpfr_nextbelow, :libmpfr), Int32, (Ref{BigFloat},), x)
end
return x
end

nextfloat(x::BigFloat, n::Integer=1) = n == 0 ? x : nextfloat!(_duplicate(x), n)
prevfloat(x::BigFloat, n::Integer=1) = n == 0 ? x : prevfloat!(_duplicate(x), n)

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

floatmin(::Type{BigFloat}) = nextfloat(zero(BigFloat))
Expand All @@ -922,6 +930,9 @@ It is logically equivalent to:
setprecision(BigFloat, old)
Often used as `setprecision(T, precision) do ... end`
Note: `nextfloat()`, `prevfloat()` do not use the precision mentioned by
`setprecision`
"""
function setprecision(f::Function, ::Type{T}, prec::Integer) where T
old_prec = precision(T)
Expand Down
13 changes: 13 additions & 0 deletions test/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,21 @@ end
@test BigFloat(nextfloat(12.12)) == nextfloat(x)
@test BigFloat(prevfloat(12.12)) == prevfloat(x)
end
x = BigFloat(12.12, 100)
@test nextfloat(x, 0) === x
@test prevfloat(x, 0) === x
@test nextfloat(x).prec == x.prec
@test prevfloat(x).prec == x.prec
@test nextfloat(x) == nextfloat(x, 1)
@test prevfloat(x) == prevfloat(x, 1)
@test nextfloat(x, -1) == prevfloat(x, 1)
@test nextfloat(x, -2) == prevfloat(x, 2)
@test prevfloat(x, -1) == nextfloat(x, 1)
@test prevfloat(x, -2) == nextfloat(x, 2)
@test isnan(nextfloat(BigFloat(NaN)))
@test isnan(prevfloat(BigFloat(NaN)))
@test isnan(nextfloat(BigFloat(NaN), 1))
@test isnan(prevfloat(BigFloat(NaN), 1))
end
# sqrt DomainError
@test_throws DomainError sqrt(BigFloat(-1))
Expand Down

0 comments on commit 4c2e570

Please sign in to comment.