Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/numpy/core/function_base.py : 55%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import functools
2import warnings
3import operator
4import types
6from . import numeric as _nx
7from .numeric import result_type, NaN, asanyarray, ndim
8from numpy.core.multiarray import add_docstring
9from numpy.core import overrides
11__all__ = ['logspace', 'linspace', 'geomspace']
14array_function_dispatch = functools.partial(
15 overrides.array_function_dispatch, module='numpy')
18def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None,
19 dtype=None, axis=None):
20 return (start, stop)
23@array_function_dispatch(_linspace_dispatcher)
24def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
25 axis=0):
26 """
27 Return evenly spaced numbers over a specified interval.
29 Returns `num` evenly spaced samples, calculated over the
30 interval [`start`, `stop`].
32 The endpoint of the interval can optionally be excluded.
34 .. versionchanged:: 1.16.0
35 Non-scalar `start` and `stop` are now supported.
37 Parameters
38 ----------
39 start : array_like
40 The starting value of the sequence.
41 stop : array_like
42 The end value of the sequence, unless `endpoint` is set to False.
43 In that case, the sequence consists of all but the last of ``num + 1``
44 evenly spaced samples, so that `stop` is excluded. Note that the step
45 size changes when `endpoint` is False.
46 num : int, optional
47 Number of samples to generate. Default is 50. Must be non-negative.
48 endpoint : bool, optional
49 If True, `stop` is the last sample. Otherwise, it is not included.
50 Default is True.
51 retstep : bool, optional
52 If True, return (`samples`, `step`), where `step` is the spacing
53 between samples.
54 dtype : dtype, optional
55 The type of the output array. If `dtype` is not given, infer the data
56 type from the other input arguments.
58 .. versionadded:: 1.9.0
60 axis : int, optional
61 The axis in the result to store the samples. Relevant only if start
62 or stop are array-like. By default (0), the samples will be along a
63 new axis inserted at the beginning. Use -1 to get an axis at the end.
65 .. versionadded:: 1.16.0
67 Returns
68 -------
69 samples : ndarray
70 There are `num` equally spaced samples in the closed interval
71 ``[start, stop]`` or the half-open interval ``[start, stop)``
72 (depending on whether `endpoint` is True or False).
73 step : float, optional
74 Only returned if `retstep` is True
76 Size of spacing between samples.
79 See Also
80 --------
81 arange : Similar to `linspace`, but uses a step size (instead of the
82 number of samples).
83 geomspace : Similar to `linspace`, but with numbers spaced evenly on a log
84 scale (a geometric progression).
85 logspace : Similar to `geomspace`, but with the end points specified as
86 logarithms.
88 Examples
89 --------
90 >>> np.linspace(2.0, 3.0, num=5)
91 array([2. , 2.25, 2.5 , 2.75, 3. ])
92 >>> np.linspace(2.0, 3.0, num=5, endpoint=False)
93 array([2. , 2.2, 2.4, 2.6, 2.8])
94 >>> np.linspace(2.0, 3.0, num=5, retstep=True)
95 (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
97 Graphical illustration:
99 >>> import matplotlib.pyplot as plt
100 >>> N = 8
101 >>> y = np.zeros(N)
102 >>> x1 = np.linspace(0, 10, N, endpoint=True)
103 >>> x2 = np.linspace(0, 10, N, endpoint=False)
104 >>> plt.plot(x1, y, 'o')
105 [<matplotlib.lines.Line2D object at 0x...>]
106 >>> plt.plot(x2, y + 0.5, 'o')
107 [<matplotlib.lines.Line2D object at 0x...>]
108 >>> plt.ylim([-0.5, 1])
109 (-0.5, 1)
110 >>> plt.show()
112 """
113 num = operator.index(num)
114 if num < 0:
115 raise ValueError("Number of samples, %s, must be non-negative." % num)
116 div = (num - 1) if endpoint else num
118 # Convert float/complex array scalars to float, gh-3504
119 # and make sure one can use variables that have an __array_interface__, gh-6634
120 start = asanyarray(start) * 1.0
121 stop = asanyarray(stop) * 1.0
123 dt = result_type(start, stop, float(num))
124 if dtype is None:
125 dtype = dt
127 delta = stop - start
128 y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta))
129 # In-place multiplication y *= delta/div is faster, but prevents the multiplicant
130 # from overriding what class is produced, and thus prevents, e.g. use of Quantities,
131 # see gh-7142. Hence, we multiply in place only for standard scalar types.
132 _mult_inplace = _nx.isscalar(delta)
133 if div > 0:
134 step = delta / div
135 if _nx.any(step == 0):
136 # Special handling for denormal numbers, gh-5437
137 y /= div
138 if _mult_inplace:
139 y *= delta
140 else:
141 y = y * delta
142 else:
143 if _mult_inplace:
144 y *= step
145 else:
146 y = y * step
147 else:
148 # sequences with 0 items or 1 item with endpoint=True (i.e. div <= 0)
149 # have an undefined step
150 step = NaN
151 # Multiply with delta to allow possible override of output class.
152 y = y * delta
154 y += start
156 if endpoint and num > 1:
157 y[-1] = stop
159 if axis != 0:
160 y = _nx.moveaxis(y, 0, axis)
162 if retstep:
163 return y.astype(dtype, copy=False), step
164 else:
165 return y.astype(dtype, copy=False)
168def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None,
169 dtype=None, axis=None):
170 return (start, stop)
173@array_function_dispatch(_logspace_dispatcher)
174def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
175 axis=0):
176 """
177 Return numbers spaced evenly on a log scale.
179 In linear space, the sequence starts at ``base ** start``
180 (`base` to the power of `start`) and ends with ``base ** stop``
181 (see `endpoint` below).
183 .. versionchanged:: 1.16.0
184 Non-scalar `start` and `stop` are now supported.
186 Parameters
187 ----------
188 start : array_like
189 ``base ** start`` is the starting value of the sequence.
190 stop : array_like
191 ``base ** stop`` is the final value of the sequence, unless `endpoint`
192 is False. In that case, ``num + 1`` values are spaced over the
193 interval in log-space, of which all but the last (a sequence of
194 length `num`) are returned.
195 num : integer, optional
196 Number of samples to generate. Default is 50.
197 endpoint : boolean, optional
198 If true, `stop` is the last sample. Otherwise, it is not included.
199 Default is True.
200 base : float, optional
201 The base of the log space. The step size between the elements in
202 ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform.
203 Default is 10.0.
204 dtype : dtype
205 The type of the output array. If `dtype` is not given, infer the data
206 type from the other input arguments.
207 axis : int, optional
208 The axis in the result to store the samples. Relevant only if start
209 or stop are array-like. By default (0), the samples will be along a
210 new axis inserted at the beginning. Use -1 to get an axis at the end.
212 .. versionadded:: 1.16.0
215 Returns
216 -------
217 samples : ndarray
218 `num` samples, equally spaced on a log scale.
220 See Also
221 --------
222 arange : Similar to linspace, with the step size specified instead of the
223 number of samples. Note that, when used with a float endpoint, the
224 endpoint may or may not be included.
225 linspace : Similar to logspace, but with the samples uniformly distributed
226 in linear space, instead of log space.
227 geomspace : Similar to logspace, but with endpoints specified directly.
229 Notes
230 -----
231 Logspace is equivalent to the code
233 >>> y = np.linspace(start, stop, num=num, endpoint=endpoint)
234 ... # doctest: +SKIP
235 >>> power(base, y).astype(dtype)
236 ... # doctest: +SKIP
238 Examples
239 --------
240 >>> np.logspace(2.0, 3.0, num=4)
241 array([ 100. , 215.443469 , 464.15888336, 1000. ])
242 >>> np.logspace(2.0, 3.0, num=4, endpoint=False)
243 array([100. , 177.827941 , 316.22776602, 562.34132519])
244 >>> np.logspace(2.0, 3.0, num=4, base=2.0)
245 array([4. , 5.0396842 , 6.34960421, 8. ])
247 Graphical illustration:
249 >>> import matplotlib.pyplot as plt
250 >>> N = 10
251 >>> x1 = np.logspace(0.1, 1, N, endpoint=True)
252 >>> x2 = np.logspace(0.1, 1, N, endpoint=False)
253 >>> y = np.zeros(N)
254 >>> plt.plot(x1, y, 'o')
255 [<matplotlib.lines.Line2D object at 0x...>]
256 >>> plt.plot(x2, y + 0.5, 'o')
257 [<matplotlib.lines.Line2D object at 0x...>]
258 >>> plt.ylim([-0.5, 1])
259 (-0.5, 1)
260 >>> plt.show()
262 """
263 y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis)
264 if dtype is None:
265 return _nx.power(base, y)
266 return _nx.power(base, y).astype(dtype, copy=False)
269def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None,
270 axis=None):
271 return (start, stop)
274@array_function_dispatch(_geomspace_dispatcher)
275def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
276 """
277 Return numbers spaced evenly on a log scale (a geometric progression).
279 This is similar to `logspace`, but with endpoints specified directly.
280 Each output sample is a constant multiple of the previous.
282 .. versionchanged:: 1.16.0
283 Non-scalar `start` and `stop` are now supported.
285 Parameters
286 ----------
287 start : array_like
288 The starting value of the sequence.
289 stop : array_like
290 The final value of the sequence, unless `endpoint` is False.
291 In that case, ``num + 1`` values are spaced over the
292 interval in log-space, of which all but the last (a sequence of
293 length `num`) are returned.
294 num : integer, optional
295 Number of samples to generate. Default is 50.
296 endpoint : boolean, optional
297 If true, `stop` is the last sample. Otherwise, it is not included.
298 Default is True.
299 dtype : dtype
300 The type of the output array. If `dtype` is not given, infer the data
301 type from the other input arguments.
302 axis : int, optional
303 The axis in the result to store the samples. Relevant only if start
304 or stop are array-like. By default (0), the samples will be along a
305 new axis inserted at the beginning. Use -1 to get an axis at the end.
307 .. versionadded:: 1.16.0
309 Returns
310 -------
311 samples : ndarray
312 `num` samples, equally spaced on a log scale.
314 See Also
315 --------
316 logspace : Similar to geomspace, but with endpoints specified using log
317 and base.
318 linspace : Similar to geomspace, but with arithmetic instead of geometric
319 progression.
320 arange : Similar to linspace, with the step size specified instead of the
321 number of samples.
323 Notes
324 -----
325 If the inputs or dtype are complex, the output will follow a logarithmic
326 spiral in the complex plane. (There are an infinite number of spirals
327 passing through two points; the output will follow the shortest such path.)
329 Examples
330 --------
331 >>> np.geomspace(1, 1000, num=4)
332 array([ 1., 10., 100., 1000.])
333 >>> np.geomspace(1, 1000, num=3, endpoint=False)
334 array([ 1., 10., 100.])
335 >>> np.geomspace(1, 1000, num=4, endpoint=False)
336 array([ 1. , 5.62341325, 31.6227766 , 177.827941 ])
337 >>> np.geomspace(1, 256, num=9)
338 array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.])
340 Note that the above may not produce exact integers:
342 >>> np.geomspace(1, 256, num=9, dtype=int)
343 array([ 1, 2, 4, 7, 16, 32, 63, 127, 256])
344 >>> np.around(np.geomspace(1, 256, num=9)).astype(int)
345 array([ 1, 2, 4, 8, 16, 32, 64, 128, 256])
347 Negative, decreasing, and complex inputs are allowed:
349 >>> np.geomspace(1000, 1, num=4)
350 array([1000., 100., 10., 1.])
351 >>> np.geomspace(-1000, -1, num=4)
352 array([-1000., -100., -10., -1.])
353 >>> np.geomspace(1j, 1000j, num=4) # Straight line
354 array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
355 >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle
356 array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j,
357 6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j,
358 1.00000000e+00+0.00000000e+00j])
360 Graphical illustration of ``endpoint`` parameter:
362 >>> import matplotlib.pyplot as plt
363 >>> N = 10
364 >>> y = np.zeros(N)
365 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
366 [<matplotlib.lines.Line2D object at 0x...>]
367 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
368 [<matplotlib.lines.Line2D object at 0x...>]
369 >>> plt.axis([0.5, 2000, 0, 3])
370 [0.5, 2000, 0, 3]
371 >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
372 >>> plt.show()
374 """
375 start = asanyarray(start)
376 stop = asanyarray(stop)
377 if _nx.any(start == 0) or _nx.any(stop == 0):
378 raise ValueError('Geometric sequence cannot include zero')
380 dt = result_type(start, stop, float(num), _nx.zeros((), dtype))
381 if dtype is None:
382 dtype = dt
383 else:
384 # complex to dtype('complex128'), for instance
385 dtype = _nx.dtype(dtype)
387 # Promote both arguments to the same dtype in case, for instance, one is
388 # complex and another is negative and log would produce NaN otherwise.
389 # Copy since we may change things in-place further down.
390 start = start.astype(dt, copy=True)
391 stop = stop.astype(dt, copy=True)
393 out_sign = _nx.ones(_nx.broadcast(start, stop).shape, dt)
394 # Avoid negligible real or imaginary parts in output by rotating to
395 # positive real, calculating, then undoing rotation
396 if _nx.issubdtype(dt, _nx.complexfloating):
397 all_imag = (start.real == 0.) & (stop.real == 0.)
398 if _nx.any(all_imag):
399 start[all_imag] = start[all_imag].imag
400 stop[all_imag] = stop[all_imag].imag
401 out_sign[all_imag] = 1j
403 both_negative = (_nx.sign(start) == -1) & (_nx.sign(stop) == -1)
404 if _nx.any(both_negative):
405 _nx.negative(start, out=start, where=both_negative)
406 _nx.negative(stop, out=stop, where=both_negative)
407 _nx.negative(out_sign, out=out_sign, where=both_negative)
409 log_start = _nx.log10(start)
410 log_stop = _nx.log10(stop)
411 result = out_sign * logspace(log_start, log_stop, num=num,
412 endpoint=endpoint, base=10.0, dtype=dtype)
413 if axis != 0:
414 result = _nx.moveaxis(result, 0, axis)
416 return result.astype(dtype, copy=False)
419def _needs_add_docstring(obj):
420 """
421 Returns true if the only way to set the docstring of `obj` from python is
422 via add_docstring.
424 This function errs on the side of being overly conservative.
425 """
426 Py_TPFLAGS_HEAPTYPE = 1 << 9
428 if isinstance(obj, (types.FunctionType, types.MethodType, property)):
429 return False
431 if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE:
432 return False
434 return True
437def _add_docstring(obj, doc, warn_on_python):
438 if warn_on_python and not _needs_add_docstring(obj):
439 warnings.warn(
440 "add_newdoc was used on a pure-python object {}. "
441 "Prefer to attach it directly to the source."
442 .format(obj),
443 UserWarning,
444 stacklevel=3)
445 try:
446 add_docstring(obj, doc)
447 except Exception:
448 pass
451def add_newdoc(place, obj, doc, warn_on_python=True):
452 """
453 Add documentation to an existing object, typically one defined in C
455 The purpose is to allow easier editing of the docstrings without requiring
456 a re-compile. This exists primarily for internal use within numpy itself.
458 Parameters
459 ----------
460 place : str
461 The absolute name of the module to import from
462 obj : str
463 The name of the object to add documentation to, typically a class or
464 function name
465 doc : {str, Tuple[str, str], List[Tuple[str, str]]}
466 If a string, the documentation to apply to `obj`
468 If a tuple, then the first element is interpreted as an attribute of
469 `obj` and the second as the docstring to apply - ``(method, docstring)``
471 If a list, then each element of the list should be a tuple of length
472 two - ``[(method1, docstring1), (method2, docstring2), ...]``
473 warn_on_python : bool
474 If True, the default, emit `UserWarning` if this is used to attach
475 documentation to a pure-python object.
477 Notes
478 -----
479 This routine never raises an error if the docstring can't be written, but
480 will raise an error if the object being documented does not exist.
482 This routine cannot modify read-only docstrings, as appear
483 in new-style classes or built-in functions. Because this
484 routine never raises an error the caller must check manually
485 that the docstrings were changed.
487 Since this function grabs the ``char *`` from a c-level str object and puts
488 it into the ``tp_doc`` slot of the type of `obj`, it violates a number of
489 C-API best-practices, by:
491 - modifying a `PyTypeObject` after calling `PyType_Ready`
492 - calling `Py_INCREF` on the str and losing the reference, so the str
493 will never be released
495 If possible it should be avoided.
496 """
497 new = getattr(__import__(place, globals(), {}, [obj]), obj)
498 if isinstance(doc, str):
499 _add_docstring(new, doc.strip(), warn_on_python)
500 elif isinstance(doc, tuple):
501 attr, docstring = doc
502 _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)
503 elif isinstance(doc, list):
504 for attr, docstring in doc:
505 _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)