-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
589 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# Number of significant digits | ||
const PRECISION = Ref(9) | ||
const ROUNDING = Ref{RoundingMode}(RoundNearest) | ||
const EMAX = Ref(99999) | ||
const EMIN = Ref(-99999) | ||
|
||
function Base.setprecision(::Type{Decimal}, precision::Int) | ||
PRECISION[] = precision | ||
return precision | ||
end | ||
Base.precision(::Type{Decimal}) = PRECISION[] | ||
|
||
function Base.setrounding(::Type{Decimal}, rounding::RoundingMode) | ||
ROUNDING[] = rounding | ||
return rounding | ||
end | ||
Base.rounding(::Type{Decimal}) = ROUNDING[] | ||
|
||
""" | ||
fixed(x) | ||
Round `x` if necessary to keep within `PRECISION`. | ||
""" | ||
function fixed(x::Decimal) | ||
prec = precision(Decimal) | ||
rmod = rounding(Decimal) | ||
|
||
Emin, Emax = EMIN[], EMAX[] | ||
Etiny = Emin - prec + 1 | ||
Etop = Emax - prec + 1 | ||
|
||
if iszero(x) | ||
return Decimal(x.s, x.c, clamp(x.q, Etiny, Etop)) | ||
end | ||
|
||
clen = ndigits(x.c) | ||
exp_min = clen + x.q - prec | ||
|
||
if exp_min > Etop | ||
throw(OverflowError("Exponent limit ($Emax) exceeded: $x")) | ||
end | ||
|
||
subnormal = exp_min < Etiny | ||
if subnormal | ||
exp_min = Etiny | ||
end | ||
|
||
# Number of digits and exponent within bounds | ||
if x.q ≥ exp_min | ||
return x | ||
end | ||
|
||
# Signed coefficient for rounding modes like RoundToZero | ||
c = (-1)^x.s * x.c | ||
q = exp_min | ||
|
||
# Number of digits of the resulting coefficient | ||
digits = clen + x.q - exp_min | ||
if digits < 0 | ||
c = big(1) | ||
q = exp_min - 1 | ||
digits = 0 | ||
end | ||
|
||
# Number of least significant digits to remove from `c` | ||
trun_len = clen - digits | ||
|
||
# Split `c` into `digits` most significant digits and `trun_len` least | ||
# significant digits | ||
# This is like round(c, rmod, sigdigits=digits), except here we can | ||
# tell from `rem` if the rounding was lossless | ||
c, rem = divrem(c, BigTen ^ trun_len, rmod) | ||
|
||
# Rounding is exact if the truncated digits were zero | ||
exact = iszero(rem) | ||
|
||
# If the number of digits exceeded `digits` after rounding, | ||
# it means that `c` was like 99...9 and was rounded up, | ||
# becoming 100...0, so `c` is divisible by 10 | ||
if ndigits(c) > prec | ||
c = exactdiv(c, 10) | ||
q += 1 | ||
end | ||
|
||
# Exponent might have exceeded due to rounding | ||
if q > Etop | ||
throw(OverflowError("Exponent limit ($Emax) exceeded: $x")) | ||
end | ||
|
||
if subnormal && !exact | ||
# throw(ErrorException("Underflow")) | ||
end | ||
|
||
return Decimal(signbit(c), abs(c), q) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
@testset "Minus" begin | ||
setprecision(Decimal, 9) | ||
setrounding(Decimal, RoundNearestTiesAway) | ||
Decimals.EMAX[] = 384 | ||
Decimals.EMIN[] = -383 | ||
|
||
# minx001 | ||
@test -(dec"1") == dec"-1" | ||
# minx002 | ||
@test -(dec"-1") == dec"1" | ||
# minx003 | ||
@test -(dec"1.00") == dec"-1.00" | ||
# minx004 | ||
@test -(dec"-1.00") == dec"1.00" | ||
# minx005 | ||
@test -(dec"0") == dec"0" | ||
# minx006 | ||
@test -(dec"0.00") == dec"0.00" | ||
# minx007 | ||
@test -(dec"00.0") == dec"0.0" | ||
# minx008 | ||
@test -(dec"00.00") == dec"0.00" | ||
# minx009 | ||
@test -(dec"00") == dec"0" | ||
# minx010 | ||
@test -(dec"-2") == dec"2" | ||
# minx011 | ||
@test -(dec"2") == dec"-2" | ||
# minx012 | ||
@test -(dec"-2.00") == dec"2.00" | ||
# minx013 | ||
@test -(dec"2.00") == dec"-2.00" | ||
# minx014 | ||
@test -(dec"-0") == dec"0" | ||
# minx015 | ||
@test -(dec"-0.00") == dec"0.00" | ||
# minx016 | ||
@test -(dec"-00.0") == dec"0.0" | ||
# minx017 | ||
@test -(dec"-00.00") == dec"0.00" | ||
# minx018 | ||
@test -(dec"-00") == dec"0" | ||
# minx020 | ||
@test -(dec"-0e3") == dec"0e+3" | ||
# minx021 | ||
@test -(dec"-0e2") == dec"0e+2" | ||
# minx022 | ||
@test -(dec"-0e1") == dec"0e+1" | ||
# minx023 | ||
@test -(dec"-0e0") == dec"0" | ||
# minx024 | ||
@test -(dec"+0e0") == dec"0" | ||
# minx025 | ||
@test -(dec"+0e1") == dec"0e+1" | ||
# minx026 | ||
@test -(dec"+0e2") == dec"0e+2" | ||
# minx027 | ||
@test -(dec"+0e3") == dec"0e+3" | ||
# minx030 | ||
@test -(dec"-5e3") == dec"5e+3" | ||
# minx031 | ||
@test -(dec"-5e8") == dec"5e+8" | ||
# minx032 | ||
@test -(dec"-5e13") == dec"5e+13" | ||
# minx033 | ||
@test -(dec"-5e18") == dec"5e+18" | ||
# minx034 | ||
@test -(dec"+5e3") == dec"-5e+3" | ||
# minx035 | ||
@test -(dec"+5e8") == dec"-5e+8" | ||
# minx036 | ||
@test -(dec"+5e13") == dec"-5e+13" | ||
# minx037 | ||
@test -(dec"+5e18") == dec"-5e+18" | ||
# minx050 | ||
@test -(dec"-2000000") == dec"2000000" | ||
# minx051 | ||
@test -(dec"2000000") == dec"-2000000" | ||
|
||
setprecision(Decimal, 7) | ||
|
||
# minx052 | ||
@test -(dec"-2000000") == dec"2000000" | ||
# minx053 | ||
@test -(dec"2000000") == dec"-2000000" | ||
|
||
setprecision(Decimal, 6) | ||
|
||
# minx054 | ||
@test -(dec"-2000000") == dec"2.00000e+6" | ||
# minx055 | ||
@test -(dec"2000000") == dec"-2.00000e+6" | ||
|
||
setprecision(Decimal, 3) | ||
|
||
# minx056 | ||
@test -(dec"-2000000") == dec"2.00e+6" | ||
# minx057 | ||
@test -(dec"2000000") == dec"-2.00e+6" | ||
|
||
setprecision(Decimal, 9) | ||
|
||
# minx060 | ||
@test -(dec"56267e-10") == dec"-0.0000056267" | ||
# minx061 | ||
@test -(dec"56267e-5") == dec"-0.56267" | ||
# minx062 | ||
@test -(dec"56267e-2") == dec"-562.67" | ||
# minx063 | ||
@test -(dec"56267e-1") == dec"-5626.7" | ||
# minx065 | ||
@test -(dec"56267e-0") == dec"-56267" | ||
# minx066 | ||
@test -(dec"56267e+0") == dec"-56267" | ||
# minx067 | ||
@test -(dec"56267e+1") == dec"-5.6267e+5" | ||
# minx068 | ||
@test -(dec"56267e+2") == dec"-5.6267e+6" | ||
# minx069 | ||
@test -(dec"56267e+3") == dec"-5.6267e+7" | ||
# minx070 | ||
@test -(dec"56267e+4") == dec"-5.6267e+8" | ||
# minx071 | ||
@test -(dec"56267e+5") == dec"-5.6267e+9" | ||
# minx072 | ||
@test -(dec"56267e+6") == dec"-5.6267e+10" | ||
# minx080 | ||
@test -(dec"-56267e-10") == dec"0.0000056267" | ||
# minx081 | ||
@test -(dec"-56267e-5") == dec"0.56267" | ||
# minx082 | ||
@test -(dec"-56267e-2") == dec"562.67" | ||
# minx083 | ||
@test -(dec"-56267e-1") == dec"5626.7" | ||
# minx085 | ||
@test -(dec"-56267e-0") == dec"56267" | ||
# minx086 | ||
@test -(dec"-56267e+0") == dec"56267" | ||
# minx087 | ||
@test -(dec"-56267e+1") == dec"5.6267e+5" | ||
# minx088 | ||
@test -(dec"-56267e+2") == dec"5.6267e+6" | ||
# minx089 | ||
@test -(dec"-56267e+3") == dec"5.6267e+7" | ||
# minx090 | ||
@test -(dec"-56267e+4") == dec"5.6267e+8" | ||
# minx091 | ||
@test -(dec"-56267e+5") == dec"5.6267e+9" | ||
# minx092 | ||
@test -(dec"-56267e+6") == dec"5.6267e+10" | ||
|
||
Decimals.EMAX[] = 999999999 | ||
Decimals.EMIN[] = -999999999 | ||
setprecision(Decimal, 3) | ||
|
||
# minx100 | ||
@test_throws OverflowError -(dec"9.999e+999999999") | ||
# minx101 | ||
@test_throws OverflowError -(dec"-9.999e+999999999") | ||
|
||
setprecision(Decimal, 3) | ||
Decimals.EMAX[] = 999 | ||
Decimals.EMIN[] = -999 | ||
|
||
# minx110 | ||
@test -(dec"1.00e-999") == dec"-1.00e-999" | ||
# minx111 | ||
@test -(dec"0.1e-999") == dec"-1e-1000" | ||
# minx112 | ||
@test -(dec"0.10e-999") == dec"-1.0e-1000" | ||
# minx113 | ||
@test -(dec"0.100e-999") == dec"-1.0e-1000" | ||
# minx114 | ||
@test -(dec"0.01e-999") == dec"-1e-1001" | ||
# minx115 | ||
@test -(dec"0.999e-999") == dec"-1.00e-999" | ||
# minx116 | ||
@test -(dec"0.099e-999") == dec"-1.0e-1000" | ||
# minx117 | ||
@test -(dec"0.009e-999") == dec"-1e-1001" | ||
# minx118 | ||
@test -(dec"0.001e-999") == dec"-0e-1001" | ||
# minx119 | ||
@test -(dec"0.0009e-999") == dec"-0e-1001" | ||
# minx120 | ||
@test -(dec"0.0001e-999") == dec"-0e-1001" | ||
# minx130 | ||
@test -(dec"-1.00e-999") == dec"1.00e-999" | ||
# minx131 | ||
@test -(dec"-0.1e-999") == dec"1e-1000" | ||
# minx132 | ||
@test -(dec"-0.10e-999") == dec"1.0e-1000" | ||
# minx133 | ||
@test -(dec"-0.100e-999") == dec"1.0e-1000" | ||
# minx134 | ||
@test -(dec"-0.01e-999") == dec"1e-1001" | ||
# minx135 | ||
@test -(dec"-0.999e-999") == dec"1.00e-999" | ||
# minx136 | ||
@test -(dec"-0.099e-999") == dec"1.0e-1000" | ||
# minx137 | ||
@test -(dec"-0.009e-999") == dec"1e-1001" | ||
# minx138 | ||
@test -(dec"-0.001e-999") == dec"0e-1001" | ||
# minx139 | ||
@test -(dec"-0.0009e-999") == dec"0e-1001" | ||
# minx140 | ||
@test -(dec"-0.0001e-999") == dec"0e-1001" | ||
|
||
Decimals.EMAX[] = 999 | ||
Decimals.EMIN[] = -999 | ||
setprecision(Decimal, 9) | ||
|
||
# minx301 | ||
@test -(dec"12345678000") == dec"-1.23456780e+10" | ||
# minx302 | ||
@test -(dec"1234567800") == dec"-1.23456780e+9" | ||
# minx303 | ||
@test -(dec"1234567890") == dec"-1.23456789e+9" | ||
# minx304 | ||
@test -(dec"1234567891") == dec"-1.23456789e+9" | ||
# minx305 | ||
@test -(dec"12345678901") == dec"-1.23456789e+10" | ||
# minx306 | ||
@test -(dec"1234567896") == dec"-1.23456790e+9" | ||
|
||
setprecision(Decimal, 15) | ||
|
||
# minx321 | ||
@test -(dec"12345678000") == dec"-12345678000" | ||
# minx322 | ||
@test -(dec"1234567800") == dec"-1234567800" | ||
# minx323 | ||
@test -(dec"1234567890") == dec"-1234567890" | ||
# minx324 | ||
@test -(dec"1234567891") == dec"-1234567891" | ||
# minx325 | ||
@test -(dec"12345678901") == dec"-12345678901" | ||
# minx326 | ||
@test -(dec"1234567896") == dec"-1234567896" | ||
end |
Oops, something went wrong.