mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
Backport PEP 3141 from the py3k branch to the trunk. This includes r50877 (just
the complex_pow part), r56649, r56652, r56715, r57296, r57302, r57359, r57361, r57372, r57738, r57739, r58017, r58039, r58040, and r59390, and new documentation. The only significant difference is that round(x) returns a float to preserve backward-compatibility. See http://bugs.python.org/issue1689.
This commit is contained in:
parent
27edd829d7
commit
2f3c16be73
21 changed files with 1089 additions and 124 deletions
|
@ -986,10 +986,13 @@ available. They are listed here in alphabetical order.
|
||||||
.. function:: round(x[, n])
|
.. function:: round(x[, n])
|
||||||
|
|
||||||
Return the floating point value *x* rounded to *n* digits after the decimal
|
Return the floating point value *x* rounded to *n* digits after the decimal
|
||||||
point. If *n* is omitted, it defaults to zero. The result is a floating point
|
point. If *n* is omitted, it defaults to zero. Values are rounded to the
|
||||||
number. Values are rounded to the closest multiple of 10 to the power minus
|
closest multiple of 10 to the power minus *n*; if two multiples are equally
|
||||||
*n*; if two multiples are equally close, rounding is done away from 0 (so. for
|
close, rounding is done toward the even choice (so, for example, both
|
||||||
example, ``round(0.5)`` is ``1.0`` and ``round(-0.5)`` is ``-1.0``).
|
``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is
|
||||||
|
``2``). Delegates to ``x.__round__(n)``.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.6
|
||||||
|
|
||||||
|
|
||||||
.. function:: set([iterable])
|
.. function:: set([iterable])
|
||||||
|
@ -1132,6 +1135,14 @@ available. They are listed here in alphabetical order.
|
||||||
.. versionadded:: 2.2
|
.. versionadded:: 2.2
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: trunc(x)
|
||||||
|
|
||||||
|
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
|
||||||
|
a long integer). Delegates to ``x.__trunc__()``.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
|
||||||
.. function:: tuple([iterable])
|
.. function:: tuple([iterable])
|
||||||
|
|
||||||
Return a tuple whose items are the same and in the same order as *iterable*'s
|
Return a tuple whose items are the same and in the same order as *iterable*'s
|
||||||
|
|
|
@ -26,8 +26,9 @@ Number-theoretic and representation functions:
|
||||||
|
|
||||||
.. function:: ceil(x)
|
.. function:: ceil(x)
|
||||||
|
|
||||||
Return the ceiling of *x* as a float, the smallest integer value greater than or
|
Return the ceiling of *x* as a float, the smallest integer value greater than
|
||||||
equal to *x*.
|
or equal to *x*. If *x* is not a float, delegates to ``x.__ceil__()``, which
|
||||||
|
should return an :class:`Integral` value.
|
||||||
|
|
||||||
|
|
||||||
.. function:: fabs(x)
|
.. function:: fabs(x)
|
||||||
|
@ -37,8 +38,9 @@ Number-theoretic and representation functions:
|
||||||
|
|
||||||
.. function:: floor(x)
|
.. function:: floor(x)
|
||||||
|
|
||||||
Return the floor of *x* as a float, the largest integer value less than or equal
|
Return the floor of *x* as a float, the largest integer value less than or
|
||||||
to *x*.
|
equal to *x*. If *x* is not a float, delegates to ``x.__floor__()``, which
|
||||||
|
should return an :class:`Integral` value.
|
||||||
|
|
||||||
|
|
||||||
.. function:: fmod(x, y)
|
.. function:: fmod(x, y)
|
||||||
|
|
99
Doc/library/numbers.rst
Normal file
99
Doc/library/numbers.rst
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
|
||||||
|
:mod:`numbers` --- Numeric abstract base classes
|
||||||
|
================================================
|
||||||
|
|
||||||
|
.. module:: numbers
|
||||||
|
:synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.).
|
||||||
|
|
||||||
|
The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric abstract
|
||||||
|
base classes which progressively define more operations. These concepts also
|
||||||
|
provide a way to distinguish exact from inexact types. None of the types defined
|
||||||
|
in this module can be instantiated.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: Number
|
||||||
|
|
||||||
|
The root of the numeric hierarchy. If you just want to check if an argument
|
||||||
|
*x* is a number, without caring what kind, use ``isinstance(x, Number)``.
|
||||||
|
|
||||||
|
|
||||||
|
Exact and inexact operations
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. class:: Exact
|
||||||
|
|
||||||
|
Subclasses of this type have exact operations.
|
||||||
|
|
||||||
|
As long as the result of a homogenous operation is of the same type, you can
|
||||||
|
assume that it was computed exactly, and there are no round-off errors. Laws
|
||||||
|
like commutativity and associativity hold.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: Inexact
|
||||||
|
|
||||||
|
Subclasses of this type have inexact operations.
|
||||||
|
|
||||||
|
Given X, an instance of :class:`Inexact`, it is possible that ``(X + -X) + 3
|
||||||
|
== 3``, but ``X + (-X + 3) == 0``. The exact form this error takes will vary
|
||||||
|
by type, but it's generally unsafe to compare this type for equality.
|
||||||
|
|
||||||
|
|
||||||
|
The numeric tower
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. class:: Complex
|
||||||
|
|
||||||
|
Subclasses of this type describe complex numbers and include the operations
|
||||||
|
that work on the builtin :class:`complex` type. These are: conversions to
|
||||||
|
:class:`complex` and :class:`bool`, :attr:`.real`, :attr:`.imag`, ``+``,
|
||||||
|
``-``, ``*``, ``/``, :func:`abs`, :meth:`conjugate`, ``==``, and ``!=``. All
|
||||||
|
except ``-`` and ``!=`` are abstract.
|
||||||
|
|
||||||
|
.. attribute:: Complex.real
|
||||||
|
|
||||||
|
Abstract. Retrieves the :class:`Real` component of this number.
|
||||||
|
|
||||||
|
.. attribute:: Complex.imag
|
||||||
|
|
||||||
|
Abstract. Retrieves the :class:`Real` component of this number.
|
||||||
|
|
||||||
|
.. method:: Complex.conjugate()
|
||||||
|
|
||||||
|
Abstract. Returns the complex conjugate. For example, ``(1+3j).conjugate() ==
|
||||||
|
(1-3j)``.
|
||||||
|
|
||||||
|
.. class:: Real
|
||||||
|
|
||||||
|
To :class:`Complex`, :class:`Real` adds the operations that work on real
|
||||||
|
numbers.
|
||||||
|
|
||||||
|
In short, those are: a conversion to :class:`float`, :func:`trunc`,
|
||||||
|
:func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`, ``//``,
|
||||||
|
``%``, ``<``, ``<=``, ``>``, and ``>=``.
|
||||||
|
|
||||||
|
Real also provides defaults for :func:`complex`, :attr:`Complex.real`,
|
||||||
|
:attr:`Complex.imag`, and :meth:`Complex.conjugate`.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: Rational
|
||||||
|
|
||||||
|
Subtypes both :class:`Real` and :class:`Exact`, and adds
|
||||||
|
:attr:`Rational.numerator` and :attr:`Rational.denominator` properties, which
|
||||||
|
should be in lowest terms. With these, it provides a default for
|
||||||
|
:func:`float`.
|
||||||
|
|
||||||
|
.. attribute:: Rational.numerator
|
||||||
|
|
||||||
|
Abstract.
|
||||||
|
|
||||||
|
.. attribute:: Rational.denominator
|
||||||
|
|
||||||
|
Abstract.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: Integral
|
||||||
|
|
||||||
|
Subtypes :class:`Rational` and adds a conversion to :class:`long`, the
|
||||||
|
3-argument form of :func:`pow`, and the bit-string operations: ``<<``,
|
||||||
|
``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`,
|
||||||
|
:attr:`Rational.numerator`, and :attr:`Rational.denominator`.
|
|
@ -6,16 +6,18 @@ Numeric and Mathematical Modules
|
||||||
********************************
|
********************************
|
||||||
|
|
||||||
The modules described in this chapter provide numeric and math-related functions
|
The modules described in this chapter provide numeric and math-related functions
|
||||||
and data types. The :mod:`math` and :mod:`cmath` contain various mathematical
|
and data types. The :mod:`numbers` module defines an abstract hierarchy of
|
||||||
functions for floating-point and complex numbers. For users more interested in
|
numeric types. The :mod:`math` and :mod:`cmath` modules contain various
|
||||||
decimal accuracy than in speed, the :mod:`decimal` module supports exact
|
mathematical functions for floating-point and complex numbers. For users more
|
||||||
representations of decimal numbers.
|
interested in decimal accuracy than in speed, the :mod:`decimal` module supports
|
||||||
|
exact representations of decimal numbers.
|
||||||
|
|
||||||
The following modules are documented in this chapter:
|
The following modules are documented in this chapter:
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
|
numbers.rst
|
||||||
math.rst
|
math.rst
|
||||||
cmath.rst
|
cmath.rst
|
||||||
decimal.rst
|
decimal.rst
|
||||||
|
|
|
@ -270,9 +270,8 @@ numbers of mixed type use the same rule. [#]_ The constructors :func:`int`,
|
||||||
:func:`long`, :func:`float`, and :func:`complex` can be used to produce numbers
|
:func:`long`, :func:`float`, and :func:`complex` can be used to produce numbers
|
||||||
of a specific type.
|
of a specific type.
|
||||||
|
|
||||||
All numeric types (except complex) support the following operations, sorted by
|
All builtin numeric types support the following operations. See
|
||||||
ascending priority (operations in the same box have the same priority; all
|
:ref:`power` and later sections for the operators' priorities.
|
||||||
numeric operations have a higher priority than comparison operations):
|
|
||||||
|
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| Operation | Result | Notes |
|
| Operation | Result | Notes |
|
||||||
|
@ -285,7 +284,7 @@ numeric operations have a higher priority than comparison operations):
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``x / y`` | quotient of *x* and *y* | \(1) |
|
| ``x / y`` | quotient of *x* and *y* | \(1) |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``x // y`` | (floored) quotient of *x* and | \(5) |
|
| ``x // y`` | (floored) quotient of *x* and | (4)(5) |
|
||||||
| | *y* | |
|
| | *y* | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``x % y`` | remainder of ``x / y`` | \(4) |
|
| ``x % y`` | remainder of ``x / y`` | \(4) |
|
||||||
|
@ -294,7 +293,7 @@ numeric operations have a higher priority than comparison operations):
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``+x`` | *x* unchanged | |
|
| ``+x`` | *x* unchanged | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``abs(x)`` | absolute value or magnitude of | |
|
| ``abs(x)`` | absolute value or magnitude of | \(3) |
|
||||||
| | *x* | |
|
| | *x* | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``int(x)`` | *x* converted to integer | \(2) |
|
| ``int(x)`` | *x* converted to integer | \(2) |
|
||||||
|
@ -308,11 +307,11 @@ numeric operations have a higher priority than comparison operations):
|
||||||
| | *im* defaults to zero. | |
|
| | *im* defaults to zero. | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``c.conjugate()`` | conjugate of the complex number | |
|
| ``c.conjugate()`` | conjugate of the complex number | |
|
||||||
| | *c* | |
|
| | *c*. (Identity on real numbers) | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``divmod(x, y)`` | the pair ``(x // y, x % y)`` | (3)(4) |
|
| ``divmod(x, y)`` | the pair ``(x // y, x % y)`` | (3)(4) |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``pow(x, y)`` | *x* to the power *y* | |
|
| ``pow(x, y)`` | *x* to the power *y* | \(3) |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
| ``x ** y`` | *x* to the power *y* | |
|
| ``x ** y`` | *x* to the power *y* | |
|
||||||
+--------------------+---------------------------------+--------+
|
+--------------------+---------------------------------+--------+
|
||||||
|
@ -341,9 +340,12 @@ Notes:
|
||||||
pair: numeric; conversions
|
pair: numeric; conversions
|
||||||
pair: C; language
|
pair: C; language
|
||||||
|
|
||||||
Conversion from floating point to (long or plain) integer may round or truncate
|
Conversion from floating point to (long or plain) integer may round or
|
||||||
as in C; see functions :func:`floor` and :func:`ceil` in the :mod:`math` module
|
truncate as in C.
|
||||||
for well-defined conversions.
|
|
||||||
|
.. deprecated:: 2.6
|
||||||
|
Instead, convert floats to long explicitly with :func:`trunc`,
|
||||||
|
:func:`math.floor`, or :func:`math.ceil`.
|
||||||
|
|
||||||
(3)
|
(3)
|
||||||
See :ref:`built-in-funcs` for a full description.
|
See :ref:`built-in-funcs` for a full description.
|
||||||
|
@ -364,6 +366,22 @@ Notes:
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
All :class:`numbers.Real` types (:class:`int`, :class:`long`, and
|
||||||
|
:class:`float`) also include the following operations:
|
||||||
|
|
||||||
|
+--------------------+--------------------------------+--------+
|
||||||
|
| Operation | Result | Notes |
|
||||||
|
+====================+================================+========+
|
||||||
|
| ``trunc(x)`` | *x* truncated to Integral | |
|
||||||
|
+--------------------+--------------------------------+--------+
|
||||||
|
| ``round(x[, n])`` | *x* rounded to n digits, | |
|
||||||
|
| | rounding half to even. If n is | |
|
||||||
|
| | omitted, it defaults to 0. | |
|
||||||
|
+--------------------+--------------------------------+--------+
|
||||||
|
| ``math.floor(x)`` | the greatest Integral <= *x* | |
|
||||||
|
+--------------------+--------------------------------+--------+
|
||||||
|
| ``math.ceil(x)`` | the least Integral >= *x* | |
|
||||||
|
+--------------------+--------------------------------+--------+
|
||||||
|
|
||||||
.. XXXJH exceptions: overflow (when? what operations?) zerodivision
|
.. XXXJH exceptions: overflow (when? what operations?) zerodivision
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ Ellipsis
|
||||||
indicate the presence of the ``...`` syntax in a slice. Its truth value is
|
indicate the presence of the ``...`` syntax in a slice. Its truth value is
|
||||||
true.
|
true.
|
||||||
|
|
||||||
Numbers
|
:class:`numbers.Number`
|
||||||
.. index:: object: numeric
|
.. index:: object: numeric
|
||||||
|
|
||||||
These are created by numeric literals and returned as results by arithmetic
|
These are created by numeric literals and returned as results by arithmetic
|
||||||
|
@ -162,7 +162,7 @@ Numbers
|
||||||
Python distinguishes between integers, floating point numbers, and complex
|
Python distinguishes between integers, floating point numbers, and complex
|
||||||
numbers:
|
numbers:
|
||||||
|
|
||||||
Integers
|
:class:`numbers.Integral`
|
||||||
.. index:: object: integer
|
.. index:: object: integer
|
||||||
|
|
||||||
These represent elements from the mathematical set of integers (positive and
|
These represent elements from the mathematical set of integers (positive and
|
||||||
|
@ -214,7 +214,7 @@ Numbers
|
||||||
without causing overflow, will yield the same result in the long integer domain
|
without causing overflow, will yield the same result in the long integer domain
|
||||||
or when using mixed operands.
|
or when using mixed operands.
|
||||||
|
|
||||||
Floating point numbers
|
:class:`numbers.Real` (:class:`float`)
|
||||||
.. index::
|
.. index::
|
||||||
object: floating point
|
object: floating point
|
||||||
pair: floating point; number
|
pair: floating point; number
|
||||||
|
@ -229,7 +229,7 @@ Numbers
|
||||||
overhead of using objects in Python, so there is no reason to complicate the
|
overhead of using objects in Python, so there is no reason to complicate the
|
||||||
language with two kinds of floating point numbers.
|
language with two kinds of floating point numbers.
|
||||||
|
|
||||||
Complex numbers
|
:class:`numbers.Complex`
|
||||||
.. index::
|
.. index::
|
||||||
object: complex
|
object: complex
|
||||||
pair: complex; number
|
pair: complex; number
|
||||||
|
|
|
@ -801,7 +801,8 @@ were of integer types and the second argument was negative, an exception was
|
||||||
raised).
|
raised).
|
||||||
|
|
||||||
Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
|
Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
|
||||||
Raising a negative number to a fractional power results in a :exc:`ValueError`.
|
Raising a negative number to a fractional power results in a :class:`complex`
|
||||||
|
number. (Since Python 2.6. In earlier versions it raised a :exc:`ValueError`.)
|
||||||
|
|
||||||
|
|
||||||
.. _unary:
|
.. _unary:
|
||||||
|
|
393
Lib/numbers.py
Normal file
393
Lib/numbers.py
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
# Copyright 2007 Google, Inc. All Rights Reserved.
|
||||||
|
# Licensed to PSF under a Contributor Agreement.
|
||||||
|
|
||||||
|
"""Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
|
||||||
|
|
||||||
|
TODO: Fill out more detailed documentation on the operators."""
|
||||||
|
|
||||||
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||||
|
|
||||||
|
__all__ = ["Number", "Exact", "Inexact",
|
||||||
|
"Complex", "Real", "Rational", "Integral",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Number(object):
|
||||||
|
"""All numbers inherit from this class.
|
||||||
|
|
||||||
|
If you just want to check if an argument x is a number, without
|
||||||
|
caring what kind, use isinstance(x, Number).
|
||||||
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
|
||||||
|
class Exact(Number):
|
||||||
|
"""Operations on instances of this type are exact.
|
||||||
|
|
||||||
|
As long as the result of a homogenous operation is of the same
|
||||||
|
type, you can assume that it was computed exactly, and there are
|
||||||
|
no round-off errors. Laws like commutativity and associativity
|
||||||
|
hold.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Exact.register(int)
|
||||||
|
Exact.register(long)
|
||||||
|
|
||||||
|
|
||||||
|
class Inexact(Number):
|
||||||
|
"""Operations on instances of this type are inexact.
|
||||||
|
|
||||||
|
Given X, an instance of Inexact, it is possible that (X + -X) + 3
|
||||||
|
== 3, but X + (-X + 3) == 0. The exact form this error takes will
|
||||||
|
vary by type, but it's generally unsafe to compare this type for
|
||||||
|
equality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Inexact.register(complex)
|
||||||
|
Inexact.register(float)
|
||||||
|
# Inexact.register(decimal.Decimal)
|
||||||
|
|
||||||
|
|
||||||
|
class Complex(Number):
|
||||||
|
"""Complex defines the operations that work on the builtin complex type.
|
||||||
|
|
||||||
|
In short, those are: a conversion to complex, .real, .imag, +, -,
|
||||||
|
*, /, abs(), .conjugate, ==, and !=.
|
||||||
|
|
||||||
|
If it is given heterogenous arguments, and doesn't have special
|
||||||
|
knowledge about them, it should fall back to the builtin complex
|
||||||
|
type as described below.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __complex__(self):
|
||||||
|
"""Return a builtin complex instance. Called for complex(self)."""
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
"""True if self != 0. Called for bool(self)."""
|
||||||
|
return self != 0
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def real(self):
|
||||||
|
"""Retrieve the real component of this number.
|
||||||
|
|
||||||
|
This should subclass Real.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def imag(self):
|
||||||
|
"""Retrieve the real component of this number.
|
||||||
|
|
||||||
|
This should subclass Real.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __add__(self, other):
|
||||||
|
"""self + other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __radd__(self, other):
|
||||||
|
"""other + self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __neg__(self):
|
||||||
|
"""-self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __pos__(self):
|
||||||
|
"""+self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
"""self - other"""
|
||||||
|
return self + -other
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
"""other - self"""
|
||||||
|
return -self + other
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __mul__(self, other):
|
||||||
|
"""self * other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rmul__(self, other):
|
||||||
|
"""other * self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __div__(self, other):
|
||||||
|
"""self / other; should promote to float or complex when necessary."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rdiv__(self, other):
|
||||||
|
"""other / self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __pow__(self, exponent):
|
||||||
|
"""self**exponent; should promote to float or complex when necessary."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rpow__(self, base):
|
||||||
|
"""base ** self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __abs__(self):
|
||||||
|
"""Returns the Real distance from 0. Called for abs(self)."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def conjugate(self):
|
||||||
|
"""(x+y*i).conjugate() returns (x-y*i)."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __eq__(self, other):
|
||||||
|
"""self == other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# __ne__ is inherited from object and negates whatever __eq__ does.
|
||||||
|
|
||||||
|
Complex.register(complex)
|
||||||
|
|
||||||
|
|
||||||
|
class Real(Complex):
|
||||||
|
"""To Complex, Real adds the operations that work on real numbers.
|
||||||
|
|
||||||
|
In short, those are: a conversion to float, trunc(), divmod,
|
||||||
|
%, <, <=, >, and >=.
|
||||||
|
|
||||||
|
Real also provides defaults for the derived operations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __float__(self):
|
||||||
|
"""Any Real can be converted to a native float object.
|
||||||
|
|
||||||
|
Called for float(self)."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __trunc__(self):
|
||||||
|
"""trunc(self): Truncates self to an Integral.
|
||||||
|
|
||||||
|
Returns an Integral i such that:
|
||||||
|
* i>0 iff self>0;
|
||||||
|
* abs(i) <= abs(self);
|
||||||
|
* for any Integral j satisfying the first two conditions,
|
||||||
|
abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
|
||||||
|
i.e. "truncate towards 0".
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __floor__(self):
|
||||||
|
"""Finds the greatest Integral <= self."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __ceil__(self):
|
||||||
|
"""Finds the least Integral >= self."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __round__(self, ndigits=None):
|
||||||
|
"""Rounds self to ndigits decimal places, defaulting to 0.
|
||||||
|
|
||||||
|
If ndigits is omitted or None, returns an Integral, otherwise
|
||||||
|
returns a Real. Rounds half toward even.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __divmod__(self, other):
|
||||||
|
"""divmod(self, other): The pair (self // other, self % other).
|
||||||
|
|
||||||
|
Sometimes this can be computed faster than the pair of
|
||||||
|
operations.
|
||||||
|
"""
|
||||||
|
return (self // other, self % other)
|
||||||
|
|
||||||
|
def __rdivmod__(self, other):
|
||||||
|
"""divmod(other, self): The pair (self // other, self % other).
|
||||||
|
|
||||||
|
Sometimes this can be computed faster than the pair of
|
||||||
|
operations.
|
||||||
|
"""
|
||||||
|
return (other // self, other % self)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __floordiv__(self, other):
|
||||||
|
"""self // other: The floor() of self/other."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rfloordiv__(self, other):
|
||||||
|
"""other // self: The floor() of other/self."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __mod__(self, other):
|
||||||
|
"""self % other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rmod__(self, other):
|
||||||
|
"""other % self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __lt__(self, other):
|
||||||
|
"""self < other
|
||||||
|
|
||||||
|
< on Reals defines a total ordering, except perhaps for NaN."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __le__(self, other):
|
||||||
|
"""self <= other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Concrete implementations of Complex abstract methods.
|
||||||
|
def __complex__(self):
|
||||||
|
"""complex(self) == complex(float(self), 0)"""
|
||||||
|
return complex(float(self))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def real(self):
|
||||||
|
"""Real numbers are their real component."""
|
||||||
|
return +self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def imag(self):
|
||||||
|
"""Real numbers have no imaginary component."""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def conjugate(self):
|
||||||
|
"""Conjugate is a no-op for Reals."""
|
||||||
|
return +self
|
||||||
|
|
||||||
|
Real.register(float)
|
||||||
|
# Real.register(decimal.Decimal)
|
||||||
|
|
||||||
|
|
||||||
|
class Rational(Real, Exact):
|
||||||
|
""".numerator and .denominator should be in lowest terms."""
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def numerator(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def denominator(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Concrete implementation of Real's conversion to float.
|
||||||
|
def __float__(self):
|
||||||
|
"""float(self) = self.numerator / self.denominator"""
|
||||||
|
return self.numerator / self.denominator
|
||||||
|
|
||||||
|
|
||||||
|
class Integral(Rational):
|
||||||
|
"""Integral adds a conversion to long and the bit-string operations."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __long__(self):
|
||||||
|
"""long(self)"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __index__(self):
|
||||||
|
"""index(self)"""
|
||||||
|
return long(self)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __pow__(self, exponent, modulus=None):
|
||||||
|
"""self ** exponent % modulus, but maybe faster.
|
||||||
|
|
||||||
|
Accept the modulus argument if you want to support the
|
||||||
|
3-argument version of pow(). Raise a TypeError if exponent < 0
|
||||||
|
or any argument isn't Integral. Otherwise, just implement the
|
||||||
|
2-argument version described in Complex.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __lshift__(self, other):
|
||||||
|
"""self << other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rlshift__(self, other):
|
||||||
|
"""other << self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rshift__(self, other):
|
||||||
|
"""self >> other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rrshift__(self, other):
|
||||||
|
"""other >> self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __and__(self, other):
|
||||||
|
"""self & other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rand__(self, other):
|
||||||
|
"""other & self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __xor__(self, other):
|
||||||
|
"""self ^ other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __rxor__(self, other):
|
||||||
|
"""other ^ self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __or__(self, other):
|
||||||
|
"""self | other"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __ror__(self, other):
|
||||||
|
"""other | self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __invert__(self):
|
||||||
|
"""~self"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Concrete implementations of Rational and Real abstract methods.
|
||||||
|
def __float__(self):
|
||||||
|
"""float(self) == float(long(self))"""
|
||||||
|
return float(long(self))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def numerator(self):
|
||||||
|
"""Integers are their own numerators."""
|
||||||
|
return +self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def denominator(self):
|
||||||
|
"""Integers have a denominator of 1."""
|
||||||
|
return 1
|
||||||
|
|
||||||
|
Integral.register(int)
|
||||||
|
Integral.register(long)
|
62
Lib/test/test_abstract_numbers.py
Normal file
62
Lib/test/test_abstract_numbers.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
"""Unit tests for numbers.py."""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from test import test_support
|
||||||
|
from numbers import Number
|
||||||
|
from numbers import Exact, Inexact
|
||||||
|
from numbers import Complex, Real, Rational, Integral
|
||||||
|
import operator
|
||||||
|
|
||||||
|
class TestNumbers(unittest.TestCase):
|
||||||
|
def test_int(self):
|
||||||
|
self.failUnless(issubclass(int, Integral))
|
||||||
|
self.failUnless(issubclass(int, Complex))
|
||||||
|
self.failUnless(issubclass(int, Exact))
|
||||||
|
self.failIf(issubclass(int, Inexact))
|
||||||
|
|
||||||
|
self.assertEqual(7, int(7).real)
|
||||||
|
self.assertEqual(0, int(7).imag)
|
||||||
|
self.assertEqual(7, int(7).conjugate())
|
||||||
|
self.assertEqual(7, int(7).numerator)
|
||||||
|
self.assertEqual(1, int(7).denominator)
|
||||||
|
|
||||||
|
def test_long(self):
|
||||||
|
self.failUnless(issubclass(long, Integral))
|
||||||
|
self.failUnless(issubclass(long, Complex))
|
||||||
|
self.failUnless(issubclass(long, Exact))
|
||||||
|
self.failIf(issubclass(long, Inexact))
|
||||||
|
|
||||||
|
self.assertEqual(7, long(7).real)
|
||||||
|
self.assertEqual(0, long(7).imag)
|
||||||
|
self.assertEqual(7, long(7).conjugate())
|
||||||
|
self.assertEqual(7, long(7).numerator)
|
||||||
|
self.assertEqual(1, long(7).denominator)
|
||||||
|
|
||||||
|
def test_float(self):
|
||||||
|
self.failIf(issubclass(float, Rational))
|
||||||
|
self.failUnless(issubclass(float, Real))
|
||||||
|
self.failIf(issubclass(float, Exact))
|
||||||
|
self.failUnless(issubclass(float, Inexact))
|
||||||
|
|
||||||
|
self.assertEqual(7.3, float(7.3).real)
|
||||||
|
self.assertEqual(0, float(7.3).imag)
|
||||||
|
self.assertEqual(7.3, float(7.3).conjugate())
|
||||||
|
|
||||||
|
def test_complex(self):
|
||||||
|
self.failIf(issubclass(complex, Real))
|
||||||
|
self.failUnless(issubclass(complex, Complex))
|
||||||
|
self.failIf(issubclass(complex, Exact))
|
||||||
|
self.failUnless(issubclass(complex, Inexact))
|
||||||
|
|
||||||
|
c1, c2 = complex(3, 2), complex(4,1)
|
||||||
|
# XXX: This is not ideal, but see the comment in builtin_trunc().
|
||||||
|
self.assertRaises(AttributeError, trunc, c1)
|
||||||
|
self.assertRaises(TypeError, float, c1)
|
||||||
|
self.assertRaises(TypeError, int, c1)
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
test_support.run_unittest(TestNumbers)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
|
@ -1450,11 +1450,13 @@ class BuiltinTest(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertAlmostEqual(pow(x, y, z), 24.0)
|
self.assertAlmostEqual(pow(x, y, z), 24.0)
|
||||||
|
|
||||||
|
self.assertAlmostEqual(pow(-1, 0.5), 1j)
|
||||||
|
self.assertAlmostEqual(pow(-1, 1./3), 0.5 + 0.8660254037844386j)
|
||||||
|
|
||||||
self.assertRaises(TypeError, pow, -1, -2, 3)
|
self.assertRaises(TypeError, pow, -1, -2, 3)
|
||||||
self.assertRaises(ValueError, pow, 1, 2, 0)
|
self.assertRaises(ValueError, pow, 1, 2, 0)
|
||||||
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
|
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
|
||||||
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
|
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
|
||||||
self.assertRaises(ValueError, pow, -342.43, 0.234)
|
|
||||||
|
|
||||||
self.assertRaises(TypeError, pow)
|
self.assertRaises(TypeError, pow)
|
||||||
|
|
||||||
|
@ -1622,6 +1624,7 @@ class BuiltinTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_round(self):
|
def test_round(self):
|
||||||
self.assertEqual(round(0.0), 0.0)
|
self.assertEqual(round(0.0), 0.0)
|
||||||
|
self.assertEqual(type(round(0.0)), float) # Will be int in 3.0.
|
||||||
self.assertEqual(round(1.0), 1.0)
|
self.assertEqual(round(1.0), 1.0)
|
||||||
self.assertEqual(round(10.0), 10.0)
|
self.assertEqual(round(10.0), 10.0)
|
||||||
self.assertEqual(round(1000000000.0), 1000000000.0)
|
self.assertEqual(round(1000000000.0), 1000000000.0)
|
||||||
|
@ -1650,12 +1653,50 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(round(-999999999.9), -1000000000.0)
|
self.assertEqual(round(-999999999.9), -1000000000.0)
|
||||||
|
|
||||||
self.assertEqual(round(-8.0, -1), -10.0)
|
self.assertEqual(round(-8.0, -1), -10.0)
|
||||||
|
self.assertEqual(type(round(-8.0, -1)), float)
|
||||||
|
|
||||||
|
self.assertEqual(type(round(-8.0, 0)), float)
|
||||||
|
self.assertEqual(type(round(-8.0, 1)), float)
|
||||||
|
|
||||||
|
# Check even / odd rounding behaviour
|
||||||
|
self.assertEqual(round(5.5), 6)
|
||||||
|
self.assertEqual(round(6.5), 6)
|
||||||
|
self.assertEqual(round(-5.5), -6)
|
||||||
|
self.assertEqual(round(-6.5), -6)
|
||||||
|
|
||||||
|
# Check behavior on ints
|
||||||
|
self.assertEqual(round(0), 0)
|
||||||
|
self.assertEqual(round(8), 8)
|
||||||
|
self.assertEqual(round(-8), -8)
|
||||||
|
self.assertEqual(type(round(0)), float) # Will be int in 3.0.
|
||||||
|
self.assertEqual(type(round(-8, -1)), float)
|
||||||
|
self.assertEqual(type(round(-8, 0)), float)
|
||||||
|
self.assertEqual(type(round(-8, 1)), float)
|
||||||
|
|
||||||
# test new kwargs
|
# test new kwargs
|
||||||
self.assertEqual(round(number=-8.0, ndigits=-1), -10.0)
|
self.assertEqual(round(number=-8.0, ndigits=-1), -10.0)
|
||||||
|
|
||||||
self.assertRaises(TypeError, round)
|
self.assertRaises(TypeError, round)
|
||||||
|
|
||||||
|
# test generic rounding delegation for reals
|
||||||
|
class TestRound(object):
|
||||||
|
def __round__(self):
|
||||||
|
return 23
|
||||||
|
|
||||||
|
class TestNoRound(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.assertEqual(round(TestRound()), 23)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, round, 1, 2, 3)
|
||||||
|
# XXX: This is not ideal, but see the comment in builtin_round().
|
||||||
|
self.assertRaises(AttributeError, round, TestNoRound())
|
||||||
|
|
||||||
|
t = TestNoRound()
|
||||||
|
t.__round__ = lambda *args: args
|
||||||
|
self.assertEquals((), round(t))
|
||||||
|
self.assertEquals((0,), round(t, 0))
|
||||||
|
|
||||||
def test_setattr(self):
|
def test_setattr(self):
|
||||||
setattr(sys, 'spam', 1)
|
setattr(sys, 'spam', 1)
|
||||||
self.assertEqual(sys.spam, 1)
|
self.assertEqual(sys.spam, 1)
|
||||||
|
@ -1697,6 +1738,38 @@ class BuiltinTest(unittest.TestCase):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
self.assertRaises(ValueError, sum, BadSeq())
|
self.assertRaises(ValueError, sum, BadSeq())
|
||||||
|
|
||||||
|
def test_trunc(self):
|
||||||
|
|
||||||
|
self.assertEqual(trunc(1), 1)
|
||||||
|
self.assertEqual(trunc(-1), -1)
|
||||||
|
self.assertEqual(type(trunc(1)), int)
|
||||||
|
self.assertEqual(type(trunc(1.5)), int)
|
||||||
|
self.assertEqual(trunc(1.5), 1)
|
||||||
|
self.assertEqual(trunc(-1.5), -1)
|
||||||
|
self.assertEqual(trunc(1.999999), 1)
|
||||||
|
self.assertEqual(trunc(-1.999999), -1)
|
||||||
|
self.assertEqual(trunc(-0.999999), -0)
|
||||||
|
self.assertEqual(trunc(-100.999), -100)
|
||||||
|
|
||||||
|
class TestTrunc(object):
|
||||||
|
def __trunc__(self):
|
||||||
|
return 23
|
||||||
|
|
||||||
|
class TestNoTrunc(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.assertEqual(trunc(TestTrunc()), 23)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, trunc)
|
||||||
|
self.assertRaises(TypeError, trunc, 1, 2)
|
||||||
|
# XXX: This is not ideal, but see the comment in builtin_trunc().
|
||||||
|
self.assertRaises(AttributeError, trunc, TestNoTrunc())
|
||||||
|
|
||||||
|
t = TestNoTrunc()
|
||||||
|
t.__trunc__ = lambda *args: args
|
||||||
|
self.assertEquals((), trunc(t))
|
||||||
|
self.assertRaises(TypeError, trunc, t, 0)
|
||||||
|
|
||||||
def test_tuple(self):
|
def test_tuple(self):
|
||||||
self.assertEqual(tuple(()), ())
|
self.assertEqual(tuple(()), ())
|
||||||
t0_3 = (0, 1, 2, 3)
|
t0_3 = (0, 1, 2, 3)
|
||||||
|
|
|
@ -385,7 +385,9 @@ class LongTest(unittest.TestCase):
|
||||||
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
|
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
|
||||||
"math.sin(huge)", "math.sin(mhuge)",
|
"math.sin(huge)", "math.sin(mhuge)",
|
||||||
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
|
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
|
||||||
"math.floor(huge)", "math.floor(mhuge)"]:
|
# math.floor() of an int returns an int now
|
||||||
|
##"math.floor(huge)", "math.floor(mhuge)",
|
||||||
|
]:
|
||||||
|
|
||||||
self.assertRaises(OverflowError, eval, test, namespace)
|
self.assertRaises(OverflowError, eval, test, namespace)
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,19 @@ class MathTests(unittest.TestCase):
|
||||||
self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
|
self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
|
||||||
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
|
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
|
||||||
|
|
||||||
|
class TestCeil(object):
|
||||||
|
def __ceil__(self):
|
||||||
|
return 42
|
||||||
|
class TestNoCeil(object):
|
||||||
|
pass
|
||||||
|
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
|
||||||
|
self.assertRaises(TypeError, math.ceil, TestNoCeil())
|
||||||
|
|
||||||
|
t = TestNoCeil()
|
||||||
|
t.__ceil__ = lambda *args: args
|
||||||
|
self.assertRaises(TypeError, math.ceil, t)
|
||||||
|
self.assertRaises(TypeError, math.ceil, t, 0)
|
||||||
|
|
||||||
def testCos(self):
|
def testCos(self):
|
||||||
self.assertRaises(TypeError, math.cos)
|
self.assertRaises(TypeError, math.cos)
|
||||||
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
|
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
|
||||||
|
@ -101,6 +114,19 @@ class MathTests(unittest.TestCase):
|
||||||
self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
|
self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
|
||||||
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
|
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
|
||||||
|
|
||||||
|
class TestFloor(object):
|
||||||
|
def __floor__(self):
|
||||||
|
return 42
|
||||||
|
class TestNoFloor(object):
|
||||||
|
pass
|
||||||
|
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
|
||||||
|
self.assertRaises(TypeError, math.floor, TestNoFloor())
|
||||||
|
|
||||||
|
t = TestNoFloor()
|
||||||
|
t.__floor__ = lambda *args: args
|
||||||
|
self.assertRaises(TypeError, math.floor, t)
|
||||||
|
self.assertRaises(TypeError, math.floor, t, 0)
|
||||||
|
|
||||||
def testFmod(self):
|
def testFmod(self):
|
||||||
self.assertRaises(TypeError, math.fmod)
|
self.assertRaises(TypeError, math.fmod)
|
||||||
self.ftest('fmod(10,1)', math.fmod(10,1), 0)
|
self.ftest('fmod(10,1)', math.fmod(10,1), 0)
|
||||||
|
|
|
@ -2264,13 +2264,34 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
expected = ['startTest', 'test', 'stopTest']
|
expected = ['startTest', 'test', 'stopTest']
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
class Test_Assertions(TestCase):
|
||||||
|
def test_AlmostEqual(self):
|
||||||
|
self.failUnlessAlmostEqual(1.00000001, 1.0)
|
||||||
|
self.failIfAlmostEqual(1.0000001, 1.0)
|
||||||
|
self.assertRaises(AssertionError,
|
||||||
|
self.failUnlessAlmostEqual, 1.0000001, 1.0)
|
||||||
|
self.assertRaises(AssertionError,
|
||||||
|
self.failIfAlmostEqual, 1.00000001, 1.0)
|
||||||
|
|
||||||
|
self.failUnlessAlmostEqual(1.1, 1.0, places=0)
|
||||||
|
self.assertRaises(AssertionError,
|
||||||
|
self.failUnlessAlmostEqual, 1.1, 1.0, places=1)
|
||||||
|
|
||||||
|
self.failUnlessAlmostEqual(0, .1+.1j, places=0)
|
||||||
|
self.failIfAlmostEqual(0, .1+.1j, places=1)
|
||||||
|
self.assertRaises(AssertionError,
|
||||||
|
self.failUnlessAlmostEqual, 0, .1+.1j, places=1)
|
||||||
|
self.assertRaises(AssertionError,
|
||||||
|
self.failIfAlmostEqual, 0, .1+.1j, places=0)
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
## Main
|
## Main
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test_support.run_unittest(Test_TestCase, Test_TestLoader,
|
test_support.run_unittest(Test_TestCase, Test_TestLoader,
|
||||||
Test_TestSuite, Test_TestResult, Test_FunctionTestCase)
|
Test_TestSuite, Test_TestResult, Test_FunctionTestCase,
|
||||||
|
Test_Assertions)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
test_main()
|
||||||
|
|
|
@ -358,7 +358,7 @@ class TestCase:
|
||||||
Note that decimal places (from zero) are usually not the same
|
Note that decimal places (from zero) are usually not the same
|
||||||
as significant digits (measured from the most signficant digit).
|
as significant digits (measured from the most signficant digit).
|
||||||
"""
|
"""
|
||||||
if round(second-first, places) != 0:
|
if round(abs(second-first), places) != 0:
|
||||||
raise self.failureException, \
|
raise self.failureException, \
|
||||||
(msg or '%r != %r within %r places' % (first, second, places))
|
(msg or '%r != %r within %r places' % (first, second, places))
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ class TestCase:
|
||||||
Note that decimal places (from zero) are usually not the same
|
Note that decimal places (from zero) are usually not the same
|
||||||
as significant digits (measured from the most signficant digit).
|
as significant digits (measured from the most signficant digit).
|
||||||
"""
|
"""
|
||||||
if round(second-first, places) == 0:
|
if round(abs(second-first), places) == 0:
|
||||||
raise self.failureException, \
|
raise self.failureException, \
|
||||||
(msg or '%r == %r within %r places' % (first, second, places))
|
(msg or '%r == %r within %r places' % (first, second, places))
|
||||||
|
|
||||||
|
|
|
@ -346,6 +346,8 @@ Core and builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #1689: PEP 3141, numeric abstract base classes.
|
||||||
|
|
||||||
- Tk issue #1851526: Return results from Python callbacks to Tcl as
|
- Tk issue #1851526: Return results from Python callbacks to Tcl as
|
||||||
Tcl objects.
|
Tcl objects.
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,28 @@ FUNC1(atan, atan,
|
||||||
FUNC2(atan2, atan2,
|
FUNC2(atan2, atan2,
|
||||||
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
|
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
|
||||||
"Unlike atan(y/x), the signs of both x and y are considered.")
|
"Unlike atan(y/x), the signs of both x and y are considered.")
|
||||||
FUNC1(ceil, ceil,
|
|
||||||
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
|
static PyObject * math_ceil(PyObject *self, PyObject *number) {
|
||||||
"This is the smallest integral value >= x.")
|
static PyObject *ceil_str = NULL;
|
||||||
|
PyObject *method;
|
||||||
|
|
||||||
|
if (ceil_str == NULL) {
|
||||||
|
ceil_str = PyString_FromString("__ceil__");
|
||||||
|
if (ceil_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
method = _PyType_Lookup(Py_Type(number), ceil_str);
|
||||||
|
if (method == NULL)
|
||||||
|
return math_1(number, ceil);
|
||||||
|
else
|
||||||
|
return PyObject_CallFunction(method, "O", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(math_ceil_doc,
|
||||||
|
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
|
||||||
|
"This is the smallest integral value >= x.");
|
||||||
|
|
||||||
FUNC1(cos, cos,
|
FUNC1(cos, cos,
|
||||||
"cos(x)\n\nReturn the cosine of x (measured in radians).")
|
"cos(x)\n\nReturn the cosine of x (measured in radians).")
|
||||||
FUNC1(cosh, cosh,
|
FUNC1(cosh, cosh,
|
||||||
|
@ -118,9 +137,28 @@ FUNC1(exp, exp,
|
||||||
"exp(x)\n\nReturn e raised to the power of x.")
|
"exp(x)\n\nReturn e raised to the power of x.")
|
||||||
FUNC1(fabs, fabs,
|
FUNC1(fabs, fabs,
|
||||||
"fabs(x)\n\nReturn the absolute value of the float x.")
|
"fabs(x)\n\nReturn the absolute value of the float x.")
|
||||||
FUNC1(floor, floor,
|
|
||||||
"floor(x)\n\nReturn the floor of x as a float.\n"
|
static PyObject * math_floor(PyObject *self, PyObject *number) {
|
||||||
"This is the largest integral value <= x.")
|
static PyObject *floor_str = NULL;
|
||||||
|
PyObject *method;
|
||||||
|
|
||||||
|
if (floor_str == NULL) {
|
||||||
|
floor_str = PyString_FromString("__floor__");
|
||||||
|
if (floor_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
method = _PyType_Lookup(Py_Type(number), floor_str);
|
||||||
|
if (method == NULL)
|
||||||
|
return math_1(number, floor);
|
||||||
|
else
|
||||||
|
return PyObject_CallFunction(method, "O", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(math_floor_doc,
|
||||||
|
"floor(x)\n\nReturn the floor of x as a float.\n"
|
||||||
|
"This is the largest integral value <= x.");
|
||||||
|
|
||||||
FUNC2(fmod, fmod,
|
FUNC2(fmod, fmod,
|
||||||
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
|
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
|
||||||
" x % y may differ.")
|
" x % y may differ.")
|
||||||
|
|
|
@ -385,6 +385,41 @@ complex_hash(PyComplexObject *v)
|
||||||
return combined;
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This macro may return! */
|
||||||
|
#define TO_COMPLEX(obj, c) \
|
||||||
|
if (PyComplex_Check(obj)) \
|
||||||
|
c = ((PyComplexObject *)(obj))->cval; \
|
||||||
|
else if (to_complex(&(obj), &(c)) < 0) \
|
||||||
|
return (obj)
|
||||||
|
|
||||||
|
static int
|
||||||
|
to_complex(PyObject **pobj, Py_complex *pc)
|
||||||
|
{
|
||||||
|
PyObject *obj = *pobj;
|
||||||
|
|
||||||
|
pc->real = pc->imag = 0.0;
|
||||||
|
if (PyInt_Check(obj)) {
|
||||||
|
pc->real = PyInt_AS_LONG(obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (PyLong_Check(obj)) {
|
||||||
|
pc->real = PyLong_AsDouble(obj);
|
||||||
|
if (pc->real == -1.0 && PyErr_Occurred()) {
|
||||||
|
*pobj = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (PyFloat_Check(obj)) {
|
||||||
|
pc->real = PyFloat_AsDouble(obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Py_INCREF(Py_NotImplemented);
|
||||||
|
*pobj = Py_NotImplemented;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
complex_add(PyComplexObject *v, PyComplexObject *w)
|
complex_add(PyComplexObject *v, PyComplexObject *w)
|
||||||
{
|
{
|
||||||
|
@ -502,24 +537,27 @@ complex_divmod(PyComplexObject *v, PyComplexObject *w)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z)
|
complex_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
{
|
{
|
||||||
Py_complex p;
|
Py_complex p;
|
||||||
Py_complex exponent;
|
Py_complex exponent;
|
||||||
long int_exponent;
|
long int_exponent;
|
||||||
|
Py_complex a, b;
|
||||||
|
TO_COMPLEX(v, a);
|
||||||
|
TO_COMPLEX(w, b);
|
||||||
|
|
||||||
if ((PyObject *)z!=Py_None) {
|
if (z!=Py_None) {
|
||||||
PyErr_SetString(PyExc_ValueError, "complex modulo");
|
PyErr_SetString(PyExc_ValueError, "complex modulo");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyFPE_START_PROTECT("complex_pow", return 0)
|
PyFPE_START_PROTECT("complex_pow", return 0)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
exponent = ((PyComplexObject*)w)->cval;
|
exponent = b;
|
||||||
int_exponent = (long)exponent.real;
|
int_exponent = (long)exponent.real;
|
||||||
if (exponent.imag == 0. && exponent.real == int_exponent)
|
if (exponent.imag == 0. && exponent.real == int_exponent)
|
||||||
p = c_powi(v->cval,int_exponent);
|
p = c_powi(a,int_exponent);
|
||||||
else
|
else
|
||||||
p = c_pow(v->cval,exponent);
|
p = c_pow(a,exponent);
|
||||||
|
|
||||||
PyFPE_END_PROTECT(p)
|
PyFPE_END_PROTECT(p)
|
||||||
Py_ADJUST_ERANGE2(p.real, p.imag);
|
Py_ADJUST_ERANGE2(p.real, p.imag);
|
||||||
|
@ -541,6 +579,10 @@ complex_int_div(PyComplexObject *v, PyComplexObject *w)
|
||||||
{
|
{
|
||||||
PyObject *t, *r;
|
PyObject *t, *r;
|
||||||
|
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"complex divmod(), // and % are deprecated") < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
t = complex_divmod(v, w);
|
t = complex_divmod(v, w);
|
||||||
if (t != NULL) {
|
if (t != NULL) {
|
||||||
r = PyTuple_GET_ITEM(t, 0);
|
r = PyTuple_GET_ITEM(t, 0);
|
||||||
|
@ -695,6 +737,11 @@ complex_conjugate(PyObject *self)
|
||||||
return PyComplex_FromCComplex(c);
|
return PyComplex_FromCComplex(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(complex_conjugate_doc,
|
||||||
|
"complex.conjugate() -> complex\n"
|
||||||
|
"\n"
|
||||||
|
"Returns the complex conjugate of its argument. (3-4j).conjugate() == 3+4j.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
complex_getnewargs(PyComplexObject *v)
|
complex_getnewargs(PyComplexObject *v)
|
||||||
{
|
{
|
||||||
|
@ -702,7 +749,8 @@ complex_getnewargs(PyComplexObject *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef complex_methods[] = {
|
static PyMethodDef complex_methods[] = {
|
||||||
{"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS},
|
{"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS,
|
||||||
|
complex_conjugate_doc},
|
||||||
{"__getnewargs__", (PyCFunction)complex_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)complex_getnewargs, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
|
@ -986,9 +986,10 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
* bugs so we have to figure it out ourselves.
|
* bugs so we have to figure it out ourselves.
|
||||||
*/
|
*/
|
||||||
if (iw != floor(iw)) {
|
if (iw != floor(iw)) {
|
||||||
PyErr_SetString(PyExc_ValueError, "negative number "
|
/* Negative numbers raised to fractional powers
|
||||||
"cannot be raised to a fractional power");
|
* become complex.
|
||||||
return NULL;
|
*/
|
||||||
|
return PyComplex_Type.tp_as_number->nb_power(v, w, z);
|
||||||
}
|
}
|
||||||
/* iw is an exact integer, albeit perhaps a very large one.
|
/* iw is an exact integer, albeit perhaps a very large one.
|
||||||
* -1 raised to an exact integer should never be exceptional.
|
* -1 raised to an exact integer should never be exceptional.
|
||||||
|
@ -1034,17 +1035,6 @@ float_neg(PyFloatObject *v)
|
||||||
return PyFloat_FromDouble(-v->ob_fval);
|
return PyFloat_FromDouble(-v->ob_fval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
float_pos(PyFloatObject *v)
|
|
||||||
{
|
|
||||||
if (PyFloat_CheckExact(v)) {
|
|
||||||
Py_INCREF(v);
|
|
||||||
return (PyObject *)v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyFloat_FromDouble(v->ob_fval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
float_abs(PyFloatObject *v)
|
float_abs(PyFloatObject *v)
|
||||||
{
|
{
|
||||||
|
@ -1083,14 +1073,7 @@ float_coerce(PyObject **pv, PyObject **pw)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
float_long(PyObject *v)
|
float_trunc(PyObject *v)
|
||||||
{
|
|
||||||
double x = PyFloat_AsDouble(v);
|
|
||||||
return PyLong_FromDouble(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
float_int(PyObject *v)
|
|
||||||
{
|
{
|
||||||
double x = PyFloat_AsDouble(v);
|
double x = PyFloat_AsDouble(v);
|
||||||
double wholepart; /* integral portion of x, rounded toward 0 */
|
double wholepart; /* integral portion of x, rounded toward 0 */
|
||||||
|
@ -1115,6 +1098,54 @@ float_int(PyObject *v)
|
||||||
return PyLong_FromDouble(wholepart);
|
return PyLong_FromDouble(wholepart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
float_round(PyObject *v, PyObject *args)
|
||||||
|
{
|
||||||
|
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
|
||||||
|
double x;
|
||||||
|
double f;
|
||||||
|
double flr, cil;
|
||||||
|
double rounded;
|
||||||
|
int i;
|
||||||
|
int ndigits = UNDEF_NDIGITS;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|i", &ndigits))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
x = PyFloat_AsDouble(v);
|
||||||
|
|
||||||
|
if (ndigits != UNDEF_NDIGITS) {
|
||||||
|
f = 1.0;
|
||||||
|
i = abs(ndigits);
|
||||||
|
while (--i >= 0)
|
||||||
|
f = f*10.0;
|
||||||
|
if (ndigits < 0)
|
||||||
|
x /= f;
|
||||||
|
else
|
||||||
|
x *= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
flr = floor(x);
|
||||||
|
cil = ceil(x);
|
||||||
|
|
||||||
|
if (x-flr > 0.5)
|
||||||
|
rounded = cil;
|
||||||
|
else if (x-flr == 0.5)
|
||||||
|
rounded = fmod(flr, 2) == 0 ? flr : cil;
|
||||||
|
else
|
||||||
|
rounded = flr;
|
||||||
|
|
||||||
|
if (ndigits != UNDEF_NDIGITS) {
|
||||||
|
if (ndigits < 0)
|
||||||
|
rounded *= f;
|
||||||
|
else
|
||||||
|
rounded /= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyFloat_FromDouble(rounded);
|
||||||
|
#undef UNDEF_NDIGITS
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
float_float(PyObject *v)
|
float_float(PyObject *v)
|
||||||
{
|
{
|
||||||
|
@ -1302,7 +1333,20 @@ PyDoc_STRVAR(float_setformat_doc,
|
||||||
"Overrides the automatic determination of C-level floating point type.\n"
|
"Overrides the automatic determination of C-level floating point type.\n"
|
||||||
"This affects how floats are converted to and from binary strings.");
|
"This affects how floats are converted to and from binary strings.");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
float_getzero(PyObject *v, void *closure)
|
||||||
|
{
|
||||||
|
return PyFloat_FromDouble(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef float_methods[] = {
|
static PyMethodDef float_methods[] = {
|
||||||
|
{"conjugate", (PyCFunction)float_float, METH_NOARGS,
|
||||||
|
"Returns self, the complex conjugate of any float."},
|
||||||
|
{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,
|
||||||
|
"Returns the Integral closest to x between 0 and x."},
|
||||||
|
{"__round__", (PyCFunction)float_round, METH_VARARGS,
|
||||||
|
"Returns the Integral closest to x, rounding half toward even.\n"
|
||||||
|
"When an argument is passed, works like built-in round(x, ndigits)."},
|
||||||
{"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},
|
||||||
{"__getformat__", (PyCFunction)float_getformat,
|
{"__getformat__", (PyCFunction)float_getformat,
|
||||||
METH_O|METH_CLASS, float_getformat_doc},
|
METH_O|METH_CLASS, float_getformat_doc},
|
||||||
|
@ -1311,6 +1355,18 @@ static PyMethodDef float_methods[] = {
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef float_getset[] = {
|
||||||
|
{"real",
|
||||||
|
(getter)float_float, (setter)NULL,
|
||||||
|
"the real part of a complex number",
|
||||||
|
NULL},
|
||||||
|
{"imag",
|
||||||
|
(getter)float_getzero, (setter)NULL,
|
||||||
|
"the imaginary part of a complex number",
|
||||||
|
NULL},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
PyDoc_STRVAR(float_doc,
|
PyDoc_STRVAR(float_doc,
|
||||||
"float(x) -> floating point number\n\
|
"float(x) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -1326,7 +1382,7 @@ static PyNumberMethods float_as_number = {
|
||||||
float_divmod, /*nb_divmod*/
|
float_divmod, /*nb_divmod*/
|
||||||
float_pow, /*nb_power*/
|
float_pow, /*nb_power*/
|
||||||
(unaryfunc)float_neg, /*nb_negative*/
|
(unaryfunc)float_neg, /*nb_negative*/
|
||||||
(unaryfunc)float_pos, /*nb_positive*/
|
(unaryfunc)float_float, /*nb_positive*/
|
||||||
(unaryfunc)float_abs, /*nb_absolute*/
|
(unaryfunc)float_abs, /*nb_absolute*/
|
||||||
(inquiry)float_nonzero, /*nb_nonzero*/
|
(inquiry)float_nonzero, /*nb_nonzero*/
|
||||||
0, /*nb_invert*/
|
0, /*nb_invert*/
|
||||||
|
@ -1336,8 +1392,8 @@ static PyNumberMethods float_as_number = {
|
||||||
0, /*nb_xor*/
|
0, /*nb_xor*/
|
||||||
0, /*nb_or*/
|
0, /*nb_or*/
|
||||||
float_coerce, /*nb_coerce*/
|
float_coerce, /*nb_coerce*/
|
||||||
float_int, /*nb_int*/
|
float_trunc, /*nb_int*/
|
||||||
float_long, /*nb_long*/
|
float_trunc, /*nb_long*/
|
||||||
float_float, /*nb_float*/
|
float_float, /*nb_float*/
|
||||||
0, /* nb_oct */
|
0, /* nb_oct */
|
||||||
0, /* nb_hex */
|
0, /* nb_hex */
|
||||||
|
@ -1389,7 +1445,7 @@ PyTypeObject PyFloat_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
float_methods, /* tp_methods */
|
float_methods, /* tp_methods */
|
||||||
0, /* tp_members */
|
0, /* tp_members */
|
||||||
0, /* tp_getset */
|
float_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static PyObject *int_int(PyIntObject *v);
|
||||||
|
|
||||||
long
|
long
|
||||||
PyInt_GetMax(void)
|
PyInt_GetMax(void)
|
||||||
{
|
{
|
||||||
|
@ -782,22 +784,11 @@ int_neg(PyIntObject *v)
|
||||||
return PyInt_FromLong(-a);
|
return PyInt_FromLong(-a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
int_pos(PyIntObject *v)
|
|
||||||
{
|
|
||||||
if (PyInt_CheckExact(v)) {
|
|
||||||
Py_INCREF(v);
|
|
||||||
return (PyObject *)v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyInt_FromLong(v->ob_ival);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
int_abs(PyIntObject *v)
|
int_abs(PyIntObject *v)
|
||||||
{
|
{
|
||||||
if (v->ob_ival >= 0)
|
if (v->ob_ival >= 0)
|
||||||
return int_pos(v);
|
return int_int(v);
|
||||||
else
|
else
|
||||||
return int_neg(v);
|
return int_neg(v);
|
||||||
}
|
}
|
||||||
|
@ -827,7 +818,7 @@ int_lshift(PyIntObject *v, PyIntObject *w)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (a == 0 || b == 0)
|
if (a == 0 || b == 0)
|
||||||
return int_pos(v);
|
return int_int(v);
|
||||||
if (b >= LONG_BIT) {
|
if (b >= LONG_BIT) {
|
||||||
vv = PyLong_FromLong(PyInt_AS_LONG(v));
|
vv = PyLong_FromLong(PyInt_AS_LONG(v));
|
||||||
if (vv == NULL)
|
if (vv == NULL)
|
||||||
|
@ -871,7 +862,7 @@ int_rshift(PyIntObject *v, PyIntObject *w)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (a == 0 || b == 0)
|
if (a == 0 || b == 0)
|
||||||
return int_pos(v);
|
return int_int(v);
|
||||||
if (b >= LONG_BIT) {
|
if (b >= LONG_BIT) {
|
||||||
if (a < 0)
|
if (a < 0)
|
||||||
a = -1;
|
a = -1;
|
||||||
|
@ -1060,11 +1051,72 @@ int_getnewargs(PyIntObject *v)
|
||||||
return Py_BuildValue("(l)", v->ob_ival);
|
return Py_BuildValue("(l)", v->ob_ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
int_getN(PyIntObject *v, void *context) {
|
||||||
|
return PyInt_FromLong((intptr_t)context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
int_round(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
|
||||||
|
int ndigits = UNDEF_NDIGITS;
|
||||||
|
double x;
|
||||||
|
PyObject *res;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|i", &ndigits))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ndigits == UNDEF_NDIGITS)
|
||||||
|
return int_float((PyIntObject *)self);
|
||||||
|
|
||||||
|
/* If called with two args, defer to float.__round__(). */
|
||||||
|
x = (double) PyInt_AS_LONG(self);
|
||||||
|
self = PyFloat_FromDouble(x);
|
||||||
|
if (self == NULL)
|
||||||
|
return NULL;
|
||||||
|
res = PyObject_CallMethod(self, "__round__", "i", ndigits);
|
||||||
|
Py_DECREF(self);
|
||||||
|
return res;
|
||||||
|
#undef UNDEF_NDIGITS
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef int_methods[] = {
|
static PyMethodDef int_methods[] = {
|
||||||
|
{"conjugate", (PyCFunction)int_int, METH_NOARGS,
|
||||||
|
"Returns self, the complex conjugate of any int."},
|
||||||
|
{"__trunc__", (PyCFunction)int_int, METH_NOARGS,
|
||||||
|
"Truncating an Integral returns itself."},
|
||||||
|
{"__floor__", (PyCFunction)int_int, METH_NOARGS,
|
||||||
|
"Flooring an Integral returns itself."},
|
||||||
|
{"__ceil__", (PyCFunction)int_int, METH_NOARGS,
|
||||||
|
"Ceiling of an Integral returns itself."},
|
||||||
|
{"__round__", (PyCFunction)int_round, METH_VARARGS,
|
||||||
|
"Rounding an Integral returns itself.\n"
|
||||||
|
"Rounding with an ndigits arguments defers to float.__round__."},
|
||||||
{"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef int_getset[] = {
|
||||||
|
{"real",
|
||||||
|
(getter)int_int, (setter)NULL,
|
||||||
|
"the real part of a complex number",
|
||||||
|
NULL},
|
||||||
|
{"imag",
|
||||||
|
(getter)int_getN, (setter)NULL,
|
||||||
|
"the imaginary part of a complex number",
|
||||||
|
(void*)0},
|
||||||
|
{"numerator",
|
||||||
|
(getter)int_int, (setter)NULL,
|
||||||
|
"the numerator of a rational number in lowest terms",
|
||||||
|
NULL},
|
||||||
|
{"denominator",
|
||||||
|
(getter)int_getN, (setter)NULL,
|
||||||
|
"the denominator of a rational number in lowest terms",
|
||||||
|
(void*)1},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
PyDoc_STRVAR(int_doc,
|
PyDoc_STRVAR(int_doc,
|
||||||
"int(x[, base]) -> integer\n\
|
"int(x[, base]) -> integer\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -1085,7 +1137,7 @@ static PyNumberMethods int_as_number = {
|
||||||
(binaryfunc)int_divmod, /*nb_divmod*/
|
(binaryfunc)int_divmod, /*nb_divmod*/
|
||||||
(ternaryfunc)int_pow, /*nb_power*/
|
(ternaryfunc)int_pow, /*nb_power*/
|
||||||
(unaryfunc)int_neg, /*nb_negative*/
|
(unaryfunc)int_neg, /*nb_negative*/
|
||||||
(unaryfunc)int_pos, /*nb_positive*/
|
(unaryfunc)int_int, /*nb_positive*/
|
||||||
(unaryfunc)int_abs, /*nb_absolute*/
|
(unaryfunc)int_abs, /*nb_absolute*/
|
||||||
(inquiry)int_nonzero, /*nb_nonzero*/
|
(inquiry)int_nonzero, /*nb_nonzero*/
|
||||||
(unaryfunc)int_invert, /*nb_invert*/
|
(unaryfunc)int_invert, /*nb_invert*/
|
||||||
|
@ -1149,7 +1201,7 @@ PyTypeObject PyInt_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
int_methods, /* tp_methods */
|
int_methods, /* tp_methods */
|
||||||
0, /* tp_members */
|
0, /* tp_members */
|
||||||
0, /* tp_getset */
|
int_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
|
|
|
@ -1716,7 +1716,7 @@ PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
|
||||||
/* forward */
|
/* forward */
|
||||||
static PyLongObject *x_divrem
|
static PyLongObject *x_divrem
|
||||||
(PyLongObject *, PyLongObject *, PyLongObject **);
|
(PyLongObject *, PyLongObject *, PyLongObject **);
|
||||||
static PyObject *long_pos(PyLongObject *);
|
static PyObject *long_long(PyObject *v);
|
||||||
static int long_divrem(PyLongObject *, PyLongObject *,
|
static int long_divrem(PyLongObject *, PyLongObject *,
|
||||||
PyLongObject **, PyLongObject **);
|
PyLongObject **, PyLongObject **);
|
||||||
|
|
||||||
|
@ -2905,17 +2905,6 @@ long_invert(PyLongObject *v)
|
||||||
return (PyObject *)x;
|
return (PyObject *)x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
long_pos(PyLongObject *v)
|
|
||||||
{
|
|
||||||
if (PyLong_CheckExact(v)) {
|
|
||||||
Py_INCREF(v);
|
|
||||||
return (PyObject *)v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return _PyLong_Copy(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_neg(PyLongObject *v)
|
long_neg(PyLongObject *v)
|
||||||
{
|
{
|
||||||
|
@ -2937,7 +2926,7 @@ long_abs(PyLongObject *v)
|
||||||
if (v->ob_size < 0)
|
if (v->ob_size < 0)
|
||||||
return long_neg(v);
|
return long_neg(v);
|
||||||
else
|
else
|
||||||
return long_pos(v);
|
return long_long((PyObject *)v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3373,11 +3362,74 @@ long_getnewargs(PyLongObject *v)
|
||||||
return Py_BuildValue("(N)", _PyLong_Copy(v));
|
return Py_BuildValue("(N)", _PyLong_Copy(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
long_getN(PyLongObject *v, void *context) {
|
||||||
|
return PyLong_FromLong((intptr_t)context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
long_round(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
|
||||||
|
int ndigits = UNDEF_NDIGITS;
|
||||||
|
double x;
|
||||||
|
PyObject *res;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|i", &ndigits))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ndigits == UNDEF_NDIGITS)
|
||||||
|
return long_float(self);
|
||||||
|
|
||||||
|
/* If called with two args, defer to float.__round__(). */
|
||||||
|
x = PyLong_AsDouble(self);
|
||||||
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
self = PyFloat_FromDouble(x);
|
||||||
|
if (self == NULL)
|
||||||
|
return NULL;
|
||||||
|
res = PyObject_CallMethod(self, "__round__", "i", ndigits);
|
||||||
|
Py_DECREF(self);
|
||||||
|
return res;
|
||||||
|
#undef UNDEF_NDIGITS
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef long_methods[] = {
|
static PyMethodDef long_methods[] = {
|
||||||
|
{"conjugate", (PyCFunction)long_long, METH_NOARGS,
|
||||||
|
"Returns self, the complex conjugate of any long."},
|
||||||
|
{"__trunc__", (PyCFunction)long_long, METH_NOARGS,
|
||||||
|
"Truncating an Integral returns itself."},
|
||||||
|
{"__floor__", (PyCFunction)long_long, METH_NOARGS,
|
||||||
|
"Flooring an Integral returns itself."},
|
||||||
|
{"__ceil__", (PyCFunction)long_long, METH_NOARGS,
|
||||||
|
"Ceiling of an Integral returns itself."},
|
||||||
|
{"__round__", (PyCFunction)long_round, METH_VARARGS,
|
||||||
|
"Rounding an Integral returns itself.\n"
|
||||||
|
"Rounding with an ndigits arguments defers to float.__round__."},
|
||||||
{"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef long_getset[] = {
|
||||||
|
{"real",
|
||||||
|
(getter)long_long, (setter)NULL,
|
||||||
|
"the real part of a complex number",
|
||||||
|
NULL},
|
||||||
|
{"imag",
|
||||||
|
(getter)long_getN, (setter)NULL,
|
||||||
|
"the imaginary part of a complex number",
|
||||||
|
(void*)0},
|
||||||
|
{"numerator",
|
||||||
|
(getter)long_long, (setter)NULL,
|
||||||
|
"the numerator of a rational number in lowest terms",
|
||||||
|
NULL},
|
||||||
|
{"denominator",
|
||||||
|
(getter)long_getN, (setter)NULL,
|
||||||
|
"the denominator of a rational number in lowest terms",
|
||||||
|
(void*)1},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
PyDoc_STRVAR(long_doc,
|
PyDoc_STRVAR(long_doc,
|
||||||
"long(x[, base]) -> integer\n\
|
"long(x[, base]) -> integer\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -3396,7 +3448,7 @@ static PyNumberMethods long_as_number = {
|
||||||
long_divmod, /*nb_divmod*/
|
long_divmod, /*nb_divmod*/
|
||||||
long_pow, /*nb_power*/
|
long_pow, /*nb_power*/
|
||||||
(unaryfunc) long_neg, /*nb_negative*/
|
(unaryfunc) long_neg, /*nb_negative*/
|
||||||
(unaryfunc) long_pos, /*tp_positive*/
|
(unaryfunc) long_long, /*tp_positive*/
|
||||||
(unaryfunc) long_abs, /*tp_absolute*/
|
(unaryfunc) long_abs, /*tp_absolute*/
|
||||||
(inquiry) long_nonzero, /*tp_nonzero*/
|
(inquiry) long_nonzero, /*tp_nonzero*/
|
||||||
(unaryfunc) long_invert, /*nb_invert*/
|
(unaryfunc) long_invert, /*nb_invert*/
|
||||||
|
@ -3461,7 +3513,7 @@ PyTypeObject PyLong_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
long_methods, /* tp_methods */
|
long_methods, /* tp_methods */
|
||||||
0, /* tp_members */
|
0, /* tp_members */
|
||||||
0, /* tp_getset */
|
long_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
|
|
|
@ -1926,39 +1926,31 @@ For most object types, eval(repr(object)) == object.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_round(PyObject *self, PyObject *args, PyObject *kwds)
|
builtin_round(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
double number;
|
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
|
||||||
double f;
|
int ndigits = UNDEF_NDIGITS;
|
||||||
int ndigits = 0;
|
|
||||||
int i;
|
|
||||||
static char *kwlist[] = {"number", "ndigits", 0};
|
static char *kwlist[] = {"number", "ndigits", 0};
|
||||||
|
PyObject *number;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round",
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:round",
|
||||||
kwlist, &number, &ndigits))
|
kwlist, &number, &ndigits))
|
||||||
return NULL;
|
return NULL;
|
||||||
f = 1.0;
|
|
||||||
i = abs(ndigits);
|
// The py3k branch gets better errors for this by using
|
||||||
while (--i >= 0)
|
// _PyType_Lookup(), but since float's mro isn't set in py2.6,
|
||||||
f = f*10.0;
|
// we just use PyObject_CallMethod here.
|
||||||
if (ndigits < 0)
|
if (ndigits == UNDEF_NDIGITS)
|
||||||
number /= f;
|
return PyObject_CallMethod(number, "__round__", "");
|
||||||
else
|
else
|
||||||
number *= f;
|
return PyObject_CallMethod(number, "__round__", "i", ndigits);
|
||||||
if (number >= 0.0)
|
#undef UNDEF_NDIGITS
|
||||||
number = floor(number + 0.5);
|
|
||||||
else
|
|
||||||
number = ceil(number - 0.5);
|
|
||||||
if (ndigits < 0)
|
|
||||||
number *= f;
|
|
||||||
else
|
|
||||||
number /= f;
|
|
||||||
return PyFloat_FromDouble(number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(round_doc,
|
PyDoc_STRVAR(round_doc,
|
||||||
"round(number[, ndigits]) -> floating point number\n\
|
"round(number[, ndigits]) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Round a number to a given precision in decimal digits (default 0 digits).\n\
|
Round a number to a given precision in decimal digits (default 0 digits).\n\
|
||||||
This always returns a floating point number. Precision may be negative.");
|
This returns an int when called with one argument, otherwise a float.\n\
|
||||||
|
Precision may be negative.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
|
builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
@ -2039,6 +2031,20 @@ PyDoc_STRVAR(vars_doc,
|
||||||
Without arguments, equivalent to locals().\n\
|
Without arguments, equivalent to locals().\n\
|
||||||
With an argument, equivalent to object.__dict__.");
|
With an argument, equivalent to object.__dict__.");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
builtin_trunc(PyObject *self, PyObject *number)
|
||||||
|
{
|
||||||
|
// XXX: The py3k branch gets better errors for this by using
|
||||||
|
// _PyType_Lookup(), but since float's mro isn't set in py2.6,
|
||||||
|
// we just use PyObject_CallMethod here.
|
||||||
|
return PyObject_CallMethod(number, "__trunc__", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(trunc_doc,
|
||||||
|
"trunc(Real) -> Integral\n\
|
||||||
|
\n\
|
||||||
|
returns the integral closest to x between 0 and x.");
|
||||||
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
builtin_sum(PyObject *self, PyObject *args)
|
builtin_sum(PyObject *self, PyObject *args)
|
||||||
|
@ -2387,6 +2393,7 @@ static PyMethodDef builtin_methods[] = {
|
||||||
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
|
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
|
||||||
#endif
|
#endif
|
||||||
{"vars", builtin_vars, METH_VARARGS, vars_doc},
|
{"vars", builtin_vars, METH_VARARGS, vars_doc},
|
||||||
|
{"trunc", builtin_trunc, METH_O, trunc_doc},
|
||||||
{"zip", builtin_zip, METH_VARARGS, zip_doc},
|
{"zip", builtin_zip, METH_VARARGS, zip_doc},
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue