Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/_core/function_base.py: 33%
118 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-09 06:12 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-09 06:12 +0000
1import functools
2import warnings
3import operator
4import types
6import numpy as np
7from . import numeric as _nx
8from .numeric import result_type, nan, asanyarray, ndim
9from numpy._core.multiarray import add_docstring
10from numpy._core._multiarray_umath import _array_converter
11from numpy._core import overrides
13__all__ = ['logspace', 'linspace', 'geomspace']
16array_function_dispatch = functools.partial(
17 overrides.array_function_dispatch, module='numpy')
20def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None,
21 dtype=None, axis=None, *, device=None):
22 return (start, stop)
25@array_function_dispatch(_linspace_dispatcher)
26def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
27 axis=0, *, device=None):
28 """
29 Return evenly spaced numbers over a specified interval.
31 Returns `num` evenly spaced samples, calculated over the
32 interval [`start`, `stop`].
34 The endpoint of the interval can optionally be excluded.
36 .. versionchanged:: 1.16.0
37 Non-scalar `start` and `stop` are now supported.
39 .. versionchanged:: 1.20.0
40 Values are rounded towards ``-inf`` instead of ``0`` when an
41 integer ``dtype`` is specified. The old behavior can
42 still be obtained with ``np.linspace(start, stop, num).astype(int)``
44 Parameters
45 ----------
46 start : array_like
47 The starting value of the sequence.
48 stop : array_like
49 The end value of the sequence, unless `endpoint` is set to False.
50 In that case, the sequence consists of all but the last of ``num + 1``
51 evenly spaced samples, so that `stop` is excluded. Note that the step
52 size changes when `endpoint` is False.
53 num : int, optional
54 Number of samples to generate. Default is 50. Must be non-negative.
55 endpoint : bool, optional
56 If True, `stop` is the last sample. Otherwise, it is not included.
57 Default is True.
58 retstep : bool, optional
59 If True, return (`samples`, `step`), where `step` is the spacing
60 between samples.
61 dtype : dtype, optional
62 The type of the output array. If `dtype` is not given, the data type
63 is inferred from `start` and `stop`. The inferred dtype will never be
64 an integer; `float` is chosen even if the arguments would produce an
65 array of integers.
67 .. versionadded:: 1.9.0
68 axis : int, optional
69 The axis in the result to store the samples. Relevant only if start
70 or stop are array-like. By default (0), the samples will be along a
71 new axis inserted at the beginning. Use -1 to get an axis at the end.
73 .. versionadded:: 1.16.0
74 device : str, optional
75 The device on which to place the created array. Default: None.
76 For Array-API interoperability only, so must be ``"cpu"`` if passed.
78 .. versionadded:: 2.0.0
80 Returns
81 -------
82 samples : ndarray
83 There are `num` equally spaced samples in the closed interval
84 ``[start, stop]`` or the half-open interval ``[start, stop)``
85 (depending on whether `endpoint` is True or False).
86 step : float, optional
87 Only returned if `retstep` is True
89 Size of spacing between samples.
92 See Also
93 --------
94 arange : Similar to `linspace`, but uses a step size (instead of the
95 number of samples).
96 geomspace : Similar to `linspace`, but with numbers spaced evenly on a log
97 scale (a geometric progression).
98 logspace : Similar to `geomspace`, but with the end points specified as
99 logarithms.
100 :ref:`how-to-partition`
102 Examples
103 --------
104 >>> np.linspace(2.0, 3.0, num=5)
105 array([2. , 2.25, 2.5 , 2.75, 3. ])
106 >>> np.linspace(2.0, 3.0, num=5, endpoint=False)
107 array([2. , 2.2, 2.4, 2.6, 2.8])
108 >>> np.linspace(2.0, 3.0, num=5, retstep=True)
109 (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
111 Graphical illustration:
113 >>> import matplotlib.pyplot as plt
114 >>> N = 8
115 >>> y = np.zeros(N)
116 >>> x1 = np.linspace(0, 10, N, endpoint=True)
117 >>> x2 = np.linspace(0, 10, N, endpoint=False)
118 >>> plt.plot(x1, y, 'o')
119 [<matplotlib.lines.Line2D object at 0x...>]
120 >>> plt.plot(x2, y + 0.5, 'o')
121 [<matplotlib.lines.Line2D object at 0x...>]
122 >>> plt.ylim([-0.5, 1])
123 (-0.5, 1)
124 >>> plt.show()
126 """
127 num = operator.index(num)
128 if num < 0:
129 raise ValueError(
130 "Number of samples, %s, must be non-negative." % num
131 )
132 div = (num - 1) if endpoint else num
134 conv = _array_converter(start, stop)
135 start, stop = conv.as_arrays()
136 dt = conv.result_type(ensure_inexact=True)
138 if dtype is None:
139 dtype = dt
140 integer_dtype = False
141 else:
142 integer_dtype = _nx.issubdtype(dtype, _nx.integer)
144 # Use `dtype=type(dt)` to enforce a floating point evaluation:
145 delta = np.subtract(stop, start, dtype=type(dt))
146 y = _nx.arange(
147 0, num, dtype=dt, device=device
148 ).reshape((-1,) + (1,) * ndim(delta))
150 # In-place multiplication y *= delta/div is faster, but prevents
151 # the multiplicant from overriding what class is produced, and thus
152 # prevents, e.g. use of Quantities, see gh-7142. Hence, we multiply
153 # in place only for standard scalar types.
154 if div > 0:
155 _mult_inplace = _nx.isscalar(delta)
156 step = delta / div
157 any_step_zero = (
158 step == 0 if _mult_inplace else _nx.asanyarray(step == 0).any())
159 if any_step_zero:
160 # Special handling for denormal numbers, gh-5437
161 y /= div
162 if _mult_inplace:
163 y *= delta
164 else:
165 y = y * delta
166 else:
167 if _mult_inplace:
168 y *= step
169 else:
170 y = y * step
171 else:
172 # sequences with 0 items or 1 item with endpoint=True (i.e. div <= 0)
173 # have an undefined step
174 step = nan
175 # Multiply with delta to allow possible override of output class.
176 y = y * delta
178 y += start
180 if endpoint and num > 1:
181 y[-1, ...] = stop
183 if axis != 0:
184 y = _nx.moveaxis(y, 0, axis)
186 if integer_dtype:
187 _nx.floor(y, out=y)
189 y = conv.wrap(y.astype(dtype, copy=False))
190 if retstep:
191 return y, step
192 else:
193 return y
196def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None,
197 dtype=None, axis=None):
198 return (start, stop, base)
201@array_function_dispatch(_logspace_dispatcher)
202def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
203 axis=0):
204 """
205 Return numbers spaced evenly on a log scale.
207 In linear space, the sequence starts at ``base ** start``
208 (`base` to the power of `start`) and ends with ``base ** stop``
209 (see `endpoint` below).
211 .. versionchanged:: 1.16.0
212 Non-scalar `start` and `stop` are now supported.
214 .. versionchanged:: 1.25.0
215 Non-scalar 'base` is now supported
217 Parameters
218 ----------
219 start : array_like
220 ``base ** start`` is the starting value of the sequence.
221 stop : array_like
222 ``base ** stop`` is the final value of the sequence, unless `endpoint`
223 is False. In that case, ``num + 1`` values are spaced over the
224 interval in log-space, of which all but the last (a sequence of
225 length `num`) are returned.
226 num : integer, optional
227 Number of samples to generate. Default is 50.
228 endpoint : boolean, optional
229 If true, `stop` is the last sample. Otherwise, it is not included.
230 Default is True.
231 base : array_like, optional
232 The base of the log space. The step size between the elements in
233 ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform.
234 Default is 10.0.
235 dtype : dtype
236 The type of the output array. If `dtype` is not given, the data type
237 is inferred from `start` and `stop`. The inferred type will never be
238 an integer; `float` is chosen even if the arguments would produce an
239 array of integers.
240 axis : int, optional
241 The axis in the result to store the samples. Relevant only if start,
242 stop, or base are array-like. By default (0), the samples will be
243 along a new axis inserted at the beginning. Use -1 to get an axis at
244 the end.
246 .. versionadded:: 1.16.0
249 Returns
250 -------
251 samples : ndarray
252 `num` samples, equally spaced on a log scale.
254 See Also
255 --------
256 arange : Similar to linspace, with the step size specified instead of the
257 number of samples. Note that, when used with a float endpoint, the
258 endpoint may or may not be included.
259 linspace : Similar to logspace, but with the samples uniformly distributed
260 in linear space, instead of log space.
261 geomspace : Similar to logspace, but with endpoints specified directly.
262 :ref:`how-to-partition`
264 Notes
265 -----
266 If base is a scalar, logspace is equivalent to the code
268 >>> y = np.linspace(start, stop, num=num, endpoint=endpoint)
269 ... # doctest: +SKIP
270 >>> power(base, y).astype(dtype)
271 ... # doctest: +SKIP
273 Examples
274 --------
275 >>> np.logspace(2.0, 3.0, num=4)
276 array([ 100. , 215.443469 , 464.15888336, 1000. ])
277 >>> np.logspace(2.0, 3.0, num=4, endpoint=False)
278 array([100. , 177.827941 , 316.22776602, 562.34132519])
279 >>> np.logspace(2.0, 3.0, num=4, base=2.0)
280 array([4. , 5.0396842 , 6.34960421, 8. ])
281 >>> np.logspace(2.0, 3.0, num=4, base=[2.0, 3.0], axis=-1)
282 array([[ 4. , 5.0396842 , 6.34960421, 8. ],
283 [ 9. , 12.98024613, 18.72075441, 27. ]])
285 Graphical illustration:
287 >>> import matplotlib.pyplot as plt
288 >>> N = 10
289 >>> x1 = np.logspace(0.1, 1, N, endpoint=True)
290 >>> x2 = np.logspace(0.1, 1, N, endpoint=False)
291 >>> y = np.zeros(N)
292 >>> plt.plot(x1, y, 'o')
293 [<matplotlib.lines.Line2D object at 0x...>]
294 >>> plt.plot(x2, y + 0.5, 'o')
295 [<matplotlib.lines.Line2D object at 0x...>]
296 >>> plt.ylim([-0.5, 1])
297 (-0.5, 1)
298 >>> plt.show()
300 """
301 if not isinstance(base, (float, int)) and np.ndim(base):
302 # If base is non-scalar, broadcast it with the others, since it
303 # may influence how axis is interpreted.
304 ndmax = np.broadcast(start, stop, base).ndim
305 start, stop, base = (
306 np.array(a, copy=None, subok=True, ndmin=ndmax)
307 for a in (start, stop, base)
308 )
309 base = np.expand_dims(base, axis=axis)
310 y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis)
311 if dtype is None:
312 return _nx.power(base, y)
313 return _nx.power(base, y).astype(dtype, copy=False)
316def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None,
317 axis=None):
318 return (start, stop)
321@array_function_dispatch(_geomspace_dispatcher)
322def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
323 """
324 Return numbers spaced evenly on a log scale (a geometric progression).
326 This is similar to `logspace`, but with endpoints specified directly.
327 Each output sample is a constant multiple of the previous.
329 .. versionchanged:: 1.16.0
330 Non-scalar `start` and `stop` are now supported.
332 Parameters
333 ----------
334 start : array_like
335 The starting value of the sequence.
336 stop : array_like
337 The final value of the sequence, unless `endpoint` is False.
338 In that case, ``num + 1`` values are spaced over the
339 interval in log-space, of which all but the last (a sequence of
340 length `num`) are returned.
341 num : integer, optional
342 Number of samples to generate. Default is 50.
343 endpoint : boolean, optional
344 If true, `stop` is the last sample. Otherwise, it is not included.
345 Default is True.
346 dtype : dtype
347 The type of the output array. If `dtype` is not given, the data type
348 is inferred from `start` and `stop`. The inferred dtype will never be
349 an integer; `float` is chosen even if the arguments would produce an
350 array of integers.
351 axis : int, optional
352 The axis in the result to store the samples. Relevant only if start
353 or stop are array-like. By default (0), the samples will be along a
354 new axis inserted at the beginning. Use -1 to get an axis at the end.
356 .. versionadded:: 1.16.0
358 Returns
359 -------
360 samples : ndarray
361 `num` samples, equally spaced on a log scale.
363 See Also
364 --------
365 logspace : Similar to geomspace, but with endpoints specified using log
366 and base.
367 linspace : Similar to geomspace, but with arithmetic instead of geometric
368 progression.
369 arange : Similar to linspace, with the step size specified instead of the
370 number of samples.
371 :ref:`how-to-partition`
373 Notes
374 -----
375 If the inputs or dtype are complex, the output will follow a logarithmic
376 spiral in the complex plane. (There are an infinite number of spirals
377 passing through two points; the output will follow the shortest such path.)
379 Examples
380 --------
381 >>> np.geomspace(1, 1000, num=4)
382 array([ 1., 10., 100., 1000.])
383 >>> np.geomspace(1, 1000, num=3, endpoint=False)
384 array([ 1., 10., 100.])
385 >>> np.geomspace(1, 1000, num=4, endpoint=False)
386 array([ 1. , 5.62341325, 31.6227766 , 177.827941 ])
387 >>> np.geomspace(1, 256, num=9)
388 array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.])
390 Note that the above may not produce exact integers:
392 >>> np.geomspace(1, 256, num=9, dtype=int)
393 array([ 1, 2, 4, 7, 16, 32, 63, 127, 256])
394 >>> np.around(np.geomspace(1, 256, num=9)).astype(int)
395 array([ 1, 2, 4, 8, 16, 32, 64, 128, 256])
397 Negative, decreasing, and complex inputs are allowed:
399 >>> np.geomspace(1000, 1, num=4)
400 array([1000., 100., 10., 1.])
401 >>> np.geomspace(-1000, -1, num=4)
402 array([-1000., -100., -10., -1.])
403 >>> np.geomspace(1j, 1000j, num=4) # Straight line
404 array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
405 >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle
406 array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j,
407 6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j,
408 1.00000000e+00+0.00000000e+00j])
410 Graphical illustration of `endpoint` parameter:
412 >>> import matplotlib.pyplot as plt
413 >>> N = 10
414 >>> y = np.zeros(N)
415 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
416 [<matplotlib.lines.Line2D object at 0x...>]
417 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
418 [<matplotlib.lines.Line2D object at 0x...>]
419 >>> plt.axis([0.5, 2000, 0, 3])
420 [0.5, 2000, 0, 3]
421 >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
422 >>> plt.show()
424 """
425 start = asanyarray(start)
426 stop = asanyarray(stop)
427 if _nx.any(start == 0) or _nx.any(stop == 0):
428 raise ValueError('Geometric sequence cannot include zero')
430 dt = result_type(start, stop, float(num), _nx.zeros((), dtype))
431 if dtype is None:
432 dtype = dt
433 else:
434 # complex to dtype('complex128'), for instance
435 dtype = _nx.dtype(dtype)
437 # Promote both arguments to the same dtype in case, for instance, one is
438 # complex and another is negative and log would produce NaN otherwise.
439 # Copy since we may change things in-place further down.
440 start = start.astype(dt, copy=True)
441 stop = stop.astype(dt, copy=True)
443 # Allow negative real values and ensure a consistent result for complex
444 # (including avoiding negligible real or imaginary parts in output) by
445 # rotating start to positive real, calculating, then undoing rotation.
446 out_sign = _nx.sign(start)
447 start /= out_sign
448 stop = stop / out_sign
450 log_start = _nx.log10(start)
451 log_stop = _nx.log10(stop)
452 result = logspace(log_start, log_stop, num=num,
453 endpoint=endpoint, base=10.0, dtype=dt)
455 # Make sure the endpoints match the start and stop arguments. This is
456 # necessary because np.exp(np.log(x)) is not necessarily equal to x.
457 if num > 0:
458 result[0] = start
459 if num > 1 and endpoint:
460 result[-1] = stop
462 result *= out_sign
464 if axis != 0:
465 result = _nx.moveaxis(result, 0, axis)
467 return result.astype(dtype, copy=False)
470def _needs_add_docstring(obj):
471 """
472 Returns true if the only way to set the docstring of `obj` from python is
473 via add_docstring.
475 This function errs on the side of being overly conservative.
476 """
477 Py_TPFLAGS_HEAPTYPE = 1 << 9
479 if isinstance(obj, (types.FunctionType, types.MethodType, property)):
480 return False
482 if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE:
483 return False
485 return True
488def _add_docstring(obj, doc, warn_on_python):
489 if warn_on_python and not _needs_add_docstring(obj):
490 warnings.warn(
491 "add_newdoc was used on a pure-python object {}. "
492 "Prefer to attach it directly to the source."
493 .format(obj),
494 UserWarning,
495 stacklevel=3)
496 try:
497 add_docstring(obj, doc)
498 except Exception:
499 pass
502def add_newdoc(place, obj, doc, warn_on_python=True):
503 """
504 Add documentation to an existing object, typically one defined in C
506 The purpose is to allow easier editing of the docstrings without requiring
507 a re-compile. This exists primarily for internal use within numpy itself.
509 Parameters
510 ----------
511 place : str
512 The absolute name of the module to import from
513 obj : str or None
514 The name of the object to add documentation to, typically a class or
515 function name.
516 doc : {str, Tuple[str, str], List[Tuple[str, str]]}
517 If a string, the documentation to apply to `obj`
519 If a tuple, then the first element is interpreted as an attribute
520 of `obj` and the second as the docstring to apply -
521 ``(method, docstring)``
523 If a list, then each element of the list should be a tuple of length
524 two - ``[(method1, docstring1), (method2, docstring2), ...]``
525 warn_on_python : bool
526 If True, the default, emit `UserWarning` if this is used to attach
527 documentation to a pure-python object.
529 Notes
530 -----
531 This routine never raises an error if the docstring can't be written, but
532 will raise an error if the object being documented does not exist.
534 This routine cannot modify read-only docstrings, as appear
535 in new-style classes or built-in functions. Because this
536 routine never raises an error the caller must check manually
537 that the docstrings were changed.
539 Since this function grabs the ``char *`` from a c-level str object and puts
540 it into the ``tp_doc`` slot of the type of `obj`, it violates a number of
541 C-API best-practices, by:
543 - modifying a `PyTypeObject` after calling `PyType_Ready`
544 - calling `Py_INCREF` on the str and losing the reference, so the str
545 will never be released
547 If possible it should be avoided.
548 """
549 new = getattr(__import__(place, globals(), {}, [obj]), obj)
550 if isinstance(doc, str):
551 _add_docstring(new, doc.strip(), warn_on_python)
552 elif isinstance(doc, tuple):
553 attr, docstring = doc
554 _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)
555 elif isinstance(doc, list):
556 for attr, docstring in doc:
557 _add_docstring(
558 getattr(new, attr), docstring.strip(), warn_on_python
559 )