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

use MPFR-style rounding enum #87

Merged
merged 4 commits into from
Mar 1, 2019
Merged
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ os:
- osx

julia:
- 0.6
- 0.7
- 1.0
- nightly

notifications:
Expand Down
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
julia 0.6
julia 0.7
Compat 0.61.0
BinaryProvider
SpecialFunctions
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
environment:
matrix:
- julia_version: 0.6
- julia_version: 0.7
- julia_version: 1.0
- julia_version: latest

platform:
Expand Down
48 changes: 41 additions & 7 deletions src/DecFP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,41 @@ end

#############################################################################

const rounding = Ref{Ptr{Cuint}}()
@enum DecFPRoundingMode begin
DecFPRoundNearest
DecFPRoundDown
DecFPRoundUp
DecFPRoundToZero
DecFPRoundFromZero
end

# rounding modes, from bid_functions.h
const rounding_c2j = [RoundNearest, RoundDown, RoundUp, RoundToZero, RoundFromZero]
const rounding_j2c = Dict{RoundingMode, UInt32}([(rounding_c2j[i], Cuint(i-1)) for i in 1:length(rounding_c2j)])
Base.convert(::Type{DecFPRoundingMode}, ::RoundingMode{:Nearest}) = DecFPRoundNearest
Base.convert(::Type{DecFPRoundingMode}, ::RoundingMode{:Down}) = DecFPRoundDown
Base.convert(::Type{DecFPRoundingMode}, ::RoundingMode{:Up}) = DecFPRoundUp
Base.convert(::Type{DecFPRoundingMode}, ::RoundingMode{:ToZero}) = DecFPRoundToZero
Base.convert(::Type{DecFPRoundingMode}, ::RoundingMode{:FromZero}) = DecFPRoundFromZero

function Base.convert(::Type{RoundingMode}, r::DecFPRoundingMode)
if r == DecFPRoundNearest
return RoundNearest
elseif r == DecFPRRoundDown
return RoundDown
elseif r == DecFPRRoundUp
return RoundUp
elseif r == DecFPRRoundToZero
return RoundToZero
elseif r == DecFPRRoundFromZero
return RoundFromZero
else
throw(ArgumentError("invalid DecFP rounding mode code: $c"))
end
end

const ROUNDING_PTR = Ref{Ptr{DecFPRoundingMode}}()

# global pointers and dicts must be initialized at runtime (via __init__)
function __init__()
global rounding[] = cglobal((:__bid_IDEC_glbround, libbid), Cuint) # rounding mode
global ROUNDING_PTR[] = cglobal((:__bid_IDEC_glbround, libbid), DecFPRoundingMode) # rounding mode
global flags[] = cglobal((:__bid_IDEC_glbflags, libbid), Cuint) # exception status
unsafe_store!(flags[], 0)
end
Expand All @@ -94,8 +120,16 @@ const INEXACT = 0x20
bidsym(w,s...) = string("__bid", w, "_", s...)

abstract type DecimalFloatingPoint <: AbstractFloat end
Base.rounding(::Type{T}) where {T<:DecimalFloatingPoint} = rounding_c2j[unsafe_load(rounding[])+1]
Base.setrounding(::Type{T}, r::RoundingMode) where {T<:DecimalFloatingPoint} = unsafe_store!(rounding[], rounding_j2c[r])

Base.Rounding.rounding_raw(::Type{T}) where {T<:DecimalFloatingPoint} =
unsafe_load(ROUNDING_PTR[])
Base.Rounding.setrounding_raw(::Type{T}, r::DecFPRoundingMode) where {T<:DecimalFloatingPoint} =
unsafe_store!(ROUNDING_PTR[],r)

Base.Rounding.rounding(::Type{T}) where {T<:DecimalFloatingPoint} =
convert(RoundingMode, Base.Rounding.rounding_raw(T))
Base.Rounding.setrounding(::Type{T}, r::RoundingMode) where {T<:DecimalFloatingPoint} =
Base.Rounding.setrounding_raw(T, convert(DecFPRoundingMode, r))

for w in (32,64,128)
BID = Symbol(string("Dec",w))
Expand Down
7 changes: 7 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,10 @@ end
@test reinterpret(UInt128, Dec128(1.5)) == 0x303e000000000000000000000000000f
# issue #38
@test collect(v for i in 1:1, v in zeros(Dec128, 1)) == zeros(Dec128, 1, 1)

@test setrounding(Dec64, RoundDown) do
Float64(d64"1e100") < 1e100
end

@test Float64(d64"1e100") == 1e100