Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imaginary type and IEC 60559-compatible complex arithmetic #1

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Doc/c-api/complex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ pointers. This is consistent throughout the API.
.. versionadded:: 3.14


.. c:function:: Py_complex _Py_ci_sum(Py_complex left, double right)

Return the sum of a complex number and an imaginary number, using the C
:c:type:`Py_complex` representation.

.. versionadded:: next


.. c:function:: Py_complex _Py_c_diff(Py_complex left, Py_complex right)

Return the difference between two complex numbers, using the C
Expand All @@ -74,6 +82,22 @@ pointers. This is consistent throughout the API.
.. versionadded:: 3.14


.. c:function:: Py_complex _Py_ci_diff(Py_complex left, double right)

Return the difference between a complex number and an imaginary number,
using the C :c:type:`Py_complex` representation.

.. versionadded:: next


.. c:function:: Py_complex _Py_ic_diff(double left, Py_complex right)

Return the difference between an imaginary number and a complex number,
using the C :c:type:`Py_complex` representation.

.. versionadded:: next


.. c:function:: Py_complex _Py_c_neg(Py_complex num)

Return the negation of the complex number *num*, using the C
Expand All @@ -94,6 +118,14 @@ pointers. This is consistent throughout the API.
.. versionadded:: 3.14


.. c:function:: Py_complex _Py_ci_prod(Py_complex left, double right)

Return the product of a complex number and an imaginary number, using the C
:c:type:`Py_complex` representation.

.. versionadded:: next


.. c:function:: Py_complex _Py_c_quot(Py_complex dividend, Py_complex divisor)

Return the quotient of two complex numbers, using the C :c:type:`Py_complex`
Expand Down Expand Up @@ -125,6 +157,28 @@ pointers. This is consistent throughout the API.
.. versionadded:: 3.14


.. c:function:: Py_complex _Py_ci_quot(Py_complex dividend, double divisor)

Return the quotient of a complex number and an imaginary number, using the C
:c:type:`Py_complex` representation.

If *divisor* is zero, this method returns zero and sets
:c:data:`errno` to :c:macro:`!EDOM`.

.. versionadded:: next


.. c:function:: Py_complex _Py_ic_quot(double dividend, Py_complex divisor)

Return the quotient of an imaginary number and a complex number, using the C
:c:type:`Py_complex` representation.

If *divisor* is zero, this method returns zero and sets
:c:data:`errno` to :c:macro:`!EDOM`.

.. versionadded:: next


.. c:function:: Py_complex _Py_c_pow(Py_complex num, Py_complex exp)

Return the exponentiation of *num* by *exp*, using the C :c:type:`Py_complex`
Expand Down
2 changes: 2 additions & 0 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Doc/library/cmath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ Constants
.. data:: infj

Complex number with zero real part and positive infinity imaginary
part. Equivalent to ``complex(0.0, float('inf'))``.
part. Equivalent to ``float('inf')*1j``.

.. versionadded:: 3.6

Expand All @@ -295,7 +295,7 @@ Constants
.. data:: nanj

Complex number with zero real part and NaN imaginary part. Equivalent to
``complex(0.0, float('nan'))``.
``float('nan')*1j``.

.. versionadded:: 3.6

Expand Down
23 changes: 16 additions & 7 deletions Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ are always available. They are listed here in alphabetical order.
| | :func:`complex` | | | | **P** | | **V** |
| | | | **I** | | :func:`pow` | | :func:`vars` |
| | **D** | | :func:`id` | | :func:`print` | | |
| | :func:`delattr` | | :func:`input` | | :func:`property` | | **Z** |
| | |func-dict|_ | | :func:`int` | | | | :func:`zip` |
| | :func:`dir` | | :func:`isinstance` | | | | |
| | :func:`divmod` | | :func:`issubclass` | | | | **_** |
| | :func:`delattr` | | :func:`imaginary` | | :func:`property` | | |
| | |func-dict|_ | | :func:`input` | | | | **Z** |
| | :func:`dir` | | :func:`int` | | | | :func:`zip` |
| | :func:`divmod` | | :func:`isinstance` | | | | |
| | | | :func:`issubclass` | | | | **_** |
| | | | :func:`iter` | | | | :func:`__import__` |
+-------------------------+-----------------------+-----------------------+-------------------------+

Expand Down Expand Up @@ -388,7 +389,7 @@ are always available. They are listed here in alphabetical order.
>>> complex('+1.23')
(1.23+0j)
>>> complex('-4.5j')
-4.5j
(0.0-4.5j)
>>> complex('-1.23+4.5j')
(-1.23+4.5j)
>>> complex('\t( -1.23+4.5J )\n')
Expand All @@ -398,7 +399,7 @@ are always available. They are listed here in alphabetical order.
>>> complex(1.23)
(1.23+0j)
>>> complex(imag=-4.5)
-4.5j
(0.0-4.5j)
>>> complex(-1.23, 4.5)
(-1.23+4.5j)

Expand Down Expand Up @@ -442,7 +443,7 @@ are always available. They are listed here in alphabetical order.

See also :meth:`complex.from_number` which only accepts a single numeric argument.

If all arguments are omitted, returns ``0j``.
If all arguments are omitted, returns ``0.0+0j``.

The complex type is described in :ref:`typesnumeric`.

Expand Down Expand Up @@ -970,6 +971,14 @@ are always available. They are listed here in alphabetical order.
.. audit-event:: builtins.id id id


.. class:: imaginary(x=0.0)

Return an imaginary number with the value ``float(x)*1j``. If argument is
omitted, returns ``0j``.

.. versionadded:: next


.. function:: input()
input(prompt)

Expand Down
11 changes: 6 additions & 5 deletions Doc/reference/lexical_analysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -979,11 +979,12 @@ Imaginary literals are described by the following lexical definitions:
.. productionlist:: python-grammar
imagnumber: (`floatnumber` | `digitpart`) ("j" | "J")

An imaginary literal yields a complex number with a real part of 0.0. Complex
numbers are represented as a pair of floating-point numbers and have the same
restrictions on their range. To create a complex number with a nonzero real
part, add a floating-point number to it, e.g., ``(3+4j)``. Some examples of
imaginary literals::
An imaginary literal yields a complex number without a real part, an instance
of :class:`imaginary`. Complex numbers are represented as a pair of
floating-point numbers and have the same restrictions on their range. To
create a complex number with a nonzero real part, add an integer or
floating-point number to imaginary, e.g., ``3+4j``. Some examples of imaginary
literals::

3.14j 10.j 10j .001j 1e100j 3.14e-10j 3.14_15_93j

Expand Down
6 changes: 6 additions & 0 deletions Include/complexobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ extern "C" {
/* Complex object interface */

PyAPI_DATA(PyTypeObject) PyComplex_Type;
PyAPI_DATA(PyTypeObject) PyImaginary_Type;

#define PyComplex_Check(op) PyObject_TypeCheck((op), &PyComplex_Type)
#define PyComplex_CheckExact(op) Py_IS_TYPE((op), &PyComplex_Type)

#define PyImaginary_Check(op) PyObject_TypeCheck((op), &PyImaginary_Type)
#define PyImaginary_CheckExact(op) Py_IS_TYPE((op), &PyImaginary_Type)

PyAPI_FUNC(PyObject *) PyComplex_FromDoubles(double real, double imag);

PyAPI_FUNC(double) PyComplex_RealAsDouble(PyObject *op);
PyAPI_FUNC(double) PyComplex_ImagAsDouble(PyObject *op);

PyAPI_FUNC(PyObject *) PyImaginary_FromDouble(double imag);

#ifndef Py_LIMITED_API
# define Py_CPYTHON_COMPLEXOBJECT_H
# include "cpython/complexobject.h"
Expand Down
6 changes: 6 additions & 0 deletions Include/cpython/complexobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ typedef struct {
// Operations on complex numbers.
PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex);
PyAPI_FUNC(Py_complex) _Py_cr_sum(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_ci_sum(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex);
PyAPI_FUNC(Py_complex) _Py_cr_diff(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_rc_diff(double, Py_complex);
PyAPI_FUNC(Py_complex) _Py_ci_diff(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_ic_diff(double, Py_complex);
PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex);
PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex);
PyAPI_FUNC(Py_complex) _Py_cr_prod(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_ci_prod(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex);
PyAPI_FUNC(Py_complex) _Py_cr_quot(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_rc_quot(double, Py_complex);
PyAPI_FUNC(Py_complex) _Py_ci_quot(Py_complex, double);
PyAPI_FUNC(Py_complex) _Py_ic_quot(double, Py_complex);
PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex);
PyAPI_FUNC(double) _Py_c_abs(Py_complex);

Expand Down
2 changes: 1 addition & 1 deletion Lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def _raise_malformed_node(node):
msg += f' on line {lno}'
raise ValueError(msg + f': {node!r}')
def _convert_num(node):
if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
if not isinstance(node, Constant) or type(node.value) not in (int, float, imaginary, complex):
_raise_malformed_node(node)
return node.value
def _convert_signed_num(node):
Expand Down
5 changes: 3 additions & 2 deletions Lib/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def copy(x):
return _reconstruct(x, None, *rv)


_copy_atomic_types = {types.NoneType, int, float, bool, complex, str, tuple,
_copy_atomic_types = {types.NoneType, int, float, bool, complex, imaginary, str, tuple,
bytes, frozenset, type, range, slice, property,
types.BuiltinFunctionType, types.EllipsisType,
types.NotImplementedType, types.FunctionType, types.CodeType,
Expand Down Expand Up @@ -164,7 +164,8 @@ def deepcopy(x, memo=None, _nil=[]):

_atomic_types = {types.NoneType, types.EllipsisType, types.NotImplementedType,
int, float, bool, complex, bytes, str, types.CodeType, type, range,
types.BuiltinFunctionType, types.FunctionType, weakref.ref, property}
types.BuiltinFunctionType, types.FunctionType, weakref.ref,
property, imaginary}

_deepcopy_dispatch = d = {}

Expand Down
Loading
Loading