From a65f06ae4657950b46e4ef7dd3f2473d02ec7ad9 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 12 Sep 2018 12:25:43 -0700 Subject: [PATCH 1/9] Improve handling of precision and rounding mode arguments in BigFloat constructors. This makes a few changes to avoid unnecessarily calling `setrounding` and `setprecision`. It also changes `precision` to be a keyword argument (though does not yet deprecate the old behaviour). --- base/irrationals.jl | 12 +- base/mpfr.jl | 335 ++++++++++++++++++++++---------------------- base/parse.jl | 8 +- base/sysimg.jl | 8 +- 4 files changed, 187 insertions(+), 176 deletions(-) diff --git a/base/irrationals.jl b/base/irrationals.jl index dd47c402f1ce6..efce4669694c5 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -147,14 +147,18 @@ macro irrational(sym, val, def) esym = esc(sym) qsym = esc(Expr(:quote, sym)) bigconvert = isa(def,Symbol) ? quote - function Base.BigFloat(::Irrational{$qsym}) - c = BigFloat() + function Base.BigFloat(::Irrational{$qsym}, r::MPFR.MPFRRoundingMode=MPFR.ROUNDING_MODE[]; precision=precision(BigFloat)) + c = BigFloat(;precision=precision) ccall(($(string("mpfr_const_", def)), :libmpfr), - Cint, (Ref{BigFloat}, Int32), c, MPFR.ROUNDING_MODE[]) + Cint, (Ref{BigFloat}, MPFR.MPFRRoundingMode), c, r) return c end end : quote - Base.BigFloat(::Irrational{$qsym}) = $(esc(def)) + function Base.BigFloat(::Irrational{$qsym}; precision=precision(BigFloat)) + setprecision(BigFloat, precision) do + $(esc(def)) + end + end end quote const $esym = Irrational{$qsym}() diff --git a/base/mpfr.jl b/base/mpfr.jl index 2d5acf2605d48..0cbfb0f617666 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -39,7 +39,39 @@ function __init__() nothing end -const ROUNDING_MODE = Ref{Cint}(0) # actually an Enum, defined by `to_mpfr` +# Matches the MPFR_RNDN, etc. +# https://www.mpfr.org/mpfr-current/mpfr.html#Rounding-Modes +@enum MPFRRoundingMode begin + MPFRRoundNearest + MPFRRoundToZero + MPFRRoundUp + MPFRRoundDown + MPFRRoundFromZero +end + +convert(::Type{MPFRRoundingMode}, ::RoundingMode{:Nearest}) = MPFRRoundNearest +convert(::Type{MPFRRoundingMode}, ::RoundingMode{:ToZero}) = MPFRRoundToZero +convert(::Type{MPFRRoundingMode}, ::RoundingMode{:Up}) = MPFRRoundUp +convert(::Type{MPFRRoundingMode}, ::RoundingMode{:Down}) = MPFRRoundDown +convert(::Type{MPFRRoundingMode}, ::RoundingMode{:FromZero}) = MPFRRoundFromZero + +function convert(::Type{RoundingMode}, r::MPFRRoundingMode) + if r == MPFRRoundNearest + return RoundNearest + elseif r == MPFRRoundToZero + return RoundToZero + elseif r == MPFRRoundUp + return RoundUp + elseif r == MPFRRoundDown + return RoundDown + elseif r == MPFRRoundFromZero + return RoundFromZero + else + throw(ArgumentError("invalid MPFR rounding mode code: $c")) + end +end + +const ROUNDING_MODE = Ref{MPFRRoundingMode}(MPFRRoundNearest) const DEFAULT_PRECISION = Ref{Int}(256) # Basic type and initialization definitions @@ -69,17 +101,23 @@ mutable struct BigFloat <: AbstractFloat return new(prec, sign, exp, pointer(d), d) end - function BigFloat() - prec::Clong = precision(BigFloat) - nb = ccall((:mpfr_custom_get_size,:libmpfr), Csize_t, (Clong,), prec) + function BigFloat(; precision::Integer=precision(BigFloat)) + nb = ccall((:mpfr_custom_get_size,:libmpfr), Csize_t, (Clong,), precision) nb = (nb + Core.sizeof(Limb) - 1) ÷ Core.sizeof(Limb) # align to number of Limb allocations required for this #d = Vector{Limb}(undef, nb) d = _string_n(nb * Core.sizeof(Limb)) EXP_NAN = Clong(1) - Clong(typemax(Culong) >> 1) - return _BigFloat(prec, one(Cint), EXP_NAN, d) # +NAN + return _BigFloat(precision, one(Cint), EXP_NAN, d) # +NAN end end +rounding_raw(::Type{BigFloat}) = ROUNDING_MODE[] +setrounding_raw(::Type{BigFloat}, r::MPFRRoundingMode) = ROUNDING_MODE[]=r + +rounding(::Type{BigFloat}) = convert(RoundingMode, rounding_raw(BigFloat)) +setrounding(::Type{BigFloat},r::RoundingMode) = setrounding_raw(BigFloat, convert(MPFRRoundingMode, r)) + + # overload the definition of unsafe_convert to ensure that `x.d` is assigned # it may have been dropped in the event that the BigFloat was serialized Base.unsafe_convert(::Type{Ref{BigFloat}}, x::Ptr{BigFloat}) = x @@ -116,46 +154,62 @@ BigFloat(x) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat -BigFloat(x::BigFloat) = x +function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) + if precision == MPFR.precision(x) + x + else + z = BigFloat(;precision=precision) + ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), + z, x, r) + z + end +end + # convert to BigFloat for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) @eval begin - function BigFloat(x::($fC)) - z = BigFloat() - ccall(($(string(:mpfr_set_,fJ)), :libmpfr), Int32, (Ref{BigFloat}, $fC, Int32), z, x, ROUNDING_MODE[]) + function BigFloat(x::($fC), r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) + z = BigFloat(;precision=precision) + ccall(($(string(:mpfr_set_,fJ)), :libmpfr), Int32, (Ref{BigFloat}, $fC, MPFRRoundingMode), z, x, r) return z end end end -function BigFloat(x::Float64) - z = BigFloat() - ccall((:mpfr_set_d, :libmpfr), Int32, (Ref{BigFloat}, Float64, Int32), z, x, ROUNDING_MODE[]) +function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) + z = BigFloat(;precision=precision) + ccall((:mpfr_set_d, :libmpfr), Int32, (Ref{BigFloat}, Float64, MPFRRoundingMode), z, x, r) if isnan(x) && signbit(x) != signbit(z) z.sign = -z.sign end return z end -function BigFloat(x::BigInt) - z = BigFloat() - ccall((:mpfr_set_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Int32), z, x, ROUNDING_MODE[]) +function BigFloat(x::BigInt, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) + z = BigFloat(;precision=precision) + ccall((:mpfr_set_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, r) return z end -BigFloat(x::Integer) = BigFloat(BigInt(x)) +BigFloat(x::Integer, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = + BigFloat(BigInt(x), r; precision=precision) + +BigFloat(x::Union{Bool,Int8,Int16,Int32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = + BigFloat(convert(Clong, x), r; precision=precision) +BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = + BigFloat(convert(Culong, x), r; precision=precision) -BigFloat(x::Union{Bool,Int8,Int16,Int32}) = BigFloat(convert(Clong, x)) -BigFloat(x::Union{UInt8,UInt16,UInt32}) = BigFloat(convert(Culong, x)) +BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = + BigFloat(Float64(x), r; precision=precision) -BigFloat(x::Union{Float16,Float32}) = BigFloat(Float64(x)) -BigFloat(x::Rational) = BigFloat(numerator(x)) / BigFloat(denominator(x)) +BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = + BigFloat(numerator(x), r ;precision=precision) / BigFloat(denominator(x), r ;precision=precision) -function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer = 0) +function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=precision(BigFloat), rounding::MPFRRoundingMode=ROUNDING_MODE[]) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) - z = BigFloat() - err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, Int32), z, s, base, ROUNDING_MODE[]) + z = BigFloat(precision=precision) + err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, MPFRRoundingMode), z, s, base, rounding) err == 0 ? z : nothing end @@ -164,72 +218,54 @@ AbstractFloat(x::BigInt) = BigFloat(x) float(::Type{BigInt}) = BigFloat -# generic constructor with arbitrary precision: -""" - BigFloat(x, prec::Int) +BigFloat(x::Real, r::RoundingMode; precision::Integer=precision(BigFloat)) = + BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) +BigFloat(x::String, r::RoundingMode; precision::Integer=precision(BigFloat)) = + BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) -Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec`. -""" -function BigFloat(x, prec::Int) - setprecision(BigFloat, prec) do - BigFloat(x) - end -end +# TODO: deprecate in 2.0 +BigFloat(x, prec::Int) = BigFloat(x; precision=prec) +BigFloat(x, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) +# avoid ambiguity -""" - BigFloat(x, prec::Int, rounding::RoundingMode) +BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec) +BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) -Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec` and -[`Rounding Mode`](@ref Base.Rounding.RoundingMode) `rounding`. -""" -function BigFloat(x, prec::Int, rounding::RoundingMode) - setrounding(BigFloat, rounding) do - BigFloat(x, prec) - end -end - -""" - BigFloat(x, rounding::RoundingMode) - -Create a representation of `x` as a [`BigFloat`](@ref) with the current global precision -and [`Rounding Mode`](@ref Base.Rounding.RoundingMode) `rounding`. -""" -function BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) - BigFloat(x, precision(BigFloat), rounding) -end """ BigFloat(x::String) Create a representation of the string `x` as a [`BigFloat`](@ref). """ -BigFloat(x::AbstractString) = parse(BigFloat, x) +BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision=precision(BigFloat)) = parse(BigFloat, x; precision=precision, rounding=r) ## BigFloat -> Integer -function unsafe_cast(::Type{Int64}, x::BigFloat, ri::Cint) - ccall((:__gmpfr_mpfr_get_sj,:libmpfr), Cintmax_t, (Ref{BigFloat}, Cint), x, ri) +unsafe_cast(T, x::BigFloat, r::RoundingMode) = unsafe_cast(T, x, convert(MPFRRoundingMode, r)) + +function unsafe_cast(::Type{Int64}, x::BigFloat, r::MPFRRoundingMode) + ccall((:__gmpfr_mpfr_get_sj,:libmpfr), Cintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) end -function unsafe_cast(::Type{UInt64}, x::BigFloat, ri::Cint) - ccall((:__gmpfr_mpfr_get_uj,:libmpfr), Cuintmax_t, (Ref{BigFloat}, Cint), x, ri) +function unsafe_cast(::Type{UInt64}, x::BigFloat, r::MPFRRoundingMode) + ccall((:__gmpfr_mpfr_get_uj,:libmpfr), Cuintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) end -function unsafe_cast(::Type{T}, x::BigFloat, ri::Cint) where T<:Signed - unsafe_cast(Int64, x, ri) % T +function unsafe_cast(::Type{T}, x::BigFloat, r::MPFRRoundingMode) where T<:Signed + unsafe_cast(Int64, x, r) % T end -function unsafe_cast(::Type{T}, x::BigFloat, ri::Cint) where T<:Unsigned - unsafe_cast(UInt64, x, ri) % T +function unsafe_cast(::Type{T}, x::BigFloat, r::MPFRRoundingMode) where T<:Unsigned + unsafe_cast(UInt64, x, r) % T end -function unsafe_cast(::Type{BigInt}, x::BigFloat, ri::Cint) +function unsafe_cast(::Type{BigInt}, x::BigFloat, r::MPFRRoundingMode) # actually safe, just keep naming consistent z = BigInt() - ccall((:mpfr_get_z, :libmpfr), Int32, (Ref{BigInt}, Ref{BigFloat}, Int32), z, x, ri) + ccall((:mpfr_get_z, :libmpfr), Int32, (Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, x, r) return z end -unsafe_cast(::Type{Int128}, x::BigFloat, ri::Cint) = Int128(unsafe_cast(BigInt, x, ri)) -unsafe_cast(::Type{UInt128}, x::BigFloat, ri::Cint) = UInt128(unsafe_cast(BigInt, x, ri)) -unsafe_cast(::Type{T}, x::BigFloat, r::RoundingMode) where {T<:Integer} = unsafe_cast(T, x, to_mpfr(r)) +unsafe_cast(::Type{Int128}, x::BigFloat, r::MPFRRoundingMode) = Int128(unsafe_cast(BigInt, x, r)) +unsafe_cast(::Type{UInt128}, x::BigFloat, r::MPFRRoundingMode) = UInt128(unsafe_cast(BigInt, x, r)) +unsafe_cast(::Type{T}, x::BigFloat, r::MPFRRoundingMode) where {T<:Integer} = unsafe_cast(T, x, r) unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_cast(T, x, RoundToZero) @@ -282,16 +318,16 @@ end _cpynansgn(x::AbstractFloat, y::BigFloat) = isnan(x) && signbit(x) != signbit(y) ? -x : x Float64(x::BigFloat) = - _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, Int32), x, ROUNDING_MODE[]), x) + _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, ROUNDING_MODE[]), x) Float32(x::BigFloat) = - _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, Int32), x, ROUNDING_MODE[]), x) + _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, ROUNDING_MODE[]), x) # TODO: avoid double rounding Float16(x::BigFloat) = Float16(Float32(x)) -Float64(x::BigFloat, r::RoundingMode) = - _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, Int32), x, to_mpfr(r)), x) -Float32(x::BigFloat, r::RoundingMode) = - _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, Int32), x, to_mpfr(r)), x) +Float64(x::BigFloat, r::MPFRRoundingMode) = + _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) +Float32(x::BigFloat, r::MPFRRoundingMode) = + _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) # TODO: avoid double rounding Float16(x::BigFloat, r::RoundingMode) = Float16(Float32(x, r)) @@ -315,14 +351,14 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end # Unsigned Integer function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::CulongMax, x::BigFloat) = ($fJ)(x,c) @@ -330,7 +366,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::ClongMax, x::BigFloat) = ($fJ)(x,c) @@ -338,7 +374,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::CdoubleMax, x::BigFloat) = ($fJ)(x,c) @@ -346,7 +382,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::BigInt, x::BigFloat) = ($fJ)(x,c) @@ -358,50 +394,50 @@ for (fJ, fC) in ((:-,:sub), (:/,:div)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end # Unsigned Int function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::CulongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:ui_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, Int32), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:ui_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::ClongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:si_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, Int32), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:si_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::CdoubleMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:d_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, Int32), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:d_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, Int32), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end # no :mpfr_z_div function @@ -410,7 +446,7 @@ end function -(c::BigInt, x::BigFloat) z = BigFloat() - ccall((:mpfr_z_sub, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, Int32), z, c, x, ROUNDING_MODE[]) + ccall((:mpfr_z_sub, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end @@ -418,7 +454,7 @@ inv(x::BigFloat) = one(Clong) / x # faster than fallback one(x)/x function fma(x::BigFloat, y::BigFloat, z::BigFloat) r = BigFloat() - ccall(("mpfr_fma",:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), r, x, y, z, ROUNDING_MODE[]) + ccall(("mpfr_fma",:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), r, x, y, z, ROUNDING_MODE[]) return r end @@ -426,7 +462,7 @@ end # BigFloat function div(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_div,:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, to_mpfr(RoundToZero)) + ccall((:mpfr_div,:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -434,13 +470,13 @@ end # Unsigned Int function div(x::BigFloat, c::CulongMax) z = BigFloat() - ccall((:mpfr_div_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), z, x, c, to_mpfr(RoundToZero)) + ccall((:mpfr_div_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::CulongMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_ui_div, :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, Int32), z, c, x, to_mpfr(RoundToZero)) + ccall((:mpfr_ui_div, :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -448,13 +484,13 @@ end # Signed Integer function div(x::BigFloat, c::ClongMax) z = BigFloat() - ccall((:mpfr_div_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, x, c, to_mpfr(RoundToZero)) + ccall((:mpfr_div_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::ClongMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_si_div, :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, Int32), z, c, x, to_mpfr(RoundToZero)) + ccall((:mpfr_si_div, :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -462,13 +498,13 @@ end # Float32/Float64 function div(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall((:mpfr_div_d, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, Int32), z, x, c, to_mpfr(RoundToZero)) + ccall((:mpfr_div_d, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::CdoubleMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_d_div, :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, Int32), z, c, x, to_mpfr(RoundToZero)) + ccall((:mpfr_d_div, :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -476,7 +512,7 @@ end # BigInt function div(x::BigFloat, c::BigInt) z = BigFloat() - ccall((:mpfr_div_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, Int32), z, x, c, to_mpfr(RoundToZero)) + ccall((:mpfr_div_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, RoundToZero) ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -487,23 +523,23 @@ for (fJ, fC, fI) in ((:+, :add, 0), (:*, :mul, 1)) @eval begin function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, d, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, d, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, z, e, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, e, ROUNDING_MODE[]) return z end end @@ -511,14 +547,14 @@ end function -(x::BigFloat) z = BigFloat() - ccall((:mpfr_neg, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall((:mpfr_neg, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end function sqrt(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall((:mpfr_sqrt, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall((:mpfr_sqrt, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -527,25 +563,25 @@ sqrt(x::BigInt) = sqrt(BigFloat(x)) function ^(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_pow, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::CulongMax) z = BigFloat() - ccall((:mpfr_pow_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::ClongMax) z = BigFloat() - ccall((:mpfr_pow_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::BigInt) z = BigFloat() - ccall((:mpfr_pow_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -555,7 +591,7 @@ end for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, :cbrt) @eval function $f(x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end end @@ -563,7 +599,7 @@ end function sincos_fast(v::BigFloat) s = BigFloat() c = BigFloat() - ccall((:mpfr_sin_cos, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), s, c, v, ROUNDING_MODE[]) + ccall((:mpfr_sin_cos, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), s, c, v, ROUNDING_MODE[]) return (s, c) end sincos(v::BigFloat) = sincos_fast(v) @@ -571,18 +607,18 @@ sincos(v::BigFloat) = sincos_fast(v) # return log(2) function big_ln2() c = BigFloat() - ccall((:mpfr_const_log2, :libmpfr), Cint, (Ref{BigFloat}, Int32), c, MPFR.ROUNDING_MODE[]) + ccall((:mpfr_const_log2, :libmpfr), Cint, (Ref{BigFloat}, MPFRRoundingMode), c, MPFR.ROUNDING_MODE[]) return c end function ldexp(x::BigFloat, n::Clong) z = BigFloat() - ccall((:mpfr_mul_2si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) return z end function ldexp(x::BigFloat, n::Culong) z = BigFloat() - ccall((:mpfr_mul_2ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) return z end ldexp(x::BigFloat, n::ClongMax) = ldexp(x, convert(Clong, n)) @@ -595,13 +631,13 @@ function factorial(x::BigFloat) end ui = convert(Culong, x) z = BigFloat() - ccall((:mpfr_fac_ui, :libmpfr), Int32, (Ref{BigFloat}, Culong, Int32), z, ui, ROUNDING_MODE[]) + ccall((:mpfr_fac_ui, :libmpfr), Int32, (Ref{BigFloat}, Culong, MPFRRoundingMode), z, ui, ROUNDING_MODE[]) return z end function hypot(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_hypot, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_hypot, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -612,7 +648,7 @@ for f in (:log, :log2, :log10) "with a complex argument. Try ", $f, "(complex(x))."))) end z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end end @@ -623,7 +659,7 @@ function log1p(x::BigFloat) "with a complex argument. Try log1p(complex(x))."))) end z = BigFloat() - ccall((:mpfr_log1p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall((:mpfr_log1p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end @@ -631,7 +667,7 @@ function max(x::BigFloat, y::BigFloat) isnan(x) && return x isnan(y) && return y z = BigFloat() - ccall((:mpfr_max, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_max, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -639,7 +675,7 @@ function min(x::BigFloat, y::BigFloat) isnan(x) && return x isnan(y) && return y z = BigFloat() - ccall((:mpfr_min, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_min, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -647,19 +683,19 @@ function modf(x::BigFloat) isinf(x) && return (BigFloat(NaN), x) zint = BigFloat() zfloat = BigFloat() - ccall((:mpfr_modf, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), zint, zfloat, x, ROUNDING_MODE[]) + ccall((:mpfr_modf, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), zint, zfloat, x, ROUNDING_MODE[]) return (zfloat, zint) end function rem(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_fmod, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_fmod, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function rem(x::BigFloat, y::BigFloat, ::RoundingMode{:Nearest}) z = BigFloat() - ccall((:mpfr_remainder, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_remainder, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -670,7 +706,7 @@ function sum(arr::AbstractArray{BigFloat}) z = BigFloat(0) for i in arr ccall((:mpfr_add, :libmpfr), Int32, - (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Cint), z, z, i, 0) + (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, i, ROUNDING_MODE[]) end return z end @@ -681,7 +717,7 @@ for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :at function ($f)(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -690,7 +726,7 @@ end function atan(y::BigFloat, x::BigFloat) z = BigFloat() - ccall((:mpfr_atan2, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, y, x, ROUNDING_MODE[]) + ccall((:mpfr_atan2, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, y, x, ROUNDING_MODE[]) return z end @@ -769,38 +805,9 @@ setprecision(precision::Int) = setprecision(BigFloat, precision) maxintfloat(x::BigFloat) = BigFloat(2)^precision(x) maxintfloat(::Type{BigFloat}) = BigFloat(2)^precision(BigFloat) -to_mpfr(::RoundingMode{:Nearest}) = Cint(0) -to_mpfr(::RoundingMode{:ToZero}) = Cint(1) -to_mpfr(::RoundingMode{:Up}) = Cint(2) -to_mpfr(::RoundingMode{:Down}) = Cint(3) -to_mpfr(::RoundingMode{:FromZero}) = Cint(4) - -function from_mpfr(c::Integer) - if c == 0 - return RoundNearest - elseif c == 1 - return RoundToZero - elseif c == 2 - return RoundUp - elseif c == 3 - return RoundDown - elseif c == 4 - return RoundFromZero - else - throw(ArgumentError("invalid MPFR rounding mode code: $c")) - end - RoundingMode(c) -end - -rounding_raw(::Type{BigFloat}) = ROUNDING_MODE[] -setrounding_raw(::Type{BigFloat},i::Integer) = ROUNDING_MODE[] = i - -rounding(::Type{BigFloat}) = from_mpfr(rounding_raw(BigFloat)) -setrounding(::Type{BigFloat},r::RoundingMode) = setrounding_raw(BigFloat,to_mpfr(r)) - function copysign(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_copysign, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_copysign, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -815,16 +822,16 @@ end function frexp(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, Cint), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) return (z, c[]) end function significand(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, Cint), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) # Double the significand to make it work as Base.significand - ccall((:mpfr_mul_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, Int32), z, z, 2, ROUNDING_MODE[]) + ccall((:mpfr_mul_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, z, 2, ROUNDING_MODE[]) return z end @@ -864,7 +871,7 @@ isone(x::BigFloat) = x == Clong(1) function nextfloat(x::BigFloat) z = BigFloat() - ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), + 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 @@ -872,7 +879,7 @@ end function prevfloat(x::BigFloat) z = BigFloat() - ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), + 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 @@ -906,7 +913,7 @@ function setprecision(f::Function, ::Type{T}, prec::Integer) where T end end -setprecision(f::Function, precision::Integer) = setprecision(f, BigFloat, precision) +setprecision(f::Function, prec::Integer) = setprecision(f, BigFloat, prec) function string_mpfr(x::BigFloat, fmt::String) buf = Base.StringVector(0) diff --git a/base/parse.jl b/base/parse.jl index ecbfdbe3f92b1..e66df6044dd8c 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -347,8 +347,8 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: end return result end -function tryparse_internal(::Type{T}, s::AbstractString, raise::Bool) where T<:Real - result = tryparse(T, s) +function tryparse_internal(::Type{T}, s::AbstractString, raise::Bool; kwargs...) where T<:Real + result = tryparse(T, s; kwargs...) if raise && result === nothing _parse_failure(T, s) end @@ -360,8 +360,8 @@ end tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, raise::Bool) where T<:Integer = tryparse_internal(T, s, startpos, endpos, 10, raise) -parse(::Type{T}, s::AbstractString) where T<:Real = - convert(T, tryparse_internal(T, s, true)) +parse(::Type{T}, s::AbstractString; kwargs...) where T<:Real = + convert(T, tryparse_internal(T, s, true; kwargs...)) parse(::Type{T}, s::AbstractString) where T<:Complex = convert(T, tryparse_internal(T, s, firstindex(s), lastindex(s), true)) diff --git a/base/sysimg.jl b/base/sysimg.jl index dd605b06417f7..cdf2856da34ae 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -361,6 +361,10 @@ using .FastMath function deepcopy_internal end +# enums +include("Enums.jl") +using .Enums + # BigInts and BigFloats include("gmp.jl") using .GMP @@ -393,10 +397,6 @@ include("printf.jl") # metaprogramming include("meta.jl") -# enums -include("Enums.jl") -using .Enums - # concurrency and parallelism include("channels.jl") From c2099acafbcccd5b4d7cbc49b63fb89d992f6d0f Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 13 Sep 2018 13:13:34 -0700 Subject: [PATCH 2/9] fix docs --- base/mpfr.jl | 50 ++++++++++++++++++++++++----------------- doc/src/base/numbers.md | 5 +---- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 0cbfb0f617666..39f009e88f927 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -129,27 +129,41 @@ Base.unsafe_convert(::Type{Ref{BigFloat}}, x::Ptr{BigFloat}) = x return convert(Ptr{BigFloat}, Base.pointer_from_objref(x)) end - """ - BigFloat(x) + BigFloat(x::Union{Real, AbstractString} [, rounding::RoundingMode=rounding(BigFloat)]; [precision::Integer=precision(BigFloat)]) + +Create an arbitrary precision floating point number from `x`, with precision +`precision`. The `rounding` argument specifies the direction in which the result should be +rounded if the conversion cannot be done exactly. If not provided, these are set by the current global values. -Create an arbitrary precision floating point number. `x` may be an [`Integer`](@ref), a -[`Float64`](@ref) or a [`BigInt`](@ref). The usual mathematical operators are defined for -this type, and results are promoted to a [`BigFloat`](@ref). +`BigFloat(x::Real)` is the same as `convert(BigFloat,x)`, except if `x` itself is already +`BigFloat`, in which case it will return a value with the precision set to the current +global precision; `convert` will always return `x`. -Note that because decimal literals are converted to floating point numbers when parsed, -`BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize -constants from strings via [`parse`](@ref), or using the `big` string literal. +`BigFloat(x::AbstractString)` is identical to [`parse`](@ref), but is provided for +convenience since decimal literals are converted to floating point numbers when parsed. +`BigFloat(2.1)` may not yield what you expect. ```jldoctest -julia> BigFloat(2.1) +julia> BigFloat(2.1) # 2.1 here is a Float64 2.100000000000000088817841970012523233890533447265625 -julia> big"2.1" +julia> BigFloat("2.1") # the closest BigFloat to 2.1 2.099999999999999999999999999999999999999999999999999999999999999999999999999986 + +julia> BigFloat("2.1", RoundUp) +2.100000000000000000000000000000000000000000000000000000000000000000000000000021 + +julia> BigFloat("2.1", RoundUp, precision=128) +2.100000000000000000000000000000000000007 ``` + +# See also +- [`@big_str`](@ref) +- [`rounding`](@ref) and [`setrounding`](@ref) +- [`precision`](@ref) and [`setprecision`](@ref) """ -BigFloat(x) +BigFloat(x, r::RoundingMode) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat @@ -213,6 +227,9 @@ function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precisio err == 0 ? z : nothing end +BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision=precision(BigFloat)) = + parse(BigFloat, x; precision=precision, rounding=r) + Rational(x::BigFloat) = convert(Rational{BigInt}, x) AbstractFloat(x::BigInt) = BigFloat(x) @@ -220,7 +237,7 @@ float(::Type{BigInt}) = BigFloat BigFloat(x::Real, r::RoundingMode; precision::Integer=precision(BigFloat)) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) -BigFloat(x::String, r::RoundingMode; precision::Integer=precision(BigFloat)) = +BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=precision(BigFloat)) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) # TODO: deprecate in 2.0 @@ -231,15 +248,6 @@ BigFloat(x, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec) BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) - -""" - BigFloat(x::String) - -Create a representation of the string `x` as a [`BigFloat`](@ref). -""" -BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision=precision(BigFloat)) = parse(BigFloat, x; precision=precision, rounding=r) - - ## BigFloat -> Integer unsafe_cast(T, x::BigFloat, r::RoundingMode) = unsafe_cast(T, x, convert(MPFRRoundingMode, r)) diff --git a/doc/src/base/numbers.md b/doc/src/base/numbers.md index 50e6d2b7134da..f07f7f586d826 100644 --- a/doc/src/base/numbers.md +++ b/doc/src/base/numbers.md @@ -120,13 +120,10 @@ and for [`BigInt`](@ref) the [GNU Multiple Precision Arithmetic Library (GMP)] (https://gmplib.org) is used. ```@docs -Base.MPFR.BigFloat(::Any) +Base.MPFR.BigFloat(::Any, rounding::RoundingMode) Base.precision Base.MPFR.precision(::Type{BigFloat}) Base.MPFR.setprecision -Base.MPFR.BigFloat(x, prec::Int) -Base.MPFR.BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) -Base.MPFR.BigFloat(x, prec::Int, rounding::RoundingMode) Base.GMP.BigInt(::Any) Base.@big_str ``` From 1004df65b8bee4e7abde570f13fa65abcde75035 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Fri, 14 Sep 2018 10:50:54 -0700 Subject: [PATCH 3/9] fix Clong issue on win 64 --- base/mpfr.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 39f009e88f927..d5fa47e9254b5 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -72,7 +72,7 @@ function convert(::Type{RoundingMode}, r::MPFRRoundingMode) end const ROUNDING_MODE = Ref{MPFRRoundingMode}(MPFRRoundNearest) -const DEFAULT_PRECISION = Ref{Int}(256) +const DEFAULT_PRECISION = Ref{Clong}(256) # Basic type and initialization definitions @@ -107,7 +107,7 @@ mutable struct BigFloat <: AbstractFloat #d = Vector{Limb}(undef, nb) d = _string_n(nb * Core.sizeof(Limb)) EXP_NAN = Clong(1) - Clong(typemax(Culong) >> 1) - return _BigFloat(precision, one(Cint), EXP_NAN, d) # +NAN + return _BigFloat(Clong(precision), one(Cint), EXP_NAN, d) # +NAN end end @@ -800,7 +800,7 @@ precision(::Type{BigFloat}) = DEFAULT_PRECISION[] # precision of the type BigFlo Set the precision (in bits) to be used for `T` arithmetic. """ -function setprecision(::Type{BigFloat}, precision::Int) +function setprecision(::Type{BigFloat}, precision::Integer) if precision < 2 throw(DomainError(precision, "`precision` cannot be less than 2.")) end From 2c2c0d31deb99457a9bccf1620b6b7a09b9e5fc1 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Fri, 14 Sep 2018 16:44:50 -0700 Subject: [PATCH 4/9] more Int32 stuff --- base/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index d5fa47e9254b5..fc92f0ed12e78 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -808,7 +808,7 @@ function setprecision(::Type{BigFloat}, precision::Integer) return precision end -setprecision(precision::Int) = setprecision(BigFloat, precision) +setprecision(precision::Integer) = setprecision(BigFloat, precision) maxintfloat(x::BigFloat) = BigFloat(2)^precision(x) maxintfloat(::Type{BigFloat}) = BigFloat(2)^precision(BigFloat) From 24f46695f7d0141de4ffb1c0a263cfb4a21512ba Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 17 Sep 2018 14:10:48 -0700 Subject: [PATCH 5/9] add more documentation --- base/mpfr.jl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index fc92f0ed12e78..16854ebdd9c96 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -39,14 +39,21 @@ function __init__() nothing end -# Matches the MPFR_RNDN, etc. -# https://www.mpfr.org/mpfr-current/mpfr.html#Rounding-Modes +""" + MPFR.MPFRRoundingMode + +Matches the `mpfr_rnd_t` enum provided by MPFR, see +https://www.mpfr.org/mpfr-current/mpfr.html#Rounding-Modes + +This is for internal use, and ensures that `ROUNDING_MODE[]` is type-stable. +""" @enum MPFRRoundingMode begin MPFRRoundNearest MPFRRoundToZero MPFRRoundUp MPFRRoundDown MPFRRoundFromZero + MPFRRoundFaithful end convert(::Type{MPFRRoundingMode}, ::RoundingMode{:Nearest}) = MPFRRoundNearest @@ -140,8 +147,8 @@ rounded if the conversion cannot be done exactly. If not provided, these are set `BigFloat`, in which case it will return a value with the precision set to the current global precision; `convert` will always return `x`. -`BigFloat(x::AbstractString)` is identical to [`parse`](@ref), but is provided for -convenience since decimal literals are converted to floating point numbers when parsed. +`BigFloat(x::AbstractString)` is identical to [`parse`](@ref). This is provided for +convenience since decimal literals are converted to `Float64` when parsed, so `BigFloat(2.1)` may not yield what you expect. ```jldoctest @@ -249,6 +256,12 @@ BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec) BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) ## BigFloat -> Integer +""" + MPFR.unsafe_cast(T, x::BigFloat, r::RoundingMode) + +Convert `x` to integer type `T`, rounding the direction of `r`. If the value is not +representable by T, an arbitrary value will be returned. +""" unsafe_cast(T, x::BigFloat, r::RoundingMode) = unsafe_cast(T, x, convert(MPFRRoundingMode, r)) function unsafe_cast(::Type{Int64}, x::BigFloat, r::MPFRRoundingMode) From 9eb89c85382fb5d274cffe7e98055ec2a0431b82 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 17 Sep 2018 14:27:43 -0700 Subject: [PATCH 6/9] keep `precision(BigFloat)` returning an `Int`, to avoid breaking APIs --- base/mpfr.jl | 30 +++++++++++++++--------------- stdlib/Random/src/generation.jl | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 16854ebdd9c96..7294cba5c5962 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -108,7 +108,7 @@ mutable struct BigFloat <: AbstractFloat return new(prec, sign, exp, pointer(d), d) end - function BigFloat(; precision::Integer=precision(BigFloat)) + function BigFloat(; precision::Integer=DEFAULT_PRECISION[]) nb = ccall((:mpfr_custom_get_size,:libmpfr), Csize_t, (Clong,), precision) nb = (nb + Core.sizeof(Limb) - 1) ÷ Core.sizeof(Limb) # align to number of Limb allocations required for this #d = Vector{Limb}(undef, nb) @@ -175,7 +175,7 @@ BigFloat(x, r::RoundingMode) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat -function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) +function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) if precision == MPFR.precision(x) x else @@ -190,7 +190,7 @@ end # convert to BigFloat for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) @eval begin - function BigFloat(x::($fC), r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) + function BigFloat(x::($fC), r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) ccall(($(string(:mpfr_set_,fJ)), :libmpfr), Int32, (Ref{BigFloat}, $fC, MPFRRoundingMode), z, x, r) return z @@ -198,7 +198,7 @@ for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) end end -function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) +function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) ccall((:mpfr_set_d, :libmpfr), Int32, (Ref{BigFloat}, Float64, MPFRRoundingMode), z, x, r) if isnan(x) && signbit(x) != signbit(z) @@ -207,34 +207,34 @@ function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::In return z end -function BigFloat(x::BigInt, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) +function BigFloat(x::BigInt, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) ccall((:mpfr_set_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, r) return z end -BigFloat(x::Integer, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = +BigFloat(x::Integer, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(BigInt(x), r; precision=precision) -BigFloat(x::Union{Bool,Int8,Int16,Int32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = +BigFloat(x::Union{Bool,Int8,Int16,Int32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(convert(Clong, x), r; precision=precision) -BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = +BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(convert(Culong, x), r; precision=precision) -BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = +BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(Float64(x), r; precision=precision) -BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=precision(BigFloat)) = +BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(numerator(x), r ;precision=precision) / BigFloat(denominator(x), r ;precision=precision) -function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=precision(BigFloat), rounding::MPFRRoundingMode=ROUNDING_MODE[]) +function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=DEFAULT_PRECISION[], rounding::MPFRRoundingMode=ROUNDING_MODE[]) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) z = BigFloat(precision=precision) err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, MPFRRoundingMode), z, s, base, rounding) err == 0 ? z : nothing end -BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision=precision(BigFloat)) = +BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = parse(BigFloat, x; precision=precision, rounding=r) Rational(x::BigFloat) = convert(Rational{BigInt}, x) @@ -242,9 +242,9 @@ AbstractFloat(x::BigInt) = BigFloat(x) float(::Type{BigInt}) = BigFloat -BigFloat(x::Real, r::RoundingMode; precision::Integer=precision(BigFloat)) = +BigFloat(x::Real, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) -BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=precision(BigFloat)) = +BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) # TODO: deprecate in 2.0 @@ -806,7 +806,7 @@ end Get the precision (in bits) currently used for [`BigFloat`](@ref) arithmetic. """ -precision(::Type{BigFloat}) = DEFAULT_PRECISION[] # precision of the type BigFloat itself +precision(::Type{BigFloat}) = Int(DEFAULT_PRECISION[]) # precision of the type BigFloat itself """ setprecision([T=BigFloat,] precision::Int) diff --git a/stdlib/Random/src/generation.jl b/stdlib/Random/src/generation.jl index 7ec0c3930eb32..7451de367e89b 100644 --- a/stdlib/Random/src/generation.jl +++ b/stdlib/Random/src/generation.jl @@ -81,7 +81,7 @@ function _rand(rng::AbstractRNG, sp::SamplerBigFloat, ::CloseOpen01{BigFloat}) z.exp = 0 randbool && ccall((:mpfr_sub_d, :libmpfr), Int32, - (Ref{BigFloat}, Ref{BigFloat}, Cdouble, Int32), + (Ref{BigFloat}, Ref{BigFloat}, Cdouble, Base.MPFR.MPFRRoundingMode), z, z, 0.5, Base.MPFR.ROUNDING_MODE[]) z end @@ -90,7 +90,7 @@ end # TODO: make an API for requesting full or not-full precision function _rand(rng::AbstractRNG, sp::SamplerBigFloat, ::CloseOpen01{BigFloat}, ::Nothing) z = _rand(rng, sp, CloseOpen12(BigFloat)) - ccall((:mpfr_sub_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Int32), + ccall((:mpfr_sub_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, Base.MPFR.MPFRRoundingMode), z, z, 1, Base.MPFR.ROUNDING_MODE[]) z end From 1831e3a127c3bb2a4d7bad4715a492437ab228c4 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Sun, 7 Oct 2018 13:35:24 -0700 Subject: [PATCH 7/9] fix based on comments --- base/mpfr.jl | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 7294cba5c5962..5b914b63fe9e9 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -225,7 +225,7 @@ BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precisi BigFloat(Float64(x), r; precision=precision) BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = - BigFloat(numerator(x), r ;precision=precision) / BigFloat(denominator(x), r ;precision=precision) + BigFloat(numerator(x), r; precision=precision) / BigFloat(denominator(x), r ;precision=precision) function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=DEFAULT_PRECISION[], rounding::MPFRRoundingMode=ROUNDING_MODE[]) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) @@ -286,7 +286,6 @@ function unsafe_cast(::Type{BigInt}, x::BigFloat, r::MPFRRoundingMode) end unsafe_cast(::Type{Int128}, x::BigFloat, r::MPFRRoundingMode) = Int128(unsafe_cast(BigInt, x, r)) unsafe_cast(::Type{UInt128}, x::BigFloat, r::MPFRRoundingMode) = UInt128(unsafe_cast(BigInt, x, r)) -unsafe_cast(::Type{T}, x::BigFloat, r::MPFRRoundingMode) where {T<:Integer} = unsafe_cast(T, x, r) unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_cast(T, x, RoundToZero) @@ -335,22 +334,18 @@ function (::Type{T})(x::BigFloat) where T<:Integer end ## BigFloat -> AbstractFloat - _cpynansgn(x::AbstractFloat, y::BigFloat) = isnan(x) && signbit(x) != signbit(y) ? -x : x -Float64(x::BigFloat) = - _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, ROUNDING_MODE[]), x) -Float32(x::BigFloat) = - _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, ROUNDING_MODE[]), x) -# TODO: avoid double rounding -Float16(x::BigFloat) = Float16(Float32(x)) - -Float64(x::BigFloat, r::MPFRRoundingMode) = +Float64(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) -Float32(x::BigFloat, r::MPFRRoundingMode) = +Float64(x::BigFloat, r::RoundingMode) = Float64(x, convert(MPFRRoundingMode, r)) + +Float32(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) +Float32(x::BigFloat, r::RoundingMode) = Float32(x, convert(MPFRRoundingMode, r)) + # TODO: avoid double rounding -Float16(x::BigFloat, r::RoundingMode) = Float16(Float32(x, r)) +Float16(x::BigFloat) = Float16(Float32(x)) promote_rule(::Type{BigFloat}, ::Type{<:Real}) = BigFloat promote_rule(::Type{BigInt}, ::Type{<:AbstractFloat}) = BigFloat From ded6e2f00426a5f9b60ca72cc0e7a784003bd362 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 31 Oct 2018 13:28:26 -0700 Subject: [PATCH 8/9] move to deprecated.jl --- base/deprecated.jl | 5 +++++ base/mpfr.jl | 8 -------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 9c370d5d6213a..7d765ae86a135 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -168,4 +168,9 @@ function promote_eltype_op end one(::CartesianIndex{N}) where {N} = one(CartesianIndex{N}) one(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 1, Val(N))) +MPFR.BigFloat(x, prec::Int) = BigFloat(x; precision=prec) +MPFR.BigFloat(x, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) +MPFR.BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec) +MPFR.BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) + # END 1.0 deprecations diff --git a/base/mpfr.jl b/base/mpfr.jl index 8176ca2c69cd7..3d3b8ed3e3f1a 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -247,14 +247,6 @@ BigFloat(x::Real, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) -# TODO: deprecate in 2.0 -BigFloat(x, prec::Int) = BigFloat(x; precision=prec) -BigFloat(x, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) -# avoid ambiguity - -BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec) -BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec) - ## BigFloat -> Integer """ MPFR.unsafe_cast(T, x::BigFloat, r::RoundingMode) From 872435d3bdfcd0c8172d0ecea741413f3f8161b5 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 19 Nov 2018 10:22:23 +1100 Subject: [PATCH 9/9] add NEWS entry --- NEWS.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4f785147c0498..812bf523cef8e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,7 +11,9 @@ Language changes ---------------- * the constructor `BigFloat(::BigFloat)` now respects the global precision setting and always - returns a `BigFloat` with precision equal to `precision(BigFloat)` ([#29127]). + returns a `BigFloat` with precision equal to `precision(BigFloat)` ([#29127]). The optional + `precision` argument to override the global setting is now a keyword instead of positional + argument ([#29157]). * Parser inputs ending with a comma are now consistently treated as incomplete. Previously they were sometimes parsed as tuples, depending on whitespace ([#28506]). * `Regex` now behave like a scalar when used in broadcasting ([#29913]).