Repository: numpy/numpy

Issue:
Numpy 1.16 linspace fails for very large start stop values
### Reproducing code example:
The following corner case works correctly with numpy 1.15.4 but raises an error with numpy 1.16.2 
```python
import numpy as np
np.linspace(start = -9223372036854775809, stop = -9223372036854775809, num =1)
```

This was detected in a test with auto generated input using hypothesis to generate the input.

### Error message:

```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-aa8cbb862cf0> in <module>
----> 1 np.linspace(start = -9223372036854775809, stop = -9223372036854775809, num =1)

~\AppData\Local\Continuum\miniconda3\envs\qcodes\lib\site-packages\numpy\core\function_base.py in linspace(start, stop, num, endpoint, retstep, dtype, axis)
    141 
    142     delta = stop - start
--> 143     y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * delta.ndim)
    144     # In-place multiplication y *= delta/div is faster, but prevents the multiplicant
    145     # from overriding what class is produced, and thus prevents, e.g. use of Quantities,

AttributeError: 'float' object has no attribute 'ndim'

```
### Numpy/Python version information:

1.16.2 3.6.8 |Anaconda, Inc.| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]

### Details
This seems to happen when the number used is sufficiently large end up being represented
as an object dtype.  This in turn means that delta will be a regular floating point number and not a numpy float. Therefore it does not have a `ndim` method. The 1.15 code looks different and does not require the `ndim` method to be defined. 

```python
type(np.asanyarray(-9223372036854775809))
dtype('O')
type(np.asanyarray(-9223372036854775809) * 1.0 - np.asanyarray(-9223372036854775809) *1.0)
float
```


Discussion:
Oops, that's an unexpected one. But fortunately easy to solve...

Resolving patch:
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py
--- a/numpy/core/function_base.py
+++ b/numpy/core/function_base.py
@@ -6,7 +6,7 @@
 
 from . import numeric as _nx
 from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS,
-                      TooHardError, asanyarray)
+                      TooHardError, asanyarray, ndim)
 from numpy.core.multiarray import add_docstring
 from numpy.core import overrides
 
@@ -140,7 +140,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
         dtype = dt
 
     delta = stop - start
-    y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * delta.ndim)
+    y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta))
     # In-place multiplication y *= delta/div is faster, but prevents the multiplicant
     # from overriding what class is produced, and thus prevents, e.g. use of Quantities,
     # see gh-7142. Hence, we multiply in place only for standard scalar types.


Test patch:
diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py
--- a/numpy/core/tests/test_function_base.py
+++ b/numpy/core/tests/test_function_base.py
@@ -362,3 +362,9 @@ def test_retstep(self):
                 assert_(isinstance(y, tuple) and len(y) == 2 and
                         len(y[0]) == num and isnan(y[1]),
                         'num={0}, endpoint={1}'.format(num, ept))
+
+    def test_object(self):
+        start = array(1, dtype='O')
+        stop = array(2, dtype='O')
+        y = linspace(start, stop, 3)
+        assert_array_equal(y, array([1., 1.5, 2.]))