Skip to content

Commit

Permalink
refactor RoundingModes to be instances instead of types
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Sep 3, 2013
1 parent c0e861a commit 4012427
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 41 deletions.
43 changes: 17 additions & 26 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module MPFR

export
BigFloat,
RoundFromZero,
get_bigfloat_precision,
set_bigfloat_precision,
with_bigfloat_precision,
Expand All @@ -20,18 +19,13 @@ import
gamma, lgamma, digamma, erf, erfc, zeta, log1p, airyai, iceil, ifloor,
itrunc, eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2,
serialize, deserialize, inf, nan, hash,
RoundingMode, RoundDown, RoundingMode, RoundNearest, RoundToZero,
RoundUp
serialize, deserialize, inf, nan, hash

import Base.Math.lgamma_r

const ROUNDING_MODE = [0]
const DEFAULT_PRECISION = [256]

# Rounding modes
type RoundFromZero <: RoundingMode end

# Basic type and initialization definitions

type BigFloat <: FloatingPoint
Expand Down Expand Up @@ -596,26 +590,23 @@ function set_bigfloat_precision(x::Int)
DEFAULT_PRECISION[end] = x
end

function get_bigfloat_rounding()
if ROUNDING_MODE[end] == 0
return RoundNearest
elseif ROUNDING_MODE[end] == 1
return RoundToZero
elseif ROUNDING_MODE[end] == 2
return RoundUp
elseif ROUNDING_MODE[end] == 3
return RoundDown
elseif ROUNDING_MODE[end] == 4
return RoundFromZero
else
error("Invalid rounding mode")
function to_mpfr(r::RoundingMode)
c = r.code
if !(0 <= c <= 4)
error("invalid BigFloat rounding mode")
end
c
end

function from_mpfr(c::Integer)
if !(0 <= c <= 4)
error("invalid MPFR rounding mode code")
end
RoundingMode(c)
end
set_bigfloat_rounding(::Type{RoundNearest}) = ROUNDING_MODE[end] = 0
set_bigfloat_rounding(::Type{RoundToZero}) = ROUNDING_MODE[end] = 1
set_bigfloat_rounding(::Type{RoundUp}) = ROUNDING_MODE[end] = 2
set_bigfloat_rounding(::Type{RoundDown}) = ROUNDING_MODE[end] = 3
set_bigfloat_rounding(::Type{RoundFromZero}) = ROUNDING_MODE[end] = 4

get_bigfloat_rounding() = from_mpfr(ROUNDING_MODE[end])
set_bigfloat_rounding(r::RoundingMode) = ROUNDING_MODE[end] = to_mpfr(r)

function copysign(x::BigFloat, y::BigFloat)
z = BigFloat()
Expand Down Expand Up @@ -694,7 +685,7 @@ function with_bigfloat_precision(f::Function, precision::Integer)
end
end

function with_bigfloat_rounding{T<:RoundingMode}(f::Function, rounding::Type{T})
function with_bigfloat_rounding(f::Function, rounding::RoundingMode)
old_rounding = get_bigfloat_rounding()
set_bigfloat_rounding(rounding)
try
Expand Down
47 changes: 32 additions & 15 deletions base/rounding.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@ module Rounding
include("fenv_constants.jl")

export
RoundingMode, RoundNearest, RoundToZero, RoundUp, RoundDown,
RoundingMode, RoundNearest, RoundToZero, RoundUp, RoundDown, RoundFromZero,
get_rounding, set_rounding, with_rounding

## rounding modes ##
abstract RoundingMode
type RoundNearest <: RoundingMode end
type RoundToZero <: RoundingMode end
type RoundUp <: RoundingMode end
type RoundDown <: RoundingMode end
immutable RoundingMode
code::Int
RoundingMode(c::Integer) = new(c)

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Sep 3, 2013

Member

Is this really necessary? Aren't the only places we call this constructor going to be immediately below this with Int arguments?

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Sep 3, 2013

Author Member

I guess. It's also used in from_mpfr but that's no big deal.

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Sep 3, 2013

Member

This reminds me that I think we should go back to automatically calling convert for inner constructor arguments, in which case this would become redundant.

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Sep 3, 2013

Member
end
const RoundNearest = RoundingMode(0)
const RoundToZero = RoundingMode(1)
const RoundUp = RoundingMode(2)
const RoundDown = RoundingMode(3)
const RoundFromZero = RoundingMode(4)

set_rounding(::Type{RoundNearest}) = ccall(:fesetround, Cint, (Cint, ), JL_FE_TONEAREST)
set_rounding(::Type{RoundToZero}) = ccall(:fesetround, Cint, (Cint, ), JL_FE_TOWARDZERO)
set_rounding(::Type{RoundUp}) = ccall(:fesetround, Cint, (Cint, ), JL_FE_UPWARD)
set_rounding(::Type{RoundDown}) = ccall(:fesetround, Cint, (Cint, ), JL_FE_DOWNWARD)
function to_fenv(r::RoundingMode)
if r === RoundNearest
JL_FE_TONEAREST
elseif r === RoundToZero
JL_FE_TOWARDZERO
elseif r === RoundUp
JL_FE_UPWARD
elseif r === RoundDown
JL_FE_DOWNWARD
elseif r === RoundFromZero
error("unsupported rounding mode")
else
error("invalid rounding mode")
end
end

function get_rounding()
r = ccall(:fegetround, Cint, ())
function from_fenv(r::Integer)
if r == JL_FE_TONEAREST
return RoundNearest
elseif r == JL_FE_DOWNWARD
Expand All @@ -28,11 +42,14 @@ function get_rounding()
elseif r == JL_FE_TOWARDZERO
return RoundToZero
else
error()
error("invalid rounding mode code")
end
end

function with_rounding{T<:RoundingMode}(f::Function, rounding::Type{T})
set_rounding(r::RoundingMode) = ccall(:fesetround, Cint, (Cint,), to_fenv(r))
get_rounding() = from_fenv(ccall(:fegetround, Cint, ()))

function with_rounding(f::Function, rounding::RoundingMode)
old_rounding = get_rounding()
set_rounding(rounding)
try
Expand All @@ -42,4 +59,4 @@ function with_rounding{T<:RoundingMode}(f::Function, rounding::Type{T})
end
end

end #module
end #module

0 comments on commit 4012427

Please sign in to comment.