Repository: numpy/numpy
Pull request: DOC: Fix description of dtype default in linspace
Clarify linspace docstring to say the default dtype will never be smaller than float.

Fixes gh-8597



Problem statement:
linspace dtype documentation misleading or a bug
The linspace documentation for the dtype argument says:

    dtype : dtype, optional
        The type of the output array.  If `dtype` is not given, infer the data
        type from the other input arguments.

However in the code linspace:

    start = asanyarray(start) * 1.0
    stop  = asanyarray(stop)  * 1.0
    dt = result_type(start, stop, float(num))
    if dtype is None:
        dtype = dt

Which means the dtype is only inferred from the other arguments if they are a floating-point type (and then not always if they are too small). It will never infer an integral or other type and the float(num) causes it to be at least float64 on more systems.

I think the correct solution here is to just state the it defaults to a floating-point type in the documentation. The reason that is probably important instead of actually inferring the dtype is that if someone has:

    np.linspace(0, 1, 100)

the inferred type would be int which is clearly not what was expected here. The only other reasonable solution would be calculate `step` first and determine if it is an integral step along with the start and stop being integral as well. Something along the following lines (which isn't complete, just an example):

    start = asanyarray(start)
    stop  = asanyarray(stop)
    if dtype is None and start.dtype.kind in 'iu' and stop.dtype.kind in 'iu' and (start - stop) % num == 0:
        dtype = result_type(start, stop, num)
    else:
        start = start * 1.0
        stop  = stop * 1.0
        dt = result_type(start, stop, float(num))
        if dtype is None:
            dtype = dt

Hints from issue discussion:
Don't think its wrong, but we can add "a floating point type inferred" or so.

Commit message: DOC: Redrafted fix for description of dtype default in linspace

Replaces 'smaller than' with more explicit wording.

Patch to review:
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py
index 9e46f0ea5b4c..d10d6cc86fb0 100644
--- a/numpy/core/function_base.py
+++ b/numpy/core/function_base.py
@@ -52,8 +52,10 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
         If True, return (`samples`, `step`), where `step` is the spacing
         between samples.
     dtype : dtype, optional
-        The type of the output array.  If `dtype` is not given, infer the data
-        type from the other input arguments.
+        The type of the output array.  If `dtype` is not given, the data type
+        is inferred from `start`, `stop`, and `num`. The inferred dtype will
+        never be an integer; `float` is chosen even if all three arguments are
+        integers.
 
         .. versionadded:: 1.9.0
 


Code review comments:
diff_hunk: @@ -52,8 +52,10 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
         If True, return (`samples`, `step`), where `step` is the spacing
         between samples.
     dtype : dtype, optional
-        The type of the output array.  If `dtype` is not given, infer the data
-        type from the other input arguments.
+        The type of the output array.  If `dtype` is not given, the data type
+        is inferred from `start`, `stop`, and `num`. The inferred dtype will
path: numpy/core/function_base.py
text: @user1:
I would leave `num` off the list - it must be an integer, but for the purposes of determining the dtype it is cast to float internally. 

@author:
Agreed, `num` is dont-care.