Skip to content
Merged
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
10 changes: 10 additions & 0 deletions doc/release/1.10.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Highlights
sequence of arrays along a new axis, complementing `np.concatenate` for
joining along an existing axis.
* Addition of `nanprod` to the set of nanfunctions.
* Support for the '@' operator in Python 3.5.


Dropped Support
Expand Down Expand Up @@ -153,6 +154,15 @@ vectors. An array of ``fweights`` indicates the number of repeats of each
observation vector, and an array of ``aweights`` provides their relative
importance or probability.

Support for the '@' operator in Python 3.5+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Python 3.5 adds support for a matrix multiplication operator '@' proposed
in PEP465. Preliminary support for that has been implemented, and an
equivalent function ``matmul`` has also been added for testing purposes and
use in earlier Python versions. The function is preliminary and the order
and number of its optional arguments can be expected to change.


Improvements
============

Expand Down
20 changes: 17 additions & 3 deletions doc/source/reference/arrays.ndarray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ be performed.
ndarray.all
ndarray.any

Arithmetic and comparison operations
====================================
Arithmetic, matrix multiplication, and comparison operations
============================================================

.. index:: comparison, arithmetic, operation, operator
.. index:: comparison, arithmetic, matrix, operation, operator

Arithmetic and comparison operations on :class:`ndarrays <ndarray>`
are defined as element-wise operations, and generally yield
Expand Down Expand Up @@ -551,6 +551,20 @@ Arithmetic, in-place:
casts the result to fit back in ``a``, whereas ``a = a + 3j``
re-binds the name ``a`` to the result.

Matrix Multiplication:

.. autosummary::
:toctree: generated/

ndarray.__matmul__

.. note::

Matrix operators ``@`` and ``@=`` were introduced in Python 3.5
following PEP465. Numpy 1.10 has a preliminary implementation of ``@``
for testing purposes. Further documentation can be found in the
:func:`matmul` documentation.


Special methods
===============
Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/routines.linalg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Matrix and vector products
vdot
inner
outer
matmul
tensordot
einsum
linalg.matrix_power
Expand Down
127 changes: 126 additions & 1 deletion numpy/add_newdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1943,6 +1943,7 @@ def luf(lamdaexpr, *args, **kwargs):
vdot : Complex-conjugating dot product.
tensordot : Sum products over arbitrary axes.
einsum : Einstein summation convention.
matmul : '@' operator as method with out parameter.

Examples
--------
Expand All @@ -1954,7 +1955,7 @@ def luf(lamdaexpr, *args, **kwargs):
>>> np.dot([2j, 3j], [2j, 3j])
(-13+0j)

For 2-D arrays it's the matrix product:
For 2-D arrays it is the matrix product:

>>> a = [[1, 0], [0, 1]]
>>> b = [[4, 1], [2, 2]]
Expand All @@ -1971,6 +1972,130 @@ def luf(lamdaexpr, *args, **kwargs):

""")

add_newdoc('numpy.core', 'matmul',
"""
matmul(a, b, out=None)

Matrix product of two arrays.

The behavior depends on the arguments in the following way.

- If both arguments are 2-D they are multiplied like conventional
matrices.
- If either argument is N-D, N > 2, it is treated as a stack of
matrices residing in the last two indexes and broadcast accordingly.
- If the first argument is 1-D, it is promoted to a matrix by
prepending a 1 to its dimensions. After matrix multiplication
the prepended 1 is removed.
- If the second argument is 1-D, it is promoted to a matrix by
appending a 1 to its dimensions. After matrix multiplication
the appended 1 is removed.

Multiplication by a scalar is not allowed, use ``*`` instead. Note that
multiplying a stack of matrices with a vector will result in a stack of
vectors, but matmul will not recognize it as such.

``matmul`` differs from ``dot`` in two important ways.

- Multiplication by scalars is not allowed.
- Stacks of matrices are broadcast together as if the matrices
were elements.

.. warning::
This function is preliminary and included in Numpy 1.10 for testing
and documentation. Its semantics will not change, but the number and
order of the optional arguments will.

.. versionadded:: 1.10.0

Parameters
----------
a : array_like
First argument.
b : array_like
Second argument.
out : ndarray, optional
Output argument. This must have the exact kind that would be returned
if it was not used. In particular, it must have the right type, must be
C-contiguous, and its dtype must be the dtype that would be returned
for `dot(a,b)`. This is a performance feature. Therefore, if these
conditions are not met, an exception is raised, instead of attempting
to be flexible.

Returns
-------
output : ndarray
Returns the dot product of `a` and `b`. If `a` and `b` are both
1-D arrays then a scalar is returned; otherwise an array is
returned. If `out` is given, then it is returned.

Raises
------
ValueError
If the last dimension of `a` is not the same size as
the second-to-last dimension of `b`.

If scalar value is passed.

See Also
--------
vdot : Complex-conjugating dot product.
tensordot : Sum products over arbitrary axes.
einsum : Einstein summation convention.
dot : alternative matrix product with different broadcasting rules.

Notes
-----
The matmul function implements the semantics of the `@` operator introduced
in Python 3.5 following PEP465.

Examples
--------
For 2-D arrays it is the matrix product:

>>> a = [[1, 0], [0, 1]]
>>> b = [[4, 1], [2, 2]]
>>> np.matmul(a, b)
array([[4, 1],
[2, 2]])

For 2-D mixed with 1-D, the result is the usual.

>>> a = [[1, 0], [0, 1]]
>>> b = [1, 2]
>>> np.matmul(a, b)
array([1, 2])
>>> np.matmul(b, a)
array([1, 2])


Broadcasting is conventional for stacks of arrays

>>> a = np.arange(2*2*4).reshape((2,2,4))
>>> b = np.arange(2*2*4).reshape((2,4,2))
>>> np.matmul(a,b).shape
(2, 2, 2)
>>> np.matmul(a,b)[0,1,1]
98
>>> sum(a[0,1,:] * b[0,:,1])
98

Vector, vector returns the scalar inner product, but neither argument
is complex-conjugated:

>>> np.matmul([2j, 3j], [2j, 3j])
(-13+0j)

Scalar multiplication raises an error.

>>> np.matmul([1,2], 3)
Traceback (most recent call last):
...
ValueError: Scalar operands are not allowed, use '*' instead

""")


add_newdoc('numpy.core', 'einsum',
"""
einsum(subscripts, *operands, out=None, dtype=None, order='K', casting='safe')
Expand Down
13 changes: 7 additions & 6 deletions numpy/core/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
'Inf', 'inf', 'infty', 'Infinity',
'nan', 'NaN', 'False_', 'True_', 'bitwise_not',
'CLIP', 'RAISE', 'WRAP', 'MAXDIMS', 'BUFSIZE', 'ALLOW_THREADS',
'ComplexWarning', 'may_share_memory', 'full', 'full_like']
'ComplexWarning', 'may_share_memory', 'full', 'full_like',
'matmul']

if sys.version_info[0] < 3:
__all__.extend(['getbuffer', 'newbuffer'])
Expand Down Expand Up @@ -390,6 +391,11 @@ def extend_all(module):
compare_chararrays = multiarray.compare_chararrays
putmask = multiarray.putmask
einsum = multiarray.einsum
dot = multiarray.dot
inner = multiarray.inner
vdot = multiarray.vdot
matmul = multiarray.matmul


def asarray(a, dtype=None, order=None):
"""
Expand Down Expand Up @@ -1081,11 +1087,6 @@ def outer(a, b, out=None):
b = asarray(b)
return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis,:], out)

# try to import blas optimized dot if available
envbak = os.environ.copy()
dot = multiarray.dot
inner = multiarray.inner
vdot = multiarray.vdot

def alterdot():
"""
Expand Down
Loading