function_base.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. from __future__ import division, absolute_import, print_function
  2. import functools
  3. import warnings
  4. import operator
  5. from . import numeric as _nx
  6. from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS,
  7. TooHardError, asanyarray, ndim)
  8. from numpy.core.multiarray import add_docstring
  9. from numpy.core import overrides
  10. __all__ = ['logspace', 'linspace', 'geomspace']
  11. array_function_dispatch = functools.partial(
  12. overrides.array_function_dispatch, module='numpy')
  13. def _index_deprecate(i, stacklevel=2):
  14. try:
  15. i = operator.index(i)
  16. except TypeError:
  17. msg = ("object of type {} cannot be safely interpreted as "
  18. "an integer.".format(type(i)))
  19. i = int(i)
  20. stacklevel += 1
  21. warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel)
  22. return i
  23. def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None,
  24. dtype=None, axis=None):
  25. return (start, stop)
  26. @array_function_dispatch(_linspace_dispatcher)
  27. def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
  28. axis=0):
  29. """
  30. Return evenly spaced numbers over a specified interval.
  31. Returns `num` evenly spaced samples, calculated over the
  32. interval [`start`, `stop`].
  33. The endpoint of the interval can optionally be excluded.
  34. .. versionchanged:: 1.16.0
  35. Non-scalar `start` and `stop` are now supported.
  36. Parameters
  37. ----------
  38. start : array_like
  39. The starting value of the sequence.
  40. stop : array_like
  41. The end value of the sequence, unless `endpoint` is set to False.
  42. In that case, the sequence consists of all but the last of ``num + 1``
  43. evenly spaced samples, so that `stop` is excluded. Note that the step
  44. size changes when `endpoint` is False.
  45. num : int, optional
  46. Number of samples to generate. Default is 50. Must be non-negative.
  47. endpoint : bool, optional
  48. If True, `stop` is the last sample. Otherwise, it is not included.
  49. Default is True.
  50. retstep : bool, optional
  51. If True, return (`samples`, `step`), where `step` is the spacing
  52. between samples.
  53. dtype : dtype, optional
  54. The type of the output array. If `dtype` is not given, infer the data
  55. type from the other input arguments.
  56. .. versionadded:: 1.9.0
  57. axis : int, optional
  58. The axis in the result to store the samples. Relevant only if start
  59. or stop are array-like. By default (0), the samples will be along a
  60. new axis inserted at the beginning. Use -1 to get an axis at the end.
  61. .. versionadded:: 1.16.0
  62. Returns
  63. -------
  64. samples : ndarray
  65. There are `num` equally spaced samples in the closed interval
  66. ``[start, stop]`` or the half-open interval ``[start, stop)``
  67. (depending on whether `endpoint` is True or False).
  68. step : float, optional
  69. Only returned if `retstep` is True
  70. Size of spacing between samples.
  71. See Also
  72. --------
  73. arange : Similar to `linspace`, but uses a step size (instead of the
  74. number of samples).
  75. geomspace : Similar to `linspace`, but with numbers spaced evenly on a log
  76. scale (a geometric progression).
  77. logspace : Similar to `geomspace`, but with the end points specified as
  78. logarithms.
  79. Examples
  80. --------
  81. >>> np.linspace(2.0, 3.0, num=5)
  82. array([ 2. , 2.25, 2.5 , 2.75, 3. ])
  83. >>> np.linspace(2.0, 3.0, num=5, endpoint=False)
  84. array([ 2. , 2.2, 2.4, 2.6, 2.8])
  85. >>> np.linspace(2.0, 3.0, num=5, retstep=True)
  86. (array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
  87. Graphical illustration:
  88. >>> import matplotlib.pyplot as plt
  89. >>> N = 8
  90. >>> y = np.zeros(N)
  91. >>> x1 = np.linspace(0, 10, N, endpoint=True)
  92. >>> x2 = np.linspace(0, 10, N, endpoint=False)
  93. >>> plt.plot(x1, y, 'o')
  94. [<matplotlib.lines.Line2D object at 0x...>]
  95. >>> plt.plot(x2, y + 0.5, 'o')
  96. [<matplotlib.lines.Line2D object at 0x...>]
  97. >>> plt.ylim([-0.5, 1])
  98. (-0.5, 1)
  99. >>> plt.show()
  100. """
  101. # 2016-02-25, 1.12
  102. num = _index_deprecate(num)
  103. if num < 0:
  104. raise ValueError("Number of samples, %s, must be non-negative." % num)
  105. div = (num - 1) if endpoint else num
  106. # Convert float/complex array scalars to float, gh-3504
  107. # and make sure one can use variables that have an __array_interface__, gh-6634
  108. start = asanyarray(start) * 1.0
  109. stop = asanyarray(stop) * 1.0
  110. dt = result_type(start, stop, float(num))
  111. if dtype is None:
  112. dtype = dt
  113. delta = stop - start
  114. y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta))
  115. # In-place multiplication y *= delta/div is faster, but prevents the multiplicant
  116. # from overriding what class is produced, and thus prevents, e.g. use of Quantities,
  117. # see gh-7142. Hence, we multiply in place only for standard scalar types.
  118. _mult_inplace = _nx.isscalar(delta)
  119. if num > 1:
  120. step = delta / div
  121. if _nx.any(step == 0):
  122. # Special handling for denormal numbers, gh-5437
  123. y /= div
  124. if _mult_inplace:
  125. y *= delta
  126. else:
  127. y = y * delta
  128. else:
  129. if _mult_inplace:
  130. y *= step
  131. else:
  132. y = y * step
  133. else:
  134. # 0 and 1 item long sequences have an undefined step
  135. step = NaN
  136. # Multiply with delta to allow possible override of output class.
  137. y = y * delta
  138. y += start
  139. if endpoint and num > 1:
  140. y[-1] = stop
  141. if axis != 0:
  142. y = _nx.moveaxis(y, 0, axis)
  143. if retstep:
  144. return y.astype(dtype, copy=False), step
  145. else:
  146. return y.astype(dtype, copy=False)
  147. def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None,
  148. dtype=None, axis=None):
  149. return (start, stop)
  150. @array_function_dispatch(_logspace_dispatcher)
  151. def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
  152. axis=0):
  153. """
  154. Return numbers spaced evenly on a log scale.
  155. In linear space, the sequence starts at ``base ** start``
  156. (`base` to the power of `start`) and ends with ``base ** stop``
  157. (see `endpoint` below).
  158. .. versionchanged:: 1.16.0
  159. Non-scalar `start` and `stop` are now supported.
  160. Parameters
  161. ----------
  162. start : array_like
  163. ``base ** start`` is the starting value of the sequence.
  164. stop : array_like
  165. ``base ** stop`` is the final value of the sequence, unless `endpoint`
  166. is False. In that case, ``num + 1`` values are spaced over the
  167. interval in log-space, of which all but the last (a sequence of
  168. length `num`) are returned.
  169. num : integer, optional
  170. Number of samples to generate. Default is 50.
  171. endpoint : boolean, optional
  172. If true, `stop` is the last sample. Otherwise, it is not included.
  173. Default is True.
  174. base : float, optional
  175. The base of the log space. The step size between the elements in
  176. ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform.
  177. Default is 10.0.
  178. dtype : dtype
  179. The type of the output array. If `dtype` is not given, infer the data
  180. type from the other input arguments.
  181. axis : int, optional
  182. The axis in the result to store the samples. Relevant only if start
  183. or stop are array-like. By default (0), the samples will be along a
  184. new axis inserted at the beginning. Use -1 to get an axis at the end.
  185. .. versionadded:: 1.16.0
  186. Returns
  187. -------
  188. samples : ndarray
  189. `num` samples, equally spaced on a log scale.
  190. See Also
  191. --------
  192. arange : Similar to linspace, with the step size specified instead of the
  193. number of samples. Note that, when used with a float endpoint, the
  194. endpoint may or may not be included.
  195. linspace : Similar to logspace, but with the samples uniformly distributed
  196. in linear space, instead of log space.
  197. geomspace : Similar to logspace, but with endpoints specified directly.
  198. Notes
  199. -----
  200. Logspace is equivalent to the code
  201. >>> y = np.linspace(start, stop, num=num, endpoint=endpoint)
  202. ... # doctest: +SKIP
  203. >>> power(base, y).astype(dtype)
  204. ... # doctest: +SKIP
  205. Examples
  206. --------
  207. >>> np.logspace(2.0, 3.0, num=4)
  208. array([ 100. , 215.443469 , 464.15888336, 1000. ])
  209. >>> np.logspace(2.0, 3.0, num=4, endpoint=False)
  210. array([ 100. , 177.827941 , 316.22776602, 562.34132519])
  211. >>> np.logspace(2.0, 3.0, num=4, base=2.0)
  212. array([ 4. , 5.0396842 , 6.34960421, 8. ])
  213. Graphical illustration:
  214. >>> import matplotlib.pyplot as plt
  215. >>> N = 10
  216. >>> x1 = np.logspace(0.1, 1, N, endpoint=True)
  217. >>> x2 = np.logspace(0.1, 1, N, endpoint=False)
  218. >>> y = np.zeros(N)
  219. >>> plt.plot(x1, y, 'o')
  220. [<matplotlib.lines.Line2D object at 0x...>]
  221. >>> plt.plot(x2, y + 0.5, 'o')
  222. [<matplotlib.lines.Line2D object at 0x...>]
  223. >>> plt.ylim([-0.5, 1])
  224. (-0.5, 1)
  225. >>> plt.show()
  226. """
  227. y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis)
  228. if dtype is None:
  229. return _nx.power(base, y)
  230. return _nx.power(base, y).astype(dtype, copy=False)
  231. def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None,
  232. axis=None):
  233. return (start, stop)
  234. @array_function_dispatch(_geomspace_dispatcher)
  235. def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
  236. """
  237. Return numbers spaced evenly on a log scale (a geometric progression).
  238. This is similar to `logspace`, but with endpoints specified directly.
  239. Each output sample is a constant multiple of the previous.
  240. .. versionchanged:: 1.16.0
  241. Non-scalar `start` and `stop` are now supported.
  242. Parameters
  243. ----------
  244. start : array_like
  245. The starting value of the sequence.
  246. stop : array_like
  247. The final value of the sequence, unless `endpoint` is False.
  248. In that case, ``num + 1`` values are spaced over the
  249. interval in log-space, of which all but the last (a sequence of
  250. length `num`) are returned.
  251. num : integer, optional
  252. Number of samples to generate. Default is 50.
  253. endpoint : boolean, optional
  254. If true, `stop` is the last sample. Otherwise, it is not included.
  255. Default is True.
  256. dtype : dtype
  257. The type of the output array. If `dtype` is not given, infer the data
  258. type from the other input arguments.
  259. axis : int, optional
  260. The axis in the result to store the samples. Relevant only if start
  261. or stop are array-like. By default (0), the samples will be along a
  262. new axis inserted at the beginning. Use -1 to get an axis at the end.
  263. .. versionadded:: 1.16.0
  264. Returns
  265. -------
  266. samples : ndarray
  267. `num` samples, equally spaced on a log scale.
  268. See Also
  269. --------
  270. logspace : Similar to geomspace, but with endpoints specified using log
  271. and base.
  272. linspace : Similar to geomspace, but with arithmetic instead of geometric
  273. progression.
  274. arange : Similar to linspace, with the step size specified instead of the
  275. number of samples.
  276. Notes
  277. -----
  278. If the inputs or dtype are complex, the output will follow a logarithmic
  279. spiral in the complex plane. (There are an infinite number of spirals
  280. passing through two points; the output will follow the shortest such path.)
  281. Examples
  282. --------
  283. >>> np.geomspace(1, 1000, num=4)
  284. array([ 1., 10., 100., 1000.])
  285. >>> np.geomspace(1, 1000, num=3, endpoint=False)
  286. array([ 1., 10., 100.])
  287. >>> np.geomspace(1, 1000, num=4, endpoint=False)
  288. array([ 1. , 5.62341325, 31.6227766 , 177.827941 ])
  289. >>> np.geomspace(1, 256, num=9)
  290. array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.])
  291. Note that the above may not produce exact integers:
  292. >>> np.geomspace(1, 256, num=9, dtype=int)
  293. array([ 1, 2, 4, 7, 16, 32, 63, 127, 256])
  294. >>> np.around(np.geomspace(1, 256, num=9)).astype(int)
  295. array([ 1, 2, 4, 8, 16, 32, 64, 128, 256])
  296. Negative, decreasing, and complex inputs are allowed:
  297. >>> np.geomspace(1000, 1, num=4)
  298. array([ 1000., 100., 10., 1.])
  299. >>> np.geomspace(-1000, -1, num=4)
  300. array([-1000., -100., -10., -1.])
  301. >>> np.geomspace(1j, 1000j, num=4) # Straight line
  302. array([ 0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
  303. >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle
  304. array([-1.00000000+0.j , -0.70710678+0.70710678j,
  305. 0.00000000+1.j , 0.70710678+0.70710678j,
  306. 1.00000000+0.j ])
  307. Graphical illustration of ``endpoint`` parameter:
  308. >>> import matplotlib.pyplot as plt
  309. >>> N = 10
  310. >>> y = np.zeros(N)
  311. >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
  312. >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
  313. >>> plt.axis([0.5, 2000, 0, 3])
  314. >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
  315. >>> plt.show()
  316. """
  317. start = asanyarray(start)
  318. stop = asanyarray(stop)
  319. if _nx.any(start == 0) or _nx.any(stop == 0):
  320. raise ValueError('Geometric sequence cannot include zero')
  321. dt = result_type(start, stop, float(num), _nx.zeros((), dtype))
  322. if dtype is None:
  323. dtype = dt
  324. else:
  325. # complex to dtype('complex128'), for instance
  326. dtype = _nx.dtype(dtype)
  327. # Promote both arguments to the same dtype in case, for instance, one is
  328. # complex and another is negative and log would produce NaN otherwise.
  329. # Copy since we may change things in-place further down.
  330. start = start.astype(dt, copy=True)
  331. stop = stop.astype(dt, copy=True)
  332. out_sign = _nx.ones(_nx.broadcast(start, stop).shape, dt)
  333. # Avoid negligible real or imaginary parts in output by rotating to
  334. # positive real, calculating, then undoing rotation
  335. if _nx.issubdtype(dt, _nx.complexfloating):
  336. all_imag = (start.real == 0.) & (stop.real == 0.)
  337. if _nx.any(all_imag):
  338. start[all_imag] = start[all_imag].imag
  339. stop[all_imag] = stop[all_imag].imag
  340. out_sign[all_imag] = 1j
  341. both_negative = (_nx.sign(start) == -1) & (_nx.sign(stop) == -1)
  342. if _nx.any(both_negative):
  343. _nx.negative(start, out=start, where=both_negative)
  344. _nx.negative(stop, out=stop, where=both_negative)
  345. _nx.negative(out_sign, out=out_sign, where=both_negative)
  346. log_start = _nx.log10(start)
  347. log_stop = _nx.log10(stop)
  348. result = out_sign * logspace(log_start, log_stop, num=num,
  349. endpoint=endpoint, base=10.0, dtype=dtype)
  350. if axis != 0:
  351. result = _nx.moveaxis(result, 0, axis)
  352. return result.astype(dtype, copy=False)
  353. #always succeed
  354. def _add_docstring(obj, doc):
  355. try:
  356. add_docstring(obj, doc)
  357. except Exception:
  358. pass
  359. def add_newdoc(place, obj, doc):
  360. """
  361. Adds documentation to obj which is in module place.
  362. If doc is a string add it to obj as a docstring
  363. If doc is a tuple, then the first element is interpreted as
  364. an attribute of obj and the second as the docstring
  365. (method, docstring)
  366. If doc is a list, then each element of the list should be a
  367. sequence of length two --> [(method1, docstring1),
  368. (method2, docstring2), ...]
  369. This routine never raises an error if the docstring can't be written, but
  370. will raise an error if the object being documented does not exist.
  371. This routine cannot modify read-only docstrings, as appear
  372. in new-style classes or built-in functions. Because this
  373. routine never raises an error the caller must check manually
  374. that the docstrings were changed.
  375. """
  376. new = getattr(__import__(place, globals(), {}, [obj]), obj)
  377. if isinstance(doc, str):
  378. _add_docstring(new, doc.strip())
  379. elif isinstance(doc, tuple):
  380. _add_docstring(getattr(new, doc[0]), doc[1].strip())
  381. elif isinstance(doc, list):
  382. for val in doc:
  383. _add_docstring(getattr(new, val[0]), val[1].strip())