8000 Merge pull request #5446 from jaimefrio/linspace_denormals_again · numpy/numpy@1444550 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1444550

committed
Merge pull request #5446 from jaimefrio/linspace_denormals_again
BUG: linspace should return the same as arange when possible
2 parents 25ee91b + 2aab654 commit 1444550

File tree

2 files changed

+36
-26
lines changed

2 files changed

+36
-26
lines changed

numpy/core/function_base.py

-25Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
__all__ = ['logspace', 'linspace']
44

55
from . import numeric as _nx
6-
from .numeric import array, result_type
6+
from .numeric import array, result_type, NaN
77

88

99
def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
@@ -82,6 +82,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
8282
8383
"""
8484
num = int(num)
85+
div = (num - 1) if endpoint else num
8586

8687
# Convert float/complex array scalars to float, gh-3504
8788
start = start * 1.
@@ -91,38 +92,31 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
9192
if dtype is None:
9293
dtype = dt
9394

94-
if num <= 0:
95-
return array([], dtype)
96-
if num == 1:
97-
return array([start], dtype=dtype)
9895
y = _nx.arange(0, num, dtype=dt)
99-
if endpoint:
100-
num -= 1
101-
y /= num
102-
y *= stop - start
96+
97+
if num > 1:
98+
delta = stop - start
99+
step = delta / div
100+
if step == 0:
101+
# Special handling for denormal numbers, gh-5437
102+
y /= div
103+
y *= delta
104+
else:
105+
y *= step
106+
else:
107+
# 0 and 1 item long sequences have an undefined step
108+
step = NaN
109+
103110
y += start
104-
if endpoint:
111+
112+
if endpoint and num > 1:
105113
y[-1] = stop
106114

107115
if retstep:
108-
return y.astype(dtype, copy=False), (stop - start) / num
116+
return y.astype(dtype, copy=False), step
109117
else:
110118
return y.astype(dtype, copy=False)
111119

112-
# if endpoint:
113-
# if num == 1:
114-
# return array([start], dtype=dtype)
115-
# step = (stop-start)/float((num-1))
116-
# y = _nx.arange(0, num, dtype=dtype) * step + start
117-
# y[-1] = stop
118-
# else:
119-
# step = (stop-start)/float(num)
120-
# y = _nx.arange(0, num, dtype=dtype) * step + start
121-
# if retstep:
122-
# return y.astype(dtype), step
123-
# else:
124-
# return y.astype(dtype)
125-
126120

127121
def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None):
128122
"""

numpy/core/tests/test_function_base.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from __future__ import division, absolute_import, print_function
22

33
from numpy.testing import *
4-
from numpy import logspace, linspace, dtype, array, finfo, typecodes
4+
from numpy import (logspace, linspace, dtype, array, finfo, typecodes, arange,
5+
isnan)
56

67
class TestLogspace(TestCase):
78

@@ -117,6 +118,21 @@ def test_denormal_numbers(self):
117118
stop = finfo(dt).tiny * finfo(dt).resolution
118119
assert_(any(linspace(0, stop, 10, endpoint=False, dtype=dt)))
119120

121+
def test_equivalent_to_arange(self):
122+
for j in range(1000):
123+
assert_equal(linspace(0, j, j+1, dtype=int),
124+
arange(j+1, dtype=int))
125+
126+
def test_retstep(self):
127+
y = linspace(0, 1, 2, retstep=True)
128+
assert_(isinstance(y, tuple) and len(y) == 2)
129+
for num in (0, 1):
130+
for ept in (False, True):
131+
y = linspace(0, 1, num, endpoint=ept, retstep=True)
132+
assert_(isinstance(y, tuple) and len(y) == 2 and
133+
len(y[0]) == num and isnan(y[1]),
134+
'num={0}, endpoint={1}'.format(num, ept))
135+
120136

121137
if __name__ == "__main__":
122138
run_module_suite()

0 commit comments

Comments
 (0)
0