| from __future__ import division, absolute_import, print_function |
| |
| import functools |
| import warnings |
| import operator |
| |
| from . import numeric as _nx |
| from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS, |
| TooHardError, asanyarray) |
| from numpy.core.multiarray import add_docstring |
| from numpy.core import overrides |
| |
| __all__ = ['logspace', 'linspace', 'geomspace'] |
| |
| |
| array_function_dispatch = functools.partial( |
| overrides.array_function_dispatch, module='numpy') |
| |
| |
| def _index_deprecate(i, stacklevel=2): |
| try: |
| i = operator.index(i) |
| except TypeError: |
| msg = ("object of type {} cannot be safely interpreted as " |
| "an integer.".format(type(i))) |
| i = int(i) |
| stacklevel += 1 |
| warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel) |
| return i |
| |
| |
| def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None, |
| dtype=None, axis=None): |
| return (start, stop) |
| |
| |
| @array_function_dispatch(_linspace_dispatcher) |
| def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, |
| axis=0): |
| """ |
| Return evenly spaced numbers over a specified interval. |
| |
| Returns `num` evenly spaced samples, calculated over the |
| interval [`start`, `stop`]. |
| |
| The endpoint of the interval can optionally be excluded. |
| |
| .. versionchanged:: 1.16.0 |
| Non-scalar `start` and `stop` are now supported. |
| |
| Parameters |
| ---------- |
| start : array_like |
| The starting value of the sequence. |
| stop : array_like |
| The end value of the sequence, unless `endpoint` is set to False. |
| In that case, the sequence consists of all but the last of ``num + 1`` |
| evenly spaced samples, so that `stop` is excluded. Note that the step |
| size changes when `endpoint` is False. |
| num : int, optional |
| Number of samples to generate. Default is 50. Must be non-negative. |
| endpoint : bool, optional |
| If True, `stop` is the last sample. Otherwise, it is not included. |
| Default is True. |
| retstep : bool, optional |
| 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. |
| |
| .. versionadded:: 1.9.0 |
| |
| axis : int, optional |
| The axis in the result to store the samples. Relevant only if start |
| or stop are array-like. By default (0), the samples will be along a |
| new axis inserted at the beginning. Use -1 to get an axis at the end. |
| |
| .. versionadded:: 1.16.0 |
| |
| Returns |
| ------- |
| samples : ndarray |
| There are `num` equally spaced samples in the closed interval |
| ``[start, stop]`` or the half-open interval ``[start, stop)`` |
| (depending on whether `endpoint` is True or False). |
| step : float, optional |
| Only returned if `retstep` is True |
| |
| Size of spacing between samples. |
| |
| |
| See Also |
| -------- |
| arange : Similar to `linspace`, but uses a step size (instead of the |
| number of samples). |
| geomspace : Similar to `linspace`, but with numbers spaced evenly on a log |
| scale (a geometric progression). |
| logspace : Similar to `geomspace`, but with the end points specified as |
| logarithms. |
| |
| Examples |
| -------- |
| >>> np.linspace(2.0, 3.0, num=5) |
| array([ 2. , 2.25, 2.5 , 2.75, 3. ]) |
| >>> np.linspace(2.0, 3.0, num=5, endpoint=False) |
| array([ 2. , 2.2, 2.4, 2.6, 2.8]) |
| >>> np.linspace(2.0, 3.0, num=5, retstep=True) |
| (array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25) |
| |
| Graphical illustration: |
| |
| >>> import matplotlib.pyplot as plt |
| >>> N = 8 |
| >>> y = np.zeros(N) |
| >>> x1 = np.linspace(0, 10, N, endpoint=True) |
| >>> x2 = np.linspace(0, 10, N, endpoint=False) |
| >>> plt.plot(x1, y, 'o') |
| [<matplotlib.lines.Line2D object at 0x...>] |
| >>> plt.plot(x2, y + 0.5, 'o') |
| [<matplotlib.lines.Line2D object at 0x...>] |
| >>> plt.ylim([-0.5, 1]) |
| (-0.5, 1) |
| >>> plt.show() |
| |
| """ |
| # 2016-02-25, 1.12 |
| num = _index_deprecate(num) |
| if num < 0: |
| raise ValueError("Number of samples, %s, must be non-negative." % num) |
| div = (num - 1) if endpoint else num |
| |
| # Convert float/complex array scalars to float, gh-3504 |
| # and make sure one can use variables that have an __array_interface__, gh-6634 |
| start = asanyarray(start) * 1.0 |
| stop = asanyarray(stop) * 1.0 |
| |
| dt = result_type(start, stop, float(num)) |
| if dtype is None: |
| dtype = dt |
| |
| delta = stop - start |
| y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * delta.ndim) |
| # In-place multiplication y *= delta/div is faster, but prevents the multiplicant |
| # from overriding what class is produced, and thus prevents, e.g. use of Quantities, |
| # see gh-7142. Hence, we multiply in place only for standard scalar types. |
| _mult_inplace = _nx.isscalar(delta) |
| if num > 1: |
| step = delta / div |
| if _nx.any(step == 0): |
| # Special handling for denormal numbers, gh-5437 |
| y /= div |
| if _mult_inplace: |
| y *= delta |
| else: |
| y = y * delta |
| else: |
| if _mult_inplace: |
| y *= step |
| else: |
| y = y * step |
| else: |
| # 0 and 1 item long sequences have an undefined step |
| step = NaN |
| # Multiply with delta to allow possible override of output class. |
| y = y * delta |
| |
| y += start |
| |
| if endpoint and num > 1: |
| y[-1] = stop |
| |
| if axis != 0: |
| y = _nx.moveaxis(y, 0, axis) |
| |
| if retstep: |
| return y.astype(dtype, copy=False), step |
| else: |
| return y.astype(dtype, copy=False) |
| |
| |
| def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None, |
| dtype=None, axis=None): |
| return (start, stop) |
| |
| |
| @array_function_dispatch(_logspace_dispatcher) |
| def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, |
| axis=0): |
| """ |
| Return numbers spaced evenly on a log scale. |
| |
| In linear space, the sequence starts at ``base ** start`` |
| (`base` to the power of `start`) and ends with ``base ** stop`` |
| (see `endpoint` below). |
| |
| .. versionchanged:: 1.16.0 |
| Non-scalar `start` and `stop` are now supported. |
| |
| Parameters |
| ---------- |
| start : array_like |
| ``base ** start`` is the starting value of the sequence. |
| stop : array_like |
| ``base ** stop`` is the final value of the sequence, unless `endpoint` |
| is False. In that case, ``num + 1`` values are spaced over the |
| interval in log-space, of which all but the last (a sequence of |
| length `num`) are returned. |
| num : integer, optional |
| Number of samples to generate. Default is 50. |
| endpoint : boolean, optional |
| If true, `stop` is the last sample. Otherwise, it is not included. |
| Default is True. |
| base : float, optional |
| The base of the log space. The step size between the elements in |
| ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform. |
| Default is 10.0. |
| dtype : dtype |
| The type of the output array. If `dtype` is not given, infer the data |
| type from the other input arguments. |
| axis : int, optional |
| The axis in the result to store the samples. Relevant only if start |
| or stop are array-like. By default (0), the samples will be along a |
| new axis inserted at the beginning. Use -1 to get an axis at the end. |
| |
| .. versionadded:: 1.16.0 |
| |
| |
| Returns |
| ------- |
| samples : ndarray |
| `num` samples, equally spaced on a log scale. |
| |
| See Also |
| -------- |
| arange : Similar to linspace, with the step size specified instead of the |
| number of samples. Note that, when used with a float endpoint, the |
| endpoint may or may not be included. |
| linspace : Similar to logspace, but with the samples uniformly distributed |
| in linear space, instead of log space. |
| geomspace : Similar to logspace, but with endpoints specified directly. |
| |
| Notes |
| ----- |
| Logspace is equivalent to the code |
| |
| >>> y = np.linspace(start, stop, num=num, endpoint=endpoint) |
| ... # doctest: +SKIP |
| >>> power(base, y).astype(dtype) |
| ... # doctest: +SKIP |
| |
| Examples |
| -------- |
| >>> np.logspace(2.0, 3.0, num=4) |
| array([ 100. , 215.443469 , 464.15888336, 1000. ]) |
| >>> np.logspace(2.0, 3.0, num=4, endpoint=False) |
| array([ 100. , 177.827941 , 316.22776602, 562.34132519]) |
| >>> np.logspace(2.0, 3.0, num=4, base=2.0) |
| array([ 4. , 5.0396842 , 6.34960421, 8. ]) |
| |
| Graphical illustration: |
| |
| >>> import matplotlib.pyplot as plt |
| >>> N = 10 |
| >>> x1 = np.logspace(0.1, 1, N, endpoint=True) |
| >>> x2 = np.logspace(0.1, 1, N, endpoint=False) |
| >>> y = np.zeros(N) |
| >>> plt.plot(x1, y, 'o') |
| [<matplotlib.lines.Line2D object at 0x...>] |
| >>> plt.plot(x2, y + 0.5, 'o') |
| [<matplotlib.lines.Line2D object at 0x...>] |
| >>> plt.ylim([-0.5, 1]) |
| (-0.5, 1) |
| >>> plt.show() |
| |
| """ |
| y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis) |
| if dtype is None: |
| return _nx.power(base, y) |
| return _nx.power(base, y).astype(dtype, copy=False) |
| |
| |
| def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None, |
| axis=None): |
| return (start, stop) |
| |
| |
| @array_function_dispatch(_geomspace_dispatcher) |
| def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0): |
| """ |
| Return numbers spaced evenly on a log scale (a geometric progression). |
| |
| This is similar to `logspace`, but with endpoints specified directly. |
| Each output sample is a constant multiple of the previous. |
| |
| .. versionchanged:: 1.16.0 |
| Non-scalar `start` and `stop` are now supported. |
| |
| Parameters |
| ---------- |
| start : array_like |
| The starting value of the sequence. |
| stop : array_like |
| The final value of the sequence, unless `endpoint` is False. |
| In that case, ``num + 1`` values are spaced over the |
| interval in log-space, of which all but the last (a sequence of |
| length `num`) are returned. |
| num : integer, optional |
| Number of samples to generate. Default is 50. |
| endpoint : boolean, optional |
| If true, `stop` is the last sample. Otherwise, it is not included. |
| Default is True. |
| dtype : dtype |
| The type of the output array. If `dtype` is not given, infer the data |
| type from the other input arguments. |
| axis : int, optional |
| The axis in the result to store the samples. Relevant only if start |
| or stop are array-like. By default (0), the samples will be along a |
| new axis inserted at the beginning. Use -1 to get an axis at the end. |
| |
| .. versionadded:: 1.16.0 |
| |
| Returns |
| ------- |
| samples : ndarray |
| `num` samples, equally spaced on a log scale. |
| |
| See Also |
| -------- |
| logspace : Similar to geomspace, but with endpoints specified using log |
| and base. |
| linspace : Similar to geomspace, but with arithmetic instead of geometric |
| progression. |
| arange : Similar to linspace, with the step size specified instead of the |
| number of samples. |
| |
| Notes |
| ----- |
| If the inputs or dtype are complex, the output will follow a logarithmic |
| spiral in the complex plane. (There are an infinite number of spirals |
| passing through two points; the output will follow the shortest such path.) |
| |
| Examples |
| -------- |
| >>> np.geomspace(1, 1000, num=4) |
| array([ 1., 10., 100., 1000.]) |
| >>> np.geomspace(1, 1000, num=3, endpoint=False) |
| array([ 1., 10., 100.]) |
| >>> np.geomspace(1, 1000, num=4, endpoint=False) |
| array([ 1. , 5.62341325, 31.6227766 , 177.827941 ]) |
| >>> np.geomspace(1, 256, num=9) |
| array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.]) |
| |
| Note that the above may not produce exact integers: |
| |
| >>> np.geomspace(1, 256, num=9, dtype=int) |
| array([ 1, 2, 4, 7, 16, 32, 63, 127, 256]) |
| >>> np.around(np.geomspace(1, 256, num=9)).astype(int) |
| array([ 1, 2, 4, 8, 16, 32, 64, 128, 256]) |
| |
| Negative, decreasing, and complex inputs are allowed: |
| |
| >>> np.geomspace(1000, 1, num=4) |
| array([ 1000., 100., 10., 1.]) |
| >>> np.geomspace(-1000, -1, num=4) |
| array([-1000., -100., -10., -1.]) |
| >>> np.geomspace(1j, 1000j, num=4) # Straight line |
| array([ 0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j]) |
| >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle |
| array([-1.00000000+0.j , -0.70710678+0.70710678j, |
| 0.00000000+1.j , 0.70710678+0.70710678j, |
| 1.00000000+0.j ]) |
| |
| Graphical illustration of ``endpoint`` parameter: |
| |
| >>> import matplotlib.pyplot as plt |
| >>> N = 10 |
| >>> y = np.zeros(N) |
| >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o') |
| >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o') |
| >>> plt.axis([0.5, 2000, 0, 3]) |
| >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both') |
| >>> plt.show() |
| |
| """ |
| start = asanyarray(start) |
| stop = asanyarray(stop) |
| if _nx.any(start == 0) or _nx.any(stop == 0): |
| raise ValueError('Geometric sequence cannot include zero') |
| |
| dt = result_type(start, stop, float(num), _nx.zeros((), dtype)) |
| if dtype is None: |
| dtype = dt |
| else: |
| # complex to dtype('complex128'), for instance |
| dtype = _nx.dtype(dtype) |
| |
| # Promote both arguments to the same dtype in case, for instance, one is |
| # complex and another is negative and log would produce NaN otherwise. |
| # Copy since we may change things in-place further down. |
| start = start.astype(dt, copy=True) |
| stop = stop.astype(dt, copy=True) |
| |
| out_sign = _nx.ones(_nx.broadcast(start, stop).shape, dt) |
| # Avoid negligible real or imaginary parts in output by rotating to |
| # positive real, calculating, then undoing rotation |
| if _nx.issubdtype(dt, _nx.complexfloating): |
| all_imag = (start.real == 0.) & (stop.real == 0.) |
| if _nx.any(all_imag): |
| start[all_imag] = start[all_imag].imag |
| stop[all_imag] = stop[all_imag].imag |
| out_sign[all_imag] = 1j |
| |
| both_negative = (_nx.sign(start) == -1) & (_nx.sign(stop) == -1) |
| if _nx.any(both_negative): |
| _nx.negative(start, out=start, where=both_negative) |
| _nx.negative(stop, out=stop, where=both_negative) |
| _nx.negative(out_sign, out=out_sign, where=both_negative) |
| |
| log_start = _nx.log10(start) |
| log_stop = _nx.log10(stop) |
| result = out_sign * logspace(log_start, log_stop, num=num, |
| endpoint=endpoint, base=10.0, dtype=dtype) |
| if axis != 0: |
| result = _nx.moveaxis(result, 0, axis) |
| |
| return result.astype(dtype, copy=False) |
| |
| |
| #always succeed |
| def add_newdoc(place, obj, doc): |
| """ |
| Adds documentation to obj which is in module place. |
| |
| If doc is a string add it to obj as a docstring |
| |
| If doc is a tuple, then the first element is interpreted as |
| an attribute of obj and the second as the docstring |
| (method, docstring) |
| |
| If doc is a list, then each element of the list should be a |
| sequence of length two --> [(method1, docstring1), |
| (method2, docstring2), ...] |
| |
| This routine never raises an error. |
| |
| This routine cannot modify read-only docstrings, as appear |
| in new-style classes or built-in functions. Because this |
| routine never raises an error the caller must check manually |
| that the docstrings were changed. |
| """ |
| try: |
| new = getattr(__import__(place, globals(), {}, [obj]), obj) |
| if isinstance(doc, str): |
| add_docstring(new, doc.strip()) |
| elif isinstance(doc, tuple): |
| add_docstring(getattr(new, doc[0]), doc[1].strip()) |
| elif isinstance(doc, list): |
| for val in doc: |
| add_docstring(getattr(new, val[0]), val[1].strip()) |
| except Exception: |
| pass |