Commit 7a3955c3 authored by Jeffrey Yasskin's avatar Jeffrey Yasskin

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.
parent bbb0ef90
...@@ -986,10 +986,13 @@ available. They are listed here in alphabetical order. ...@@ -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. ...@@ -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: ...@@ -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: ...@@ -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)
......
: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 ...@@ -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`, ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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:
......
# 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)
"""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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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[] = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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 = { ...@@ -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."); ...@@ -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, ...@@ -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[] = { ...@@ -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},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment