@@ -30,8 +30,8 @@ Features:
|
||||
* Add signed option to to_man_exp(), see #783 (Sergey B Kirpichev)
|
||||
* Add fp.hypot, see #798 (Sergey B Kirpichev)
|
||||
* Support inf/nan's in ctx.almosteq(), #802 (Sergey B Kirpichev)
|
||||
* Implement mpf.__format__(), see #819, #831, #850, #859, #857, #862, #881 and
|
||||
#944 (Javier Garcia, Sergey B Kirpichev)
|
||||
* Implement mpf.__format__(), see #819, #831, #850, #859, #857, #862, #881,
|
||||
#944 and #966 (Javier Garcia, Sergey B Kirpichev)
|
||||
* Support conversion from scalar ndarray's, see #821 (Sergey B Kirpichev)
|
||||
* Support rounding modes in mpf.__format__, see #823, #831 and #834 (Javier
|
||||
Garcia, Sergey B Kirpichev)
|
||||
@@ -40,7 +40,7 @@ Features:
|
||||
* Implement 'a'/'A' formating types for mpf.__format__, see #841 and #870
|
||||
(Sergey B Kirpichev)
|
||||
* Add mpc.__format__(), see #855 (Sergey B Kirpichev)
|
||||
* Now mpf.__round__() returns mpf, see #826 (Sergey B Kirpichev)
|
||||
* Now mpf.__round__() returns mpf, see #826 and #966 (Sergey B Kirpichev)
|
||||
* Support 'b' (binary) format type for mpf/mpc, see #867 (Sergey B Kirpichev)
|
||||
* Implement mpf.__floordiv__() and mpf.__divmod__(), see #873 (Sergey B
|
||||
Kirpichev)
|
||||
@@ -70,7 +70,8 @@ Compatibility:
|
||||
* Drop to_pickable()/from_pickable() helpers, see #667 and #769 (Sergey B
|
||||
Kirpichev)
|
||||
* Direct access to _mpf_ tuples now deprecated, please use from/to_man_exp()
|
||||
functions, see #783 (Sergey B Kirpichev)
|
||||
functions and special constants (finf, fninf and fnan), see
|
||||
#783 (Sergey B Kirpichev)
|
||||
* Removed sage backend, see #732 (Sergey B Kirpichev)
|
||||
* Drop MPMATH_STRICT environment variable, see #759 (Sergey B Kirpichev)
|
||||
* Deprecate current (descending) order of coefficients in polyval(), etc, see
|
||||
@@ -152,6 +153,7 @@ Bug fixes:
|
||||
* Use mpf_log1p in acos_asin() helper (implementing Hull et al algorithm), see
|
||||
#948 (Sergey B Kirpichev)
|
||||
* Fix kwargs passing in the nstr() for mpc, see #964 (David Walker)
|
||||
* Fix exception type for int(inf), see #966 (Sergey B Kirpichev)
|
||||
|
||||
Maintenance:
|
||||
|
||||
|
||||
+10
-8
@@ -130,14 +130,14 @@ class _mpf(mpnumeric):
|
||||
def __reduce__(self): return _make_mpf, (self._mpf_,)
|
||||
|
||||
def __repr__(s):
|
||||
rounding = s.context._rounding
|
||||
rounding = s.context._prec_rounding[1]
|
||||
if s.context.pretty:
|
||||
ndigits = (s.context._repr_digits
|
||||
if s.context._pretty_repr_dps else s.context._str_digits)
|
||||
return to_str(s._mpf_, ndigits, rounding=rounding)
|
||||
return "mpf('%s')" % to_str(s._mpf_, s.context._repr_digits, rounding=rounding)
|
||||
|
||||
def __str__(s): return to_str(s._mpf_, s.context._str_digits, rounding=s.context._rounding)
|
||||
def __str__(s): return to_str(s._mpf_, s.context._str_digits, rounding=s.context._prec_rounding[1])
|
||||
def __hash__(s): return mpf_hash(s._mpf_)
|
||||
def __int__(s): return int(to_int(s._mpf_))
|
||||
def __float__(s): return to_float(s._mpf_, rnd=s.context._prec_rounding[1])
|
||||
@@ -441,13 +441,17 @@ class _mpf(mpnumeric):
|
||||
def to_fixed(self, prec):
|
||||
return to_fixed(self._mpf_, prec)
|
||||
|
||||
def __round__(self, ndigits=0):
|
||||
def __round__(self, ndigits=None):
|
||||
ctx = self.context
|
||||
if ctx.isfinite(self):
|
||||
frac = MPQ(*self.as_integer_ratio())
|
||||
res = round(frac, ndigits)
|
||||
return ctx.convert(res)
|
||||
return self
|
||||
res = ctx.convert(res)
|
||||
else:
|
||||
res = self
|
||||
if ndigits is None:
|
||||
res = int(res)
|
||||
return res
|
||||
|
||||
|
||||
class _constant(_mpf):
|
||||
@@ -731,7 +735,6 @@ class PythonMPContext:
|
||||
|
||||
def default(ctx):
|
||||
ctx._prec = ctx._prec_rounding[0] = sys.float_info.mant_dig
|
||||
ctx._rounding = ctx._prec_rounding[1]
|
||||
ctx._dps = sys.float_info.dig
|
||||
ctx.trap_complex = False
|
||||
|
||||
@@ -746,13 +749,12 @@ class PythonMPContext:
|
||||
def _set_rounding(ctx, r):
|
||||
try:
|
||||
ctx._prec_rounding[1] = ctx._parse_prec({'rounding': r})[1]
|
||||
ctx._rounding = ctx._prec_rounding[1]
|
||||
except KeyError:
|
||||
raise ValueError('invalid rounding mode')
|
||||
|
||||
prec = property(lambda ctx: ctx._prec, _set_prec)
|
||||
dps = property(lambda ctx: ctx._dps, _set_dps)
|
||||
rounding = property(lambda ctx: ctx._rounding, _set_rounding)
|
||||
rounding = property(lambda ctx: ctx._prec_rounding[1], _set_rounding)
|
||||
|
||||
def _set_pretty_dps(ctx, v):
|
||||
ctx._pretty_repr_dps = True if v == 'repr' else False
|
||||
|
||||
+14
-17
@@ -267,7 +267,9 @@ def to_int(s, rnd=round_fast):
|
||||
input is inf/nan, an exception is raised."""
|
||||
sign, man, exp, bc = s
|
||||
if (not man) and exp:
|
||||
raise ValueError("cannot convert inf or nan to int")
|
||||
if s == fnan:
|
||||
raise ValueError("cannot convert nan to int")
|
||||
raise OverflowError("cannot convert infinity to int")
|
||||
if exp >= 0:
|
||||
if sign:
|
||||
return (-man) << exp
|
||||
@@ -1397,12 +1399,12 @@ _FLOAT_FORMAT_SPECIFICATION_MATCHER = re.compile(r"""
|
||||
(?P<sign>[-+ ]?)
|
||||
(?P<no_neg_0>z)?
|
||||
(?P<alternate>\#)?
|
||||
(?P<zeropad>0(?=[0-9]))?
|
||||
(?P<width>0|[1-9][0-9]*)?
|
||||
(?P<zeropad>0(?=0*[1-9]))?
|
||||
(?P<width>[0-9]+)?
|
||||
(?P<thousands_separators>[,_])?
|
||||
(?:\.
|
||||
(?=[,_0-9]) # lookahead for digit or separator
|
||||
(?P<precision>0|[1-9][0-9]*)?
|
||||
(?P<precision>[0-9]+)?
|
||||
(?P<frac_separators>[,_])?
|
||||
)?
|
||||
(?P<rounding>[UDYZN])?
|
||||
@@ -1478,22 +1480,17 @@ def read_format_spec(format_spec):
|
||||
format_dict['rounding'] = _GMPY_ROUND_CHAR_DICT[rounding_char]
|
||||
|
||||
if match['zeropad']:
|
||||
if match['fill_char']:
|
||||
raise ValueError("Fill character conflicts with '0'"
|
||||
f" in format specifier: '{format_spec}'")
|
||||
if match['align']:
|
||||
raise ValueError("Alignment conflicts with '0'"
|
||||
f" in format specifier: '{format_spec}'")
|
||||
format_dict['align'] = '='
|
||||
format_dict['fill_char'] = '0'
|
||||
if not match['align']:
|
||||
format_dict['align'] = '='
|
||||
if not match['fill_char']:
|
||||
format_dict['fill_char'] = '0'
|
||||
|
||||
if format_dict['precision'] < 0 and (format_dict['type'].lower()
|
||||
not in ['', 'a', 'b']):
|
||||
if format_dict['precision'] < 0 and format_dict['type'].lower() not in ['', 'a', 'b']:
|
||||
format_dict['precision'] = 6
|
||||
else:
|
||||
raise ValueError("Invalid format specifier '{}'".format(format_spec))
|
||||
|
||||
return format_dict
|
||||
|
||||
raise ValueError(f"Invalid format specifier '{format_spec}'")
|
||||
return format_dict
|
||||
|
||||
|
||||
def format_fixed(s, precision=6, rounding=round_nearest):
|
||||
|
||||
@@ -665,6 +665,16 @@ def test_round_bulk(x, n):
|
||||
return
|
||||
assert nstr(mr, n=14, base=16, strip_zeros=False,
|
||||
show_zero_exponent=True, binary_exp=True) == xr.hex()
|
||||
try:
|
||||
xr = round(x)
|
||||
except ValueError:
|
||||
pytest.raises(ValueError, lambda: round(m))
|
||||
except OverflowError:
|
||||
pytest.raises(OverflowError, lambda: round(m))
|
||||
else:
|
||||
mr = round(m)
|
||||
assert type(mr) is int
|
||||
assert mr == xr
|
||||
|
||||
|
||||
def test_rounding_prop():
|
||||
|
||||
@@ -57,7 +57,9 @@ def fmt_str(draw, types='fFeE', for_complex=False):
|
||||
skip_thousand_separators = True
|
||||
|
||||
# Width
|
||||
res += draw(st.sampled_from(['']*7 + list(map(str, range(1, 40)))))
|
||||
res += draw(st.sampled_from(['']*7 + list(map(str, range(1, 40)))
|
||||
+ ([] if for_complex else ['0' + str(_)
|
||||
for _ in range(40)])))
|
||||
|
||||
# grouping character (thousand_separators)
|
||||
gchar = draw(st.sampled_from([''] + list(',_')))
|
||||
@@ -65,7 +67,8 @@ def fmt_str(draw, types='fFeE', for_complex=False):
|
||||
res += gchar
|
||||
|
||||
# Precision
|
||||
prec = draw(st.sampled_from(['']*7 + list(map(str, range(40)))))
|
||||
prec = draw(st.sampled_from(['']*7 + list(map(str, range(40)))
|
||||
+ ['0' + str(_) for _ in range(40)]))
|
||||
if prec:
|
||||
res += '.' + prec
|
||||
if vinfo >= (3, 14):
|
||||
@@ -481,6 +484,8 @@ def test_mpf_fmt_cpython():
|
||||
allow_infinity=True,
|
||||
allow_subnormal=True))
|
||||
@example(fmt='.0g', x=9.995074823339339e-05) # issue 880
|
||||
@example(fmt='.016f', x=0.1) # issue 915
|
||||
@example(fmt='0030f', x=0.3)
|
||||
@example(fmt='0=13,f', x=1.1) # issue 917
|
||||
@example(fmt='013,f', x=1.1)
|
||||
@example(fmt='013,.0%', x=1.1)
|
||||
@@ -628,8 +633,8 @@ def test_mpf_fmt():
|
||||
|
||||
# Tests for = alignment
|
||||
assert f"{mp.mpf('0.24'):=+20.2f}" == '+ 0.24'
|
||||
assert f"{mp.mpf('0.24'):0=+20.2e}" == '+000000000002.40e-01'
|
||||
assert f"{mp.mpf('0.24'):0=+20.2g}" == '+0000000000000000.24'
|
||||
assert f"{mp.mpf('0.24'):=+020.2e}" == '+000000000002.40e-01'
|
||||
assert f"{mp.mpf('0.24'):=+020.2g}" == '+0000000000000000.24'
|
||||
|
||||
# Tests for different kinds of rounding
|
||||
num = mp.mpf('-1.23456789999901234567')
|
||||
@@ -826,13 +831,6 @@ def test_errors():
|
||||
with pytest.raises(ValueError, match="Invalid format specifier '12.3 E '"):
|
||||
f"{mp.mpf('4'):12.3 E }"
|
||||
|
||||
with pytest.raises(ValueError, match="Fill character conflicts"):
|
||||
f"{mp.mpf('4'):q<03f}"
|
||||
with pytest.raises(ValueError, match="Alignment conflicts"):
|
||||
f"{mp.mpf('4'):=03f}"
|
||||
with pytest.raises(ValueError, match="Fill character conflicts"):
|
||||
f"{mp.mpf('4'): =03f}"
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
f"{mp.mpf(1):.f}"
|
||||
with pytest.raises(ValueError):
|
||||
|
||||
Reference in New Issue
Block a user