diff env/lib/python3.7/site-packages/future/builtins/newround.py @ 2:6af9afd405e9 draft

"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
author shellac
date Thu, 14 May 2020 14:56:58 -0400
parents 26e78fe6e8c4
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.7/site-packages/future/builtins/newround.py	Thu May 14 14:56:58 2020 -0400
@@ -0,0 +1,102 @@
+"""
+``python-future``: pure Python implementation of Python 3 round().
+"""
+
+from future.utils import PYPY, PY26, bind_method
+
+# Use the decimal module for simplicity of implementation (and
+# hopefully correctness).
+from decimal import Decimal, ROUND_HALF_EVEN
+
+
+def newround(number, ndigits=None):
+    """
+    See Python 3 documentation: uses Banker's Rounding.
+
+    Delegates to the __round__ method if for some reason this exists.
+
+    If not, rounds a number to a given precision in decimal digits (default
+    0 digits). This returns an int when called with one argument,
+    otherwise the same type as the number. ndigits may be negative.
+
+    See the test_round method in future/tests/test_builtins.py for
+    examples.
+    """
+    return_int = False
+    if ndigits is None:
+        return_int = True
+        ndigits = 0
+    if hasattr(number, '__round__'):
+        return number.__round__(ndigits)
+
+    if ndigits < 0:
+        raise NotImplementedError('negative ndigits not supported yet')
+    exponent = Decimal('10') ** (-ndigits)
+
+    if PYPY:
+        # Work around issue #24: round() breaks on PyPy with NumPy's types
+        if 'numpy' in repr(type(number)):
+            number = float(number)
+
+    if isinstance(number, Decimal):
+        d = number
+    else:
+        if not PY26:
+            d = Decimal.from_float(number).quantize(exponent,
+                                                rounding=ROUND_HALF_EVEN)
+        else:
+            d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN)
+
+    if return_int:
+        return int(d)
+    else:
+        return float(d)
+
+
+### From Python 2.7's decimal.py. Only needed to support Py2.6:
+
+def from_float_26(f):
+    """Converts a float to a decimal number, exactly.
+
+    Note that Decimal.from_float(0.1) is not the same as Decimal('0.1').
+    Since 0.1 is not exactly representable in binary floating point, the
+    value is stored as the nearest representable value which is
+    0x1.999999999999ap-4.  The exact equivalent of the value in decimal
+    is 0.1000000000000000055511151231257827021181583404541015625.
+
+    >>> Decimal.from_float(0.1)
+    Decimal('0.1000000000000000055511151231257827021181583404541015625')
+    >>> Decimal.from_float(float('nan'))
+    Decimal('NaN')
+    >>> Decimal.from_float(float('inf'))
+    Decimal('Infinity')
+    >>> Decimal.from_float(-float('inf'))
+    Decimal('-Infinity')
+    >>> Decimal.from_float(-0.0)
+    Decimal('-0')
+
+    """
+    import math as _math
+    from decimal import _dec_from_triple    # only available on Py2.6 and Py2.7 (not 3.3)
+
+    if isinstance(f, (int, long)):        # handle integer inputs
+        return Decimal(f)
+    if _math.isinf(f) or _math.isnan(f):  # raises TypeError if not a float
+        return Decimal(repr(f))
+    if _math.copysign(1.0, f) == 1.0:
+        sign = 0
+    else:
+        sign = 1
+    n, d = abs(f).as_integer_ratio()
+    # int.bit_length() method doesn't exist on Py2.6:
+    def bit_length(d):
+        if d != 0:
+            return len(bin(abs(d))) - 2
+        else:
+            return 0
+    k = bit_length(d) - 1
+    result = _dec_from_triple(sign, str(n*5**k), -k)
+    return result
+
+
+__all__ = ['newround']