@@ -28,6 +28,7 @@ module FixedPointDecimals
28
28
export FixedDecimal, RoundThrows
29
29
30
30
using Base: decompose, BitInteger
31
+ import Parsers
31
32
32
33
# floats that support fma and are roughly IEEE-like
33
34
const FMAFloat = Union{Float16, Float32, Float64, BigFloat}
100
101
101
102
const FD = FixedDecimal
102
103
104
+ include (" parse.jl" )
105
+
106
+ function __init__ ()
107
+ append! (_BIGINT_10s, [BigInt (0 ) for i in 0 : Threads. nthreads ()])
108
+ append! (_BIGINT_Rs, [BigInt (0 ) for i in 0 : Threads. nthreads ()])
109
+ end
110
+
103
111
(:: Type{T} )(x:: Real ) where {T <: FD } = convert (T, x)
104
112
105
113
floattype (:: Type{<:FD{T}} ) where {T<: Union{Int8, UInt8, Int16, UInt16} } = Float32
@@ -413,77 +421,6 @@ function Base.show(io::IO, x::FD{T, f}) where {T, f}
413
421
end
414
422
end
415
423
416
- # parsing
417
-
418
- """
419
- RoundThrows
420
-
421
- Raises an `InexactError` if any rounding is necessary.
422
- """
423
- const RoundThrows = RoundingMode {:Throw} ()
424
-
425
- function Base. parse (:: Type{FD{T, f}} , str:: AbstractString , mode:: RoundingMode = RoundNearest) where {T, f}
426
- if ! (mode in (RoundThrows, RoundNearest, RoundToZero))
427
- throw (ArgumentError (" Unhandled rounding mode $mode " ))
428
- end
429
-
430
- # Parse exponent information
431
- exp_index = something (findfirst (== (' e' ), str), 0 )
432
- if exp_index > 0
433
- exp = parse (Int, str[(exp_index + 1 ): end ])
434
- sig_end = exp_index - 1
435
- else
436
- exp = 0
437
- sig_end = lastindex (str)
438
- end
439
-
440
- # Remove the decimal place from the string
441
- sign = T (first (str) == ' -' ? - 1 : 1 )
442
- dec_index = something (findfirst (== (' .' ), str), 0 )
443
- sig_start = sign < 0 ? 2 : 1
444
- if dec_index > 0
445
- int_str = str[sig_start: (dec_index - 1 )] * str[(dec_index + 1 ): sig_end]
446
- exp -= sig_end - dec_index
447
- else
448
- int_str = str[sig_start: sig_end]
449
- end
450
-
451
- # Split the integer string into the value we can represent inside the FixedDecimal and
452
- # the remaining digits we'll use during rounding
453
- int_end = lastindex (int_str)
454
- pivot = int_end + exp - (- f)
455
-
456
- a = rpad (int_str[1 : min (pivot, int_end)], pivot, ' 0' )
457
- b = lpad (int_str[max (pivot, 1 ): int_end], int_end - pivot + 1 , ' 0' )
458
-
459
- # Parse the strings
460
- val = isempty (a) ? T (0 ) : sign * parse (T, a)
461
- if ! isempty (b) && any (! isequal (' 0' ), b[2 : end ])
462
- if mode == RoundThrows
463
- throw (InexactError (:parse , FD{T, f}, str))
464
- elseif mode == RoundNearest
465
- val += sign * parse_round (T, b, mode)
466
- end
467
- end
468
-
469
- reinterpret (FD{T, f}, val)
470
- end
471
-
472
- function parse_round (:: Type{T} , fractional:: AbstractString , :: RoundingMode{:Nearest} ) where T
473
- # Note: parsing each digit individually ensures we don't run into an OverflowError
474
- digits = Int8[parse (Int8, d) for d in fractional]
475
- for i in length (digits): - 1 : 2
476
- if digits[i] > 5 || digits[i] == 5 && isodd (digits[i - 1 ])
477
- if i - 1 == 1
478
- return T (1 )
479
- else
480
- digits[i - 1 ] += 1
481
- end
482
- end
483
- end
484
- return T (0 )
485
- end
486
-
487
424
488
425
"""
489
426
max_exp10(T)
0 commit comments