Repository: numpy/numpy

Issue:
i0 changes the shape
`numpy.i0` squeezes the input, as in an example of the document:
```
>>> np.i0([0.])
array(1.0)
```

This is different from `scipy.special`:
```
>>> special.i0([0.])
array([1.])
```



Discussion:
Hmm, well, I somewhat think the easiest thing is probably to just deprecate the function completely asking to use the scipy implementation, it will much better anyway I am sure. Ours is not even a ufunc....
A quick code search showed usage mostly in some book or tutorial snipplet(s), so I think we should get away with direct deprecation? Not like it needs to be rushed, can go very slowly, deprecated -> visible deprecate, etc. And mostly add a note to the decumentation. It is python code, so should be a simple thing for someone wanting to do something small.
Probably needs a ping on the mailing list, just to be sure nobody feels strongly about fixing it instead of just deprecating.
@seberg - `i0` is also used inside `kaiser` - but I guess you mean to make `i0` private? It is not a difficult fix...
Ah I missed that it is used there, I guess for the kaiser the private version may be good enough, or we should just try to clean it up, it is also not that bad, just thought it might be cleaner anyway. I would have searched for the bessel functions in scipy.special to begin with...

Resolving patch:
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -3070,10 +3070,13 @@ def i0(x):
 
     See Also
     --------
-    scipy.special.iv, scipy.special.ive
+    scipy.special.i0, scipy.special.iv, scipy.special.ive
 
     Notes
     -----
+    The scipy implementation is recommended over this function: it is a
+    proper ufunc written in C, and more than an order of magnitude faster.
+
     We use the algorithm published by Clenshaw [1]_ and referenced by
     Abramowitz and Stegun [2]_, for which the function domain is
     partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
@@ -3093,21 +3096,14 @@ def i0(x):
 
     Examples
     --------
-    >>> np.i0([0.])
-    array(1.0) # may vary
+    >>> np.i0(0.)
+    array(1.0)  # may vary
     >>> np.i0([0., 1. + 2j])
-    array([ 1.00000000+0.j        ,  0.18785373+0.64616944j]) # may vary
+    array([ 1.00000000+0.j        ,  0.18785373+0.64616944j])  # may vary
 
     """
-    x = atleast_1d(x).copy()
-    y = empty_like(x)
-    ind = (x < 0)
-    x[ind] = -x[ind]
-    ind = (x <= 8.0)
-    y[ind] = _i0_1(x[ind])
-    ind2 = ~ind
-    y[ind2] = _i0_2(x[ind2])
-    return y.squeeze()
+    x = np.abs(x)
+    return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
 
 ## End of cephes code for i0
 


Test patch:
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -1984,9 +1984,9 @@ def test_simple(self):
             np.array(1.0634833707413234))
 
         A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549])
-        assert_almost_equal(
-            i0(A),
-            np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049]))
+        expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049])
+        assert_almost_equal(i0(A), expected)
+        assert_almost_equal(i0(-A), expected)
 
         B = np.array([[0.827002, 0.99959078],
                       [0.89694769, 0.39298162],
@@ -2000,6 +2000,10 @@ def test_simple(self):
                       [1.03633899, 1.00067775],
                       [1.03352052, 1.13557954],
                       [1.05884290, 1.06432317]]))
+        # Regression test for gh-11205
+        i0_0 = np.i0([0.])
+        assert_equal(i0_0.shape, (1,))
+        assert_array_equal(np.i0([0.]), np.array([1.]))
 
 
 class TestKaiser(object):