Repository: numpy/numpy
Pull request: Update Docs : point users of np.outer to np.multiply.outer
Update docs for indicating:
- ``np.outer`` only exists at this point for compatibility with old code.
- ``np.tensordot(a, b, axes=((), ()))`` and ``np.multiply.outer(a, b)`` behave same for all dimensions of a and b.

Closes [#12980](https://github.com/numpy/numpy/issues/12980)

Problem statement:
DOC: point users of np.outer to np.multiply.outer
<!-- Please describe the issue in detail here, and fill in the fields below -->

(Was: np.outer with scalar)

(feature request)

When one of the operators to np.pout is a scalar, it would be great if the result could behave like a regular multiplication.

### Reproducing code example:

<!-- A short code example that reproduces the problem/missing feature. It should be
self-contained, i.e., possible to run as-is via 'python myproblem.py' -->

```python
import numpy as np

np.outer(1,[2,3,4])
# result: array([[2, 3, 4]])
# desired: array([2, 3, 4])

np.outer([2,3,4],1)
# result: array([[2], [3], [4]])
# desired: array([2, 3, 4])
```

The above results would be OK for 1D arrays, as in
```python
np.outer([1],[2,3,4])
np.outer([2,3,4],[1])
```
but scalars should behave differently.

Hints from issue discussion:
I'd recommend just using `np.multiply.outer`, which works as you request:
```python
>>> np.multiply.outer(1,[2,3,4])
array([2, 3, 4])
```

`np.outer` only exists at this point for compatibility with old code.
Thanks!  

Could you please add note to the documentation, for others to find?  

[Closing is OK otherwise.]
There's already a note in the see also section of [the docs](https://docs.scipy.org/doc/numpy/reference/generated/numpy.outer.html) that mentions `np.multiply.outer`:

![image](https://user-images.githubusercontent.com/425260/52909517-85766200-323e-11e9-8f0f-85163d93cab2.png)


If you don't think this is obvious enough, then feel free to submit a PR with improved docs. If you hadn't already found it, the docs have a [source] link that usually takes you to where the docstring comes from.

One improvement might just be to change "N dimensions" to "dimensions other than 1D". Another might be to stick a `.. note::` box higher up the docs suggesting that `np.multiply.outer` be used instead.
My apologies, I overlooked that.

In fact, numpy.tensordot(..., axes=0) does the same.  It should be 
mentioned.  In contrast to what the documentation of tensordot seems to 
suggest, it also accepts scalars.

On 17/2/19 6:01 pm, Eric Wieser wrote:
> There's already a note in the see also section of the docs 
> <https://docs.scipy.org/doc/numpy/reference/generated/numpy.outer.html> 
> that mentions |np.multiply.outer|:
> 
> image 
> <https://user-images.githubusercontent.com/425260/52909517-85766200-323e-11e9-8f0f-85163d93cab2.png>
> 
> If you don't think this is obvious enough, then feel free to submit a PR 
> with improved docs. If you hadn't already found it, the docs have a 
> [source] link that usually takes you to where the docstring comes from.
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub 
> <https://github.com/numpy/numpy/issues/12980#issuecomment-464423576>, or 
> mute the thread 
> <https://github.com/notifications/unsubscribe-auth/ABNtFpRg2xXm8Yeo-IMC-zbir-HN36rwks5vOP5VgaJpZM4a_YaZ>.
> 

`tensordot` behaves differently on 2d arrays.
yes, but that can be easily overwritten by the `axes` parameter to make 
it behave the same.  I am also impressed with the `einsum` function.

On 19/2/19 5:24 pm, Eric Wieser wrote:
> |tensordot| behaves differently on 2d arrays.
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub 
> <https://github.com/numpy/numpy/issues/12980#issuecomment-465001215>, or 
> mute the thread 
> <https://github.com/notifications/unsubscribe-auth/ABNtFsEzdA10raIbcFJDEdfFfZdO5nfKks5vO5iggaJpZM4a_YaZ>.
> 

Looking a little closer: the following are the same for all dimensions of `a` and `b`:

* `np.tensordot(a, b, axes=((), ()))`
* `np.multiply.outer(a, b)`
@eric-wieser : could you mention what changes needs to be made? I mean do we mention in np.multiply.order that we could use either
    np.tensordot(a, b, axes=((), ()))
    np.multiply.outer(a, b)
and also mention that np.outer is used for compatibility with oldcode so one can use np.multiply.outer?

Hi, has this issue been resolved? I am new to open-source and this project, so thought of taking this up. Let me know if that is ok.
Hi @gimseng. Anyone is welcome to submit a PR to any open issue. Please read the [developer guidelines](https://numpy.org/devdocs/dev/index.html) and the [guide to the documentation](https://numpy.org/devdocs/docs/index.html). When you do submit a PR, link back to this issue by putting `xref gh-12980` in your PR request (or use `fixes` or `closes` to automatically close it when merged) so others will know you are working on this.

Commit message: Add tenserdot to numpy.outer documentation

Patch to review:
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index e54103634e85..bfbe73695fb8 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -5043,7 +5043,9 @@
 
     See Also
     --------
-    numpy.outer
+    numpy.outer : ``np.outer`` only exists at this point for compatibility with old code.
+
+    tensordot : ``np.tensordot(a, b, axes=((), ()))`` and ``np.multiply.outer(a, b)`` behave same for all dimensions of a and b.
 
     Examples
     --------
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index 83d985a7cefa..7ed741a0b2cf 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -857,8 +857,9 @@ def outer(a, b, out=None):
     --------
     inner
     einsum : ``einsum('i,j->ij', a.ravel(), b.ravel())`` is the equivalent.
-    ufunc.outer : A generalization to N dimensions and other operations.
+    ufunc.outer : A generalization to dimensions other than 1D and other operations.
                   ``np.multiply.outer(a.ravel(), b.ravel())`` is the equivalent.
+    tensordot : ``np.tensordot(a, b, axes=((), ()))`` and ``np.multiply.outer(a, b)`` behave same for all dimensions of a and b.
 
     References
     ----------


Code review comments:
diff_hunk: @@ -5043,7 +5043,9 @@
 
     See Also
     --------
-    numpy.outer
+    numpy.outer : ``np.outer`` only exists at this point for compatibility with old code.
path: numpy/core/_add_newdocs.py
text: @user1:
```suggestion
    numpy.outer : A less powerful version of ``np.multiply.outer`` that `ravel`\ s all inputs to 1D. This exists primarily for compatibility with old code.
```

diff_hunk: @@ -857,8 +857,9 @@ def outer(a, b, out=None):
     --------
     inner
     einsum : ``einsum('i,j->ij', a.ravel(), b.ravel())`` is the equivalent.
-    ufunc.outer : A generalization to N dimensions and other operations.
+    ufunc.outer : A generalization to dimensions other than 1D and other operations.
                   ``np.multiply.outer(a.ravel(), b.ravel())`` is the equivalent.
+    tensordot : ``np.tensordot(a, b, axes=((), ()))`` and ``np.multiply.outer(a, b)`` behave same for all dimensions of a and b.
path: numpy/core/numeric.py
text: @user1:
```suggestion
    tensordot : ``np.tensordot(a.ravel(), b.ravel(), axes=((), ()))`` is the equivalent.
```