3
3
import warnings
4
4
import operator
5
5
6
- __all__ = ['logspace' , 'linspace' ]
7
-
8
6
from . import numeric as _nx
9
- from .numeric import result_type , NaN , shares_memory , MAY_SHARE_BOUNDS , TooHardError
7
+ from .numeric import (result_type , NaN , shares_memory , MAY_SHARE_BOUNDS ,
8
+ TooHardError )
9
+
10
+ __all__ = ['logspace' , 'linspace' , 'geomspace' ]
11
+
10
12
11
13
def _index_deprecate (i , stacklevel = 2 ):
12
14
try :
@@ -73,11 +75,11 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
73
75
Examples
74
76
--------
75
77
>>> np.linspace(2.0, 3.0, num=5)
76
- array([ 2. , 2.25, 2.5 , 2.75, 3. ])
78
+ array([ 2. , 2.25, 2.5 , 2.75, 3. ])
77
79
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
78
- array([ 2. , 2.2, 2.4, 2.6, 2.8])
80
+ array([ 2. , 2.2, 2.4, 2.6, 2.8])
79
81
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
80
- (array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
82
+ (array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
81
83
82
84
Graphical illustration:
83
85
@@ -102,8 +104,8 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
102
104
div = (num - 1 ) if endpoint else num
103
105
104
106
# Convert float/complex array scalars to float, gh-3504
105
- start = start * 1.
106
- stop = stop * 1.
107
+ start = start * 1.0
108
+ stop = stop * 1.0
107
109
108
110
dt = result_type (start , stop , float (num ))
109
111
if dtype is None :
@@ -156,7 +158,7 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None):
156
158
``base ** stop`` is the final value of the sequence, unless `endpoint`
157
159
is False. In that case, ``num + 1`` values are spaced over the
158
160
interval in log-space, of which all but the last (a sequence of
159
- length `` num` `) are returned.
161
+ length `num`) are returned.
160
162
num : integer, optional
161
163
Number of samples to generate. Default is 50.
162
164
endpoint : boolean, optional
@@ -195,11 +197,11 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None):
195
197
Examples
196
198
--------
197
199
>>> np.logspace(2.0, 3.0, num=4)
198
- array([ 100. , 215.443469 , 464.15888336, 1000. ])
200
+ array([ 100. , 215.443469 , 464.15888336, 1000. ])
199
201
>>> np.logspace(2.0, 3.0, num=4, endpoint=False)
200
- array([ 100. , 177.827941 , 316.22776602, 562.34132519])
202
+ array([ 100. , 177.827941 , 316.22776602, 562.34132519])
201
203
>>> np.logspace(2.0, 3.0, num=4, base=2.0)
202
- array([ 4. , 5.0396842 , 6.34960421, 8. ])
204
+ array([ 4. , 5.0396842 , 6.34960421, 8. ])
203
205
204
206
Graphical illustration:
205
207
@@ -221,3 +223,127 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None):
221
223
if dtype is None :
222
224
return _nx .power (base , y )
223
225
return _nx .power (base , y ).astype (dtype )
226
+
227
+
228
+ def geomspace (start , stop , num = 50 , endpoint = True , dtype = None ):
229
+ """
230
+ Return numbers spaced evenly on a log scale (a geometric progression).
231
+
232
+ This is similar to `logspace`, but with endpoints specified directly.
233
+ Each output sample is a constant multiple of the previous.
234
+
235
+ Parameters
236
+ ----------
237
+ start : scalar
238
+ The starting value of the sequence.
239
+ stop : scalar
240
+ The final value of the sequence, unless `endpoint` is False.
241
+ In that case, ``num + 1`` values are spaced over the
242
+ interval in log-space, of which all but the last (a sequence of
243
+ length `num`) are returned.
244
+ num : integer, optional
245
+ Number of samples to generate. Default is 50.
246
+ endpoint : boolean, optional
247
+ If true, `stop` is the last sample. Otherwise, it is not included.
248
+ Default is True.
249
+ dtype : dtype
250
+ The type of the output array. If `dtype` is not given, infer the data
251
+ type from the other input arguments.
252
+
253
+ Returns
254
+ -------
255
+ samples : ndarray
256
+ `num` samples, equally spaced on a log scale.
257
+
258
+ See Also
259
+ --------
260
+ logspace : Similar to geomspace, but with endpoints specified using log
261
+ and base.
262
+ linspace : Similar to geomspace, but with arithmetic instead of geometric
263
+ progression.
264
+ arange : Similar to linspace, with the step size specified instead of the
265
+ number of samples.
266
+
267
+ Notes
268
+ -----
269
+ If the inputs or dtype are complex, the output will follow a logarithmic
270
+ spiral in the complex plane. (There are an infinite number of spirals
271
+ passing through two points; the output will follow the shortest such path.)
272
+
273
+ Examples
274
+ --------
275
+ >>> np.geomspace(1, 1000, num=4)
276
+ array([ 1., 10., 100., 1000.])
277
+ >>> np.geomspace(1, 1000, num=3, endpoint=False)
278
+ array([ 1., 10., 100.])
279
+ >>> np.geomspace(1, 1000, num=4, endpoint=False)
280
+ array([ 1. , 5.62341325, 31.6227766 , 177.827941 ])
281
+ >>> np.geomspace(1, 256, num=9)
282
+ array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.])
283
+
284
+ Note that the above may not produce exact integers:
285
+
286
+ >>> np.geomspace(1, 256, num=9, dtype=int)
287
+ array([ 1, 2, 4, 7, 16, 32, 63, 127, 256])
288
+ >>> np.around(np.geomspace(1, 256, num=9)).astype(int)
289
+ array([ 1, 2, 4, 8, 16, 32, 64, 128, 256])
290
+
291
+ Negative, decreasing, and complex inputs are allowed:
292
+
293
+ >>> geomspace(1000, 1, num=4)
294
+ array([ 1000., 100., 10., 1.])
295
+ >>> geomspace(-1000, -1, num=4)
296
+ array([-1000., -100., -10., -1.])
297
+ >>> geomspace(1j, 1000j, num=4) # Straight line
298
+ array([ 0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
299
+ >>> geomspace(-1+0j, 1+0j, num=5) # Circle
300
+ array([-1.00000000+0.j , -0.70710678+0.70710678j,
301
+ 0.00000000+1.j , 0.70710678+0.70710678j,
302
+ 1.00000000+0.j ])
303
+
304
+ Graphical illustration of ``endpoint`` parameter:
305
+
306
+ >>> import matplotlib.pyplot as plt
307
+ >>> N = 10
308
+ >>> y = np.zeros(N)
309
+ >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
310
+ >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
311
+ >>> plt.axis([0.5, 2000, 0, 3])
312
+ >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
313
+ >>> plt.show()
314
+
315
+ """
316
+ if start == 0 or stop == 0 :
317
+ raise ValueError ('Geometric sequence cannot include zero' )
318
+
319
+ dt = result_type (start , stop , float (num ))
320
+ if dtype is None :
321
+ dtype = dt
322
+ else :
323
+ # complex to dtype('complex128'), for instance
324
+ dtype = _nx .dtype (dtype )
325
+
326
+ # Avoid negligible real or imaginary parts in output by rotating to
327
+ # positive real, calculating, then undoing rotation
328
+ out_sign = 1
329
+ if start .real == stop .real == 0 :
330
+ start , stop = start .imag , stop .imag
331
+ out_sign = 1j * out_sign
332
+ if _nx .sign (start ) == _nx .sign (stop ) == - 1 :
333
+ start , stop = - start , - stop
334
+ out_sign = - out_sign
335
+
336
+ # Promote both arguments to the same dtype in case, for instance, one is
337
+ # complex and another is negative and log would produce NaN otherwise
338
+ start = start + (stop - stop )
339
+ stop = stop + (start - start )
340
+ if _nx .issubdtype (dtype , complex ):
341
+ start = start + 0j
342
+ stop = stop + 0j
343
+
344
+ log_start = _nx .log10 (start )
345
+ log_stop = _nx .log10 (stop )
346
+ result = out_sign * logspace (log_start , log_stop , num = num ,
347
+ endpoint = endpoint , base = 10.0 , dtype = dtype )
348
+
349
+ return result .astype (dtype )
0 commit comments