Skip to content

Commit 90def97

Browse files
committed
consolidate xchk macros
1 parent 5ab7fd9 commit 90def97

File tree

1 file changed

+15
-42
lines changed

1 file changed

+15
-42
lines changed

src/DecFP.jl

+15-42
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,11 @@ function nox(x)
4040
unsafe_store!(flags[], 0)
4141
return x
4242
end
43+
4344
# Check exception flags in mask & throw, otherwise returning x;
44-
# always clearing exceptions. These are macros so that
45+
# always clearing exceptions. This is a macros so that
4546
# the error message is only evaluated if an exception occurs.
46-
47-
macro xchk(x, args...)
48-
mask=0x3f
49-
if !isempty(args) && Meta.isexpr(args[end], :(=)) && args[end].args[1] == :mask # mask=... keyword at end
50-
mask = esc(args[end].args[2])
51-
args = args[1:end-1]
52-
end
53-
quote
54-
ret = $(esc(x))
55-
f = unsafe_load(flags[])
56-
unsafe_store!(flags[], 0)
57-
f & $mask != 0 && xchk_throw(f, $(map(esc,args)...))
58-
ret
59-
end
60-
end
61-
62-
macro xchk1(x, exc, args...)
47+
macro xchk(x, exc, args...)
6348
mask=0x3f
6449
if !isempty(args) && Meta.isexpr(args[end], :(=)) && args[end].args[1] == :mask # mask=... keyword at end
6550
mask = esc(args[end].args[2])
@@ -74,18 +59,6 @@ macro xchk1(x, exc, args...)
7459
end
7560
end
7661

77-
# separate this exception throwing code into a function to avoid
78-
# inlining it over and over in the @xchk macro
79-
function xchk_throw(f, args...)
80-
f & INEXACT != 0 && throw(InexactError(args...))
81-
f & OVERFLOW != 0 && throw(OverflowError(args...))
82-
f & DIVBYZERO != 0 && throw(DivideError())
83-
f & INVALID != 0 && throw(DomainError(args...))
84-
f & UNDERFLOW != 0 && error("underflow")
85-
f & UNNORMAL != 0 && error("unnormal")
86-
@assert false # this should be unreachable
87-
end
88-
8962
#############################################################################
9063

9164
const rounding = Ref{Ptr{Cuint}}()
@@ -167,7 +140,7 @@ for w in (32,64,128)
167140
if isnan(x) && !isnanstr(s)
168141
throw(ArgumentError("invalid number format $s"))
169142
end
170-
return @xchk1(x, InexactError, :parse, $BID, s)
143+
return @xchk(x, InexactError, :parse, $BID, s)
171144
end
172145

173146
$BID(x::AbstractString) = parse($BID, x)
@@ -233,7 +206,7 @@ for w in (32,64,128)
233206
n = length(DIGITS) - 1
234207
end
235208
# rounded = round(x * exp10($BID(n)), RoundNearestTiesAway)
236-
rounded = @xchk1(ccall(($(bidsym(w,"round_integral_nearest_away")), libbid), $BID, ($BID,), x * exp10($BID(n))), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
209+
rounded = @xchk(ccall(($(bidsym(w,"round_integral_nearest_away")), libbid), $BID, ($BID,), x * exp10($BID(n))), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
237210
if rounded == 0
238211
DIGITS[1] = UInt8('0')
239212
return Int32(1), Int32(1), signbit(x)
@@ -306,7 +279,7 @@ for w in (32,64,128)
306279

307280
Base.nextfloat(x::$BID) = nox(_nextfloat(x))
308281
Base.prevfloat(x::$BID) = nox(_prevfloat(x))
309-
Base.eps(x::$BID) = ifelse(isfinite(x), @xchk(nextfloat(x) - x, "$($BID) value overflow", mask=OVERFLOW), $(_parse(T, "NaN")))
282+
Base.eps(x::$BID) = ifelse(isfinite(x), @xchk(nextfloat(x) - x, OverflowError, "$($BID) value overflow", mask=OVERFLOW), $(_parse(T, "NaN")))
310283

311284
# the meaning of the exponent is different than for binary FP: it is 10^n, not 2^n:
312285
# Base.exponent(x::$BID) = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), x))
@@ -322,11 +295,11 @@ for w in (32,64,128)
322295
end
323296

324297
for f in (:exp,:log,:sin,:cos,:tan,:asin,:acos,:atan,:sinh,:cosh,:tanh,:asinh,:acosh,:atanh,:log1p,:expm1,:log10,:log2,:exp2,:exp10,:lgamma,:sqrt,:cbrt,:abs)
325-
@eval Base.$f(x::$BID) = @xchk(ccall(($(bidsym(w,f)), libbid), $BID, ($BID,), x), "invalid operation '$($f)' on $($BID)", mask=INVALID)
298+
@eval Base.$f(x::$BID) = @xchk(ccall(($(bidsym(w,f)), libbid), $BID, ($BID,), x), DomainError, x, mask=INVALID)
326299
end
327300

328301
for (f,c) in ((:gamma,"tgamma"), (:-,"negate"), (:round,"nearbyint"))
329-
@eval Base.$f(x::$BID) = @xchk(ccall(($(bidsym(w,c)), libbid), $BID, ($BID,), x), "invalid operation '$($c)' on $($BID)", mask=INVALID)
302+
@eval Base.$f(x::$BID) = @xchk(ccall(($(bidsym(w,c)), libbid), $BID, ($BID,), x), DomainError, x, mask=INVALID)
330303
end
331304

332305
for (f,c) in ((:(==),"quiet_equal"), (:>,"quiet_greater"), (:<,"quiet_less"), (:(>=), "quiet_greater_equal"), (:(<=), "quiet_less_equal"))
@@ -358,7 +331,7 @@ for w in (32,64,128)
358331
@eval promote_rule(::Type{$BID}, ::Type{$BID′}) = $BID
359332
end
360333
if w != w′
361-
@eval Base.convert(::Type{$BID}, x::$BID′) = @xchk1(ccall(($(string("__bid",w′,"_to_","bid",w)), libbid), $BID, ($BID′,), x), InexactError, :convert, $BID, x, mask=INEXACT)
334+
@eval Base.convert(::Type{$BID}, x::$BID′) = @xchk(ccall(($(string("__bid",w′,"_to_","bid",w)), libbid), $BID, ($BID′,), x), InexactError, :convert, $BID, x, mask=INEXACT)
362335
end
363336

364337
# promote binary*decimal -> decimal, for consistency with other operations above
@@ -379,12 +352,12 @@ for w in (32,64,128)
379352
for (i′, i′str) in (("Int$w′", "int$w′"), ("UInt$w′", "uint$w′"))
380353
Ti′ = eval(Symbol(i′))
381354
@eval begin
382-
Base.trunc(::Type{$Ti′}, x::$BID) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xint")), libbid), $Ti′, ($BID,), x), InexactError, :trunc, $BID, x, mask=INVALID | OVERFLOW)
383-
Base.floor(::Type{$Ti′}, x::$BID) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xfloor")), libbid), $Ti′, ($BID,), x), InexactError, :floor, $BID, x, mask=INVALID | OVERFLOW)
384-
Base.ceil(::Type{$Ti′}, x::$BID) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xceil")), libbid), $Ti′, ($BID,), x), InexactError, :ceil, $BID, x, mask=INVALID | OVERFLOW)
385-
Base.round(::Type{$Ti′}, x::$BID) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xrnint")), libbid), $Ti′, ($BID,), x), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
386-
Base.round(::Type{$Ti′}, x::$BID, ::RoundingMode{:NearestTiesAway}) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xrninta")), libbid), $Ti′, ($BID,), x), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
387-
Base.convert(::Type{$Ti′}, x::$BID) = @xchk1(ccall(($(bidsym(w,"to_",i′str,"_xfloor")), libbid), $Ti′, ($BID,), x), InexactError, :convert, $BID, x)
355+
Base.trunc(::Type{$Ti′}, x::$BID) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xint")), libbid), $Ti′, ($BID,), x), InexactError, :trunc, $BID, x, mask=INVALID | OVERFLOW)
356+
Base.floor(::Type{$Ti′}, x::$BID) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xfloor")), libbid), $Ti′, ($BID,), x), InexactError, :floor, $BID, x, mask=INVALID | OVERFLOW)
357+
Base.ceil(::Type{$Ti′}, x::$BID) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xceil")), libbid), $Ti′, ($BID,), x), InexactError, :ceil, $BID, x, mask=INVALID | OVERFLOW)
358+
Base.round(::Type{$Ti′}, x::$BID) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xrnint")), libbid), $Ti′, ($BID,), x), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
359+
Base.round(::Type{$Ti′}, x::$BID, ::RoundingMode{:NearestTiesAway}) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xrninta")), libbid), $Ti′, ($BID,), x), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
360+
Base.convert(::Type{$Ti′}, x::$BID) = @xchk(ccall(($(bidsym(w,"to_",i′str,"_xfloor")), libbid), $Ti′, ($BID,), x), InexactError, :convert, $BID, x)
388361
Base.$(Symbol("$Ti′"))(x::$BID) = convert($Ti′, x)
389362
end
390363
end

0 commit comments

Comments
 (0)