diff options
author | Stefan Krah <skrah@bytereef.org> | 2020-08-10 14:32:21 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-10 14:32:21 (GMT) |
commit | 39042e00ab01d6521548c1b7cc6554c09f4389ff (patch) | |
tree | ea0d0a0cd9c73afe30a3573198e2d3a5844f200e /Modules/_decimal/tests | |
parent | 416f0b71ba84fe83ee2ba4399b8a28712702980b (diff) | |
download | cpython-39042e00ab01d6521548c1b7cc6554c09f4389ff.zip cpython-39042e00ab01d6521548c1b7cc6554c09f4389ff.tar.gz cpython-39042e00ab01d6521548c1b7cc6554c09f4389ff.tar.bz2 |
bpo-41324 Add a minimal decimal capsule API (#21519)
Diffstat (limited to 'Modules/_decimal/tests')
-rw-r--r-- | Modules/_decimal/tests/deccheck.py | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index 5d9179e..15f104d 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -49,6 +49,9 @@ from randdec import unary_optarg, binary_optarg, ternary_optarg from formathelper import rand_format, rand_locale from _pydecimal import _dec_from_triple +from _testcapi import decimal_as_triple +from _testcapi import decimal_from_triple + C = import_fresh_module('decimal', fresh=['_decimal']) P = import_fresh_module('decimal', blocked=['_decimal']) EXIT_STATUS = 0 @@ -154,6 +157,45 @@ TernaryRestricted = ['__pow__', 'context.power'] # ====================================================================== +# Triple tests +# ====================================================================== + +def c_as_triple(dec): + sign, hi, lo, exp = decimal_as_triple(dec) + + coeff = hi * 2**64 + lo + return (sign, coeff, exp) + +def c_from_triple(triple): + sign, coeff, exp = triple + + hi = coeff // 2**64 + lo = coeff % 2**64 + return decimal_from_triple((sign, hi, lo, exp)) + +def p_as_triple(dec): + sign, digits, exp = dec.as_tuple() + + s = "".join(str(d) for d in digits) + coeff = int(s) if s else 0 + + if coeff < 0 or coeff >= 2**128: + raise ValueError("value out of bounds for a uint128 triple"); + + return (sign, coeff, exp) + +def p_from_triple(triple): + sign, coeff, exp = triple + + if coeff < 0 or coeff >= 2**128: + raise ValueError("value out of bounds for a uint128 triple"); + + digits = tuple(int(c) for c in str(coeff)) + + return P.Decimal((sign, digits, exp)) + + +# ====================================================================== # Unified Context # ====================================================================== @@ -846,12 +888,44 @@ def verify(t, stat): t.presults.append(str(t.rp.imag)) t.presults.append(str(t.rp.real)) + ctriple = None + if t.funcname not in ['__radd__', '__rmul__']: # see skip handler + try: + ctriple = c_as_triple(t.rc) + except ValueError: + try: + ptriple = p_as_triple(t.rp) + except ValueError: + pass + else: + raise RuntimeError("ValueError not raised") + else: + cres = c_from_triple(ctriple) + t.cresults.append(ctriple) + t.cresults.append(str(cres)) + + ptriple = p_as_triple(t.rp) + pres = p_from_triple(ptriple) + t.presults.append(ptriple) + t.presults.append(str(pres)) + if t.with_maxcontext and isinstance(t.rmax, C.Decimal): t.maxresults.append(t.rmax.to_eng_string()) t.maxresults.append(t.rmax.as_tuple()) t.maxresults.append(str(t.rmax.imag)) t.maxresults.append(str(t.rmax.real)) + if ctriple is not None: + # NaN payloads etc. depend on precision and clamp. + if all_nan(t.rc) and all_nan(t.rmax): + t.maxresults.append(ctriple) + t.maxresults.append(str(cres)) + else: + maxtriple = c_as_triple(t.rmax) + maxres = c_from_triple(maxtriple) + t.maxresults.append(maxtriple) + t.maxresults.append(str(maxres)) + nc = t.rc.number_class().lstrip('+-s') stat[nc] += 1 else: |