11module DecFP
22export Dec32, Dec64, Dec128, @d_str , @d32_str , @d64_str , @d128_str
33
4- using Compat
5-
64const libbid = joinpath (dirname (@__FILE__ ), " .." , " deps" , " libbid$(Sys. WORD_SIZE) " )
75
8- const _buffer = Array {UInt8} (1024 )
6+ const _buffer = Vector {UInt8} (1024 )
97
108import Base. promote_rule
119
10+ # https://github.com/JuliaLang/julia/pull/20005
11+ if VERSION < v " 0.7.0-DEV.896"
12+ Base. InexactError (name:: Symbol , T, val) = InexactError ()
13+ end
14+
15+ # https://github.com/JuliaLang/julia/pull/22751
16+ if VERSION < v " 0.7.0-DEV.924"
17+ Base. DomainError (val) = DomainError ()
18+ Base. DomainError (val, msg) = DomainError ()
19+ end
20+
21+ # https://github.com/JuliaLang/julia/pull/222761
22+ if VERSION < v " 0.7.0-DEV.1285"
23+ Base. OverflowError (msg) = OverflowError ()
24+ end
25+
1226# global pointers and dicts must be initialized at runtime (via __init__)
1327function __init__ ()
1428 global const rounding = cglobal ((:__bid_IDEC_glbround , libbid), Cuint) # rounding mode
@@ -30,19 +44,14 @@ const INEXACT = 0x20
3044
3145bidsym (w,s... ) = string (" __bid" , w, " _" , s... )
3246
33- @compat abstract type DecimalFloatingPoint <: AbstractFloat end
34- if VERSION < v " 0.5"
35- Base. get_rounding {T<:DecimalFloatingPoint} (:: Type{T} ) = rounding_c2j[unsafe_load (rounding)+ 1 ]
36- Base. set_rounding {T<:DecimalFloatingPoint} (:: Type{T} , r:: RoundingMode ) = unsafe_store! (rounding, rounding_j2c[r])
37- else
38- Base. rounding {T<:DecimalFloatingPoint} (:: Type{T} ) = rounding_c2j[unsafe_load (rounding)+ 1 ]
39- Base. setrounding {T<:DecimalFloatingPoint} (:: Type{T} , r:: RoundingMode ) = unsafe_store! (rounding, rounding_j2c[r])
40- end
47+ abstract type DecimalFloatingPoint <: AbstractFloat end
48+ Base. rounding (:: Type{T} ) where {T<: DecimalFloatingPoint } = rounding_c2j[unsafe_load (rounding)+ 1 ]
49+ Base. setrounding (:: Type{T} , r:: RoundingMode ) where {T<: DecimalFloatingPoint } = unsafe_store! (rounding, rounding_j2c[r])
4150
4251for w in (32 ,64 ,128 )
4352 BID = Symbol (string (" Dec" ,w))
4453 Ti = Symbol (string (" UInt" ,w))
45- @eval immutable $ BID <: DecimalFloatingPoint
54+ @eval struct $ BID <: DecimalFloatingPoint
4655 x:: $Ti
4756 $ BID (x) = convert ($ BID, x)
4857 Base. reinterpret (:: Type{$BID} , x:: $Ti ) = new (x)
@@ -90,7 +99,7 @@ for w in (32,64,128)
9099 if isnan (x) && ! isnanstr (s)
91100 throw (ArgumentError (" invalid number format $s " ))
92101 end
93- return xchk (x, InexactError)
102+ return xchk (x, InexactError, :parse , $ BID, s )
94103 end
95104
96105 function Base. show (io:: IO , x:: $BID )
@@ -109,7 +118,7 @@ for w in (32,64,128)
109118
110119 Base. nextfloat (x:: $BID ) = nox (_nextfloat (x))
111120 Base. prevfloat (x:: $BID ) = nox (_prevfloat (x))
112- Base. eps (x:: $BID ) = ifelse (isfinite (x), xchk (nextfloat (x) - x, OVERFLOW), $ (_parse (T, " NaN" )))
121+ Base. eps (x:: $BID ) = ifelse (isfinite (x), xchk (nextfloat (x) - x, OVERFLOW, " $( $ BID) value overflow " ), $ (_parse (T, " NaN" )))
113122
114123 # the meaning of the exponent is different than for binary FP: it is 10^n, not 2^n:
115124 # Base.exponent(x::$BID) = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), x))
@@ -125,11 +134,11 @@ for w in (32,64,128)
125134 end
126135
127136 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 )
128- @eval Base.$ f (x:: $BID ) = xchk (ccall (($ (bidsym (w,f)), libbid), $ BID, ($ BID,), x), INVALID)
137+ @eval Base.$ f (x:: $BID ) = xchk (ccall (($ (bidsym (w,f)), libbid), $ BID, ($ BID,), x), " invalid operation ' $( $ f) ' on $( $ BID) " , mask = INVALID)
129138 end
130139
131140 for (f,c) in ((:gamma ," tgamma" ), (:- ," negate" ), (:round ," nearbyint" ))
132- @eval Base.$ f (x:: $BID ) = xchk (ccall (($ (bidsym (w,c)), libbid), $ BID, ($ BID,), x), INVALID)
141+ @eval Base.$ f (x:: $BID ) = xchk (ccall (($ (bidsym (w,c)), libbid), $ BID, ($ BID,), x), " invalid operation ' $( $ c) ' on $( $ BID) " , mask = INVALID)
133142 end
134143
135144 for (f,c) in ((:(== )," quiet_equal" ), (:> ," quiet_greater" ), (:< ," quiet_less" ), (:(>= ), " quiet_greater_equal" ), (:(<= ), " quiet_less_equal" ))
@@ -146,7 +155,7 @@ for w in (32,64,128)
146155
147156 for c in (:π , :e , :γ , :catalan , :φ )
148157 @eval begin
149- Base. convert (:: Type{$BID} , :: Irrational{$(QuoteNode(c))} ) = $ (_parse (T, @compat setprecision (256 ) do
158+ Base. convert (:: Type{$BID} , :: Irrational{$(QuoteNode(c))} ) = $ (_parse (T, setprecision (256 ) do
150159 string (BigFloat (eval (c)))
151160 end ))
152161 end
@@ -160,7 +169,7 @@ for w in (32,64,128)
160169 @eval promote_rule (:: Type{$BID} , :: Type{$BID′} ) = $ BID
161170 end
162171 if w != w′
163- @eval Base. convert (:: Type{$BID} , x:: $BID′ ) = xchk (ccall (($ (string (" __bid" ,w′," _to_" ," bid" ,w)), libbid), $ BID, ($ BID′,), x), INEXACT)
172+ @eval Base. convert (:: Type{$BID} , x:: $BID′ ) = xchk (ccall (($ (string (" __bid" ,w′," _to_" ," bid" ,w)), libbid), $ BID, ($ BID′,), x), INEXACT, :convert , $ BID, x )
164173 end
165174
166175 # promote binary*decimal -> decimal, for consistency with other operations above
@@ -181,12 +190,12 @@ for w in (32,64,128)
181190 for i′ in (" Int$w′ " , " UInt$w′ " )
182191 Ti′ = eval (Symbol (i′))
183192 @eval begin
184- Base. trunc (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xint" )), libbid), $ Ti′, ($ BID,), x), InexactError, INVALID | OVERFLOW)
185- Base. floor (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xfloor" )), libbid), $ Ti′, ($ BID,), x), InexactError, INVALID | OVERFLOW)
186- Base. ceil (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xceil" )), libbid), $ Ti′, ($ BID,), x), InexactError, INVALID | OVERFLOW)
187- Base. round (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xrnint" )), libbid), $ Ti′, ($ BID,), x), InexactError, INVALID | OVERFLOW)
188- Base. round (:: Type{$Ti′} , x:: $BID , :: RoundingMode{:NearestTiesAway} ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xrninta" )), libbid), $ Ti′, ($ BID,), x), InexactError, INVALID | OVERFLOW)
189- Base. convert (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xfloor" )), libbid), $ Ti′, ($ BID,), x), InexactError)
193+ Base. trunc (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xint" )), libbid), $ Ti′, ($ BID,), x), InexactError, :trunc , $ BID, x, mask = INVALID | OVERFLOW)
194+ Base. floor (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xfloor" )), libbid), $ Ti′, ($ BID,), x), InexactError, :floor , $ BID, x, mask = INVALID | OVERFLOW)
195+ Base. ceil (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xceil" )), libbid), $ Ti′, ($ BID,), x), InexactError, :ceil , $ BID, x, mask = INVALID | OVERFLOW)
196+ Base. round (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xrnint" )), libbid), $ Ti′, ($ BID,), x), InexactError, :round , $ BID, x, mask = INVALID | OVERFLOW)
197+ Base. round (:: Type{$Ti′} , x:: $BID , :: RoundingMode{:NearestTiesAway} ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xrninta" )), libbid), $ Ti′, ($ BID,), x), InexactError, :round , $ BID, x, mask = INVALID | OVERFLOW)
198+ Base. convert (:: Type{$Ti′} , x:: $BID ) = xchk (ccall (($ (bidsym (w," to_" ,lowercase (i′)," _xfloor" )), libbid), $ Ti′, ($ BID,), x), InexactError, :convert , $ BID, x )
190199 end
191200 end
192201 end
@@ -203,18 +212,18 @@ Base.round(::Type{Integer}, x::DecimalFloatingPoint) = round(Int, x)
203212Base. round (:: Type{Integer} , x:: DecimalFloatingPoint , :: RoundingMode{:NearestTiesAway} ) = round (Int, x, RoundNearestTiesAway)
204213Base. convert (:: Type{Integer} , x:: DecimalFloatingPoint ) = convert (Int, x)
205214
206- Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Nearest} ) = round (T, x)
207- function Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:NearestTiesUp} )
215+ Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Nearest} ) where {T <: Integer } = round (T, x)
216+ function Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:NearestTiesUp} ) where {T <: Integer }
208217 y = floor (T, x)
209218 ifelse (x== y, y, copysign (floor (T, 2 * x- y), x))
210219end
211- Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:ToZero} ) = trunc (T, x)
212- Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:FromZero} ) = (x>= 0 ? ceil (T, x) : floor (T, x))
213- Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Up} ) = ceil (T, x)
214- Base. round {T<:Integer} (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Down} ) = floor (T, x)
220+ Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:ToZero} ) where {T <: Integer } = trunc (T, x)
221+ Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:FromZero} ) where {T <: Integer } = (x>= 0 ? ceil (T, x) : floor (T, x))
222+ Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Up} ) where {T <: Integer } = ceil (T, x)
223+ Base. round (:: Type{T} , x:: DecimalFloatingPoint , :: RoundingMode{:Down} ) where {T <: Integer } = floor (T, x)
215224
216225# the complex-sqrt function in base doesn't work for use, because it requires base-2 ldexp
217- function Base. sqrt {T<:DecimalFloatingPoint} (z:: Complex{T} )
226+ function Base. sqrt (z:: Complex{T} ) where {T <: DecimalFloatingPoint }
218227 x, y = reim (z)
219228 x== y== 0 && return Complex (zero (x),y)
220229 ρ = sqrt ((abs (x) + hypot (x,y)) * 0.5 )
@@ -242,17 +251,17 @@ for T in (Dec32,Dec64,Dec128)
242251 end
243252end
244253
245- Base. convert {F<:DecimalFloatingPoint} (T:: Type{F} , x:: Union{Int8,UInt8,Int16,UInt16} ) = F (Int32 (x))
246- Base. convert {F<:DecimalFloatingPoint} (T:: Type{F} , x:: Integer ) = F (Int64 (x))
247- Base. convert {F<:DecimalFloatingPoint} (T:: Type{F} , x:: Unsigned ) = F (UInt64 (x))
248- Base. convert {F<:DecimalFloatingPoint} (T:: Type{F} , x:: Rational ) = F (x. num) / F (x. den)
249- Base. convert {F<:DecimalFloatingPoint} (T:: Type{F} , x:: Float16 ) = F (Float32 (x))
250- promote_rule {F<:DecimalFloatingPoint} (:: Type{F} , :: Type{Float16} ) = F
251- promote_rule {F <:DecimalFloatingPoint,T<:Union{Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64}}( :: Type{F} , :: Type{T} ) = F
254+ Base. convert (T:: Type{F} , x:: Union{Int8,UInt8,Int16,UInt16} ) where {F <: DecimalFloatingPoint } = F (Int32 (x))
255+ Base. convert (T:: Type{F} , x:: Integer ) where {F <: DecimalFloatingPoint } = F (Int64 (x))
256+ Base. convert (T:: Type{F} , x:: Unsigned ) where {F <: DecimalFloatingPoint } = F (UInt64 (x))
257+ Base. convert (T:: Type{F} , x:: Rational ) where {F <: DecimalFloatingPoint } = F (x. num) / F (x. den)
258+ Base. convert (T:: Type{F} , x:: Float16 ) where {F <: DecimalFloatingPoint } = F (Float32 (x))
259+ promote_rule (:: Type{F} , :: Type{Float16} ) where {F <: DecimalFloatingPoint } = F
260+ promote_rule ( :: Type{F} , :: Type{T} ) where {F <: DecimalFloatingPoint ,T<: Union{Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64} } = F
252261
253262# so that mathconsts get promoted to Dec32, not Dec64, like Float32
254- promote_rule {s,F<:DecimalFloatingPoint} (:: Type{Irrational{s}} , :: Type{F} ) = F
255- promote_rule {s,F<:DecimalFloatingPoint} (:: Type{Irrational{s}} , T:: Type{Complex{F}} ) = T
263+ promote_rule (:: Type{Irrational{s}} , :: Type{F} ) where {s,F <: DecimalFloatingPoint } = F
264+ promote_rule (:: Type{Irrational{s}} , T:: Type{Complex{F}} ) where {s,F <: DecimalFloatingPoint } = T
256265
257266macro d_str (s, flags... ) parse (Dec64, s) end
258267macro d32_str (s, flags... ) parse (Dec32, s) end
@@ -267,24 +276,24 @@ end
267276
268277# check exception flags in mask & throw, otherwise returning x;
269278# always clearing exceptions
270- function xchk (x, mask:: Integer = 0x3f )
279+ function xchk (x, args ... ; mask:: Integer = 0x3f )
271280 f = unsafe_load (flags)
272281 unsafe_store! (flags, 0 )
273282 if f & mask != 0
274- f & INEXACT != 0 && throw (InexactError ())
275- f & OVERFLOW != 0 && throw (OverflowError ())
283+ f & INEXACT != 0 && throw (InexactError (args ... ))
284+ f & OVERFLOW != 0 && throw (OverflowError (args ... ))
276285 f & DIVBYZERO != 0 && throw (DivideError ())
277- f & INVALID != 0 && throw (DomainError ())
286+ f & INVALID != 0 && throw (DomainError (args ... ))
278287 f & UNDERFLOW != 0 && error (" underflow" )
279288 f & UNNORMAL != 0 && error (" unnormal" )
280289 end
281290 return x
282291end
283292
284- function xchk {E<:Exception} (x, exc:: Type{E} , mask:: Integer = 0x3f )
293+ function xchk (x, exc:: Type{E} , args ... ; mask:: Integer = 0x3f ) where {E <: Exception }
285294 f = unsafe_load (flags)
286295 unsafe_store! (flags, 0 )
287- f & mask != 0 && throw (exc ())
296+ f & mask != 0 && throw (exc (args ... ))
288297 return x
289298end
290299
0 commit comments