Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/core/function_base.py: 52%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

124 statements  

1import functools 

2import warnings 

3import operator 

4import types 

5 

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 import overrides 

11 

12__all__ = ['logspace', 'linspace', 'geomspace'] 

13 

14 

15array_function_dispatch = functools.partial( 

16 overrides.array_function_dispatch, module='numpy') 

17 

18 

19def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None, 

20 dtype=None, axis=None): 

21 return (start, stop) 

22 

23 

24@array_function_dispatch(_linspace_dispatcher) 

25def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, 

26 axis=0): 

27 """ 

28 Return evenly spaced numbers over a specified interval. 

29 

30 Returns `num` evenly spaced samples, calculated over the 

31 interval [`start`, `stop`]. 

32 

33 The endpoint of the interval can optionally be excluded. 

34 

35 .. versionchanged:: 1.16.0 

36 Non-scalar `start` and `stop` are now supported. 

37 

38 .. versionchanged:: 1.20.0 

39 Values are rounded towards ``-inf`` instead of ``0`` when an 

40 integer ``dtype`` is specified. The old behavior can 

41 still be obtained with ``np.linspace(start, stop, num).astype(int)`` 

42 

43 Parameters 

44 ---------- 

45 start : array_like 

46 The starting value of the sequence. 

47 stop : array_like 

48 The end value of the sequence, unless `endpoint` is set to False. 

49 In that case, the sequence consists of all but the last of ``num + 1`` 

50 evenly spaced samples, so that `stop` is excluded. Note that the step 

51 size changes when `endpoint` is False. 

52 num : int, optional 

53 Number of samples to generate. Default is 50. Must be non-negative. 

54 endpoint : bool, optional 

55 If True, `stop` is the last sample. Otherwise, it is not included. 

56 Default is True. 

57 retstep : bool, optional 

58 If True, return (`samples`, `step`), where `step` is the spacing 

59 between samples. 

60 dtype : dtype, optional 

61 The type of the output array. If `dtype` is not given, the data type 

62 is inferred from `start` and `stop`. The inferred dtype will never be 

63 an integer; `float` is chosen even if the arguments would produce an 

64 array of integers. 

65 

66 .. versionadded:: 1.9.0 

67 

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. 

72 

73 .. versionadded:: 1.16.0 

74 

75 Returns 

76 ------- 

77 samples : ndarray 

78 There are `num` equally spaced samples in the closed interval 

79 ``[start, stop]`` or the half-open interval ``[start, stop)`` 

80 (depending on whether `endpoint` is True or False). 

81 step : float, optional 

82 Only returned if `retstep` is True 

83 

84 Size of spacing between samples. 

85 

86 

87 See Also 

88 -------- 

89 arange : Similar to `linspace`, but uses a step size (instead of the 

90 number of samples). 

91 geomspace : Similar to `linspace`, but with numbers spaced evenly on a log 

92 scale (a geometric progression). 

93 logspace : Similar to `geomspace`, but with the end points specified as 

94 logarithms. 

95 :ref:`how-to-partition` 

96 

97 Examples 

98 -------- 

99 >>> np.linspace(2.0, 3.0, num=5) 

100 array([2. , 2.25, 2.5 , 2.75, 3. ]) 

101 >>> np.linspace(2.0, 3.0, num=5, endpoint=False) 

102 array([2. , 2.2, 2.4, 2.6, 2.8]) 

103 >>> np.linspace(2.0, 3.0, num=5, retstep=True) 

104 (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25) 

105 

106 Graphical illustration: 

107 

108 >>> import matplotlib.pyplot as plt 

109 >>> N = 8 

110 >>> y = np.zeros(N) 

111 >>> x1 = np.linspace(0, 10, N, endpoint=True) 

112 >>> x2 = np.linspace(0, 10, N, endpoint=False) 

113 >>> plt.plot(x1, y, 'o') 

114 [<matplotlib.lines.Line2D object at 0x...>] 

115 >>> plt.plot(x2, y + 0.5, 'o') 

116 [<matplotlib.lines.Line2D object at 0x...>] 

117 >>> plt.ylim([-0.5, 1]) 

118 (-0.5, 1) 

119 >>> plt.show() 

120 

121 """ 

122 num = operator.index(num) 

123 if num < 0: 

124 raise ValueError("Number of samples, %s, must be non-negative." % num) 

125 div = (num - 1) if endpoint else num 

126 

127 # Convert float/complex array scalars to float, gh-3504 

128 # and make sure one can use variables that have an __array_interface__, gh-6634 

129 start = asanyarray(start) * 1.0 

130 stop = asanyarray(stop) * 1.0 

131 

132 dt = result_type(start, stop, float(num)) 

133 if dtype is None: 

134 dtype = dt 

135 integer_dtype = False 

136 else: 

137 integer_dtype = _nx.issubdtype(dtype, _nx.integer) 

138 

139 delta = stop - start 

140 y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta)) 

141 # In-place multiplication y *= delta/div is faster, but prevents the multiplicant 

142 # from overriding what class is produced, and thus prevents, e.g. use of Quantities, 

143 # see gh-7142. Hence, we multiply in place only for standard scalar types. 

144 if div > 0: 

145 _mult_inplace = _nx.isscalar(delta) 

146 step = delta / div 

147 any_step_zero = ( 

148 step == 0 if _mult_inplace else _nx.asanyarray(step == 0).any()) 

149 if any_step_zero: 

150 # Special handling for denormal numbers, gh-5437 

151 y /= div 

152 if _mult_inplace: 

153 y *= delta 

154 else: 

155 y = y * delta 

156 else: 

157 if _mult_inplace: 

158 y *= step 

159 else: 

160 y = y * step 

161 else: 

162 # sequences with 0 items or 1 item with endpoint=True (i.e. div <= 0) 

163 # have an undefined step 

164 step = NaN 

165 # Multiply with delta to allow possible override of output class. 

166 y = y * delta 

167 

168 y += start 

169 

170 if endpoint and num > 1: 

171 y[-1, ...] = stop 

172 

173 if axis != 0: 

174 y = _nx.moveaxis(y, 0, axis) 

175 

176 if integer_dtype: 

177 _nx.floor(y, out=y) 

178 

179 if retstep: 

180 return y.astype(dtype, copy=False), step 

181 else: 

182 return y.astype(dtype, copy=False) 

183 

184 

185def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None, 

186 dtype=None, axis=None): 

187 return (start, stop, base) 

188 

189 

190@array_function_dispatch(_logspace_dispatcher) 

191def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, 

192 axis=0): 

193 """ 

194 Return numbers spaced evenly on a log scale. 

195 

196 In linear space, the sequence starts at ``base ** start`` 

197 (`base` to the power of `start`) and ends with ``base ** stop`` 

198 (see `endpoint` below). 

199 

200 .. versionchanged:: 1.16.0 

201 Non-scalar `start` and `stop` are now supported. 

202 

203 .. versionchanged:: 1.25.0 

204 Non-scalar 'base` is now supported 

205 

206 Parameters 

207 ---------- 

208 start : array_like 

209 ``base ** start`` is the starting value of the sequence. 

210 stop : array_like 

211 ``base ** stop`` is the final value of the sequence, unless `endpoint` 

212 is False. In that case, ``num + 1`` values are spaced over the 

213 interval in log-space, of which all but the last (a sequence of 

214 length `num`) are returned. 

215 num : integer, optional 

216 Number of samples to generate. Default is 50. 

217 endpoint : boolean, optional 

218 If true, `stop` is the last sample. Otherwise, it is not included. 

219 Default is True. 

220 base : array_like, optional 

221 The base of the log space. The step size between the elements in 

222 ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform. 

223 Default is 10.0. 

224 dtype : dtype 

225 The type of the output array. If `dtype` is not given, the data type 

226 is inferred from `start` and `stop`. The inferred type will never be 

227 an integer; `float` is chosen even if the arguments would produce an 

228 array of integers. 

229 axis : int, optional 

230 The axis in the result to store the samples. Relevant only if start, 

231 stop, or base are array-like. By default (0), the samples will be 

232 along a new axis inserted at the beginning. Use -1 to get an axis at 

233 the end. 

234 

235 .. versionadded:: 1.16.0 

236 

237 

238 Returns 

239 ------- 

240 samples : ndarray 

241 `num` samples, equally spaced on a log scale. 

242 

243 See Also 

244 -------- 

245 arange : Similar to linspace, with the step size specified instead of the 

246 number of samples. Note that, when used with a float endpoint, the 

247 endpoint may or may not be included. 

248 linspace : Similar to logspace, but with the samples uniformly distributed 

249 in linear space, instead of log space. 

250 geomspace : Similar to logspace, but with endpoints specified directly. 

251 :ref:`how-to-partition` 

252 

253 Notes 

254 ----- 

255 If base is a scalar, logspace is equivalent to the code 

256 

257 >>> y = np.linspace(start, stop, num=num, endpoint=endpoint) 

258 ... # doctest: +SKIP 

259 >>> power(base, y).astype(dtype) 

260 ... # doctest: +SKIP 

261 

262 Examples 

263 -------- 

264 >>> np.logspace(2.0, 3.0, num=4) 

265 array([ 100. , 215.443469 , 464.15888336, 1000. ]) 

266 >>> np.logspace(2.0, 3.0, num=4, endpoint=False) 

267 array([100. , 177.827941 , 316.22776602, 562.34132519]) 

268 >>> np.logspace(2.0, 3.0, num=4, base=2.0) 

269 array([4. , 5.0396842 , 6.34960421, 8. ]) 

270 >>> np.logspace(2.0, 3.0, num=4, base=[2.0, 3.0], axis=-1) 

271 array([[ 4. , 5.0396842 , 6.34960421, 8. ], 

272 [ 9. , 12.98024613, 18.72075441, 27. ]]) 

273 

274 Graphical illustration: 

275 

276 >>> import matplotlib.pyplot as plt 

277 >>> N = 10 

278 >>> x1 = np.logspace(0.1, 1, N, endpoint=True) 

279 >>> x2 = np.logspace(0.1, 1, N, endpoint=False) 

280 >>> y = np.zeros(N) 

281 >>> plt.plot(x1, y, 'o') 

282 [<matplotlib.lines.Line2D object at 0x...>] 

283 >>> plt.plot(x2, y + 0.5, 'o') 

284 [<matplotlib.lines.Line2D object at 0x...>] 

285 >>> plt.ylim([-0.5, 1]) 

286 (-0.5, 1) 

287 >>> plt.show() 

288 

289 """ 

290 ndmax = np.broadcast(start, stop, base).ndim 

291 start, stop, base = ( 

292 np.array(a, copy=False, subok=True, ndmin=ndmax) 

293 for a in (start, stop, base) 

294 ) 

295 y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis) 

296 base = np.expand_dims(base, axis=axis) 

297 if dtype is None: 

298 return _nx.power(base, y) 

299 return _nx.power(base, y).astype(dtype, copy=False) 

300 

301 

302def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None, 

303 axis=None): 

304 return (start, stop) 

305 

306 

307@array_function_dispatch(_geomspace_dispatcher) 

308def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0): 

309 """ 

310 Return numbers spaced evenly on a log scale (a geometric progression). 

311 

312 This is similar to `logspace`, but with endpoints specified directly. 

313 Each output sample is a constant multiple of the previous. 

314 

315 .. versionchanged:: 1.16.0 

316 Non-scalar `start` and `stop` are now supported. 

317 

318 Parameters 

319 ---------- 

320 start : array_like 

321 The starting value of the sequence. 

322 stop : array_like 

323 The final value of the sequence, unless `endpoint` is False. 

324 In that case, ``num + 1`` values are spaced over the 

325 interval in log-space, of which all but the last (a sequence of 

326 length `num`) are returned. 

327 num : integer, optional 

328 Number of samples to generate. Default is 50. 

329 endpoint : boolean, optional 

330 If true, `stop` is the last sample. Otherwise, it is not included. 

331 Default is True. 

332 dtype : dtype 

333 The type of the output array. If `dtype` is not given, the data type 

334 is inferred from `start` and `stop`. The inferred dtype will never be 

335 an integer; `float` is chosen even if the arguments would produce an 

336 array of integers. 

337 axis : int, optional 

338 The axis in the result to store the samples. Relevant only if start 

339 or stop are array-like. By default (0), the samples will be along a 

340 new axis inserted at the beginning. Use -1 to get an axis at the end. 

341 

342 .. versionadded:: 1.16.0 

343 

344 Returns 

345 ------- 

346 samples : ndarray 

347 `num` samples, equally spaced on a log scale. 

348 

349 See Also 

350 -------- 

351 logspace : Similar to geomspace, but with endpoints specified using log 

352 and base. 

353 linspace : Similar to geomspace, but with arithmetic instead of geometric 

354 progression. 

355 arange : Similar to linspace, with the step size specified instead of the 

356 number of samples. 

357 :ref:`how-to-partition` 

358 

359 Notes 

360 ----- 

361 If the inputs or dtype are complex, the output will follow a logarithmic 

362 spiral in the complex plane. (There are an infinite number of spirals 

363 passing through two points; the output will follow the shortest such path.) 

364 

365 Examples 

366 -------- 

367 >>> np.geomspace(1, 1000, num=4) 

368 array([ 1., 10., 100., 1000.]) 

369 >>> np.geomspace(1, 1000, num=3, endpoint=False) 

370 array([ 1., 10., 100.]) 

371 >>> np.geomspace(1, 1000, num=4, endpoint=False) 

372 array([ 1. , 5.62341325, 31.6227766 , 177.827941 ]) 

373 >>> np.geomspace(1, 256, num=9) 

374 array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.]) 

375 

376 Note that the above may not produce exact integers: 

377 

378 >>> np.geomspace(1, 256, num=9, dtype=int) 

379 array([ 1, 2, 4, 7, 16, 32, 63, 127, 256]) 

380 >>> np.around(np.geomspace(1, 256, num=9)).astype(int) 

381 array([ 1, 2, 4, 8, 16, 32, 64, 128, 256]) 

382 

383 Negative, decreasing, and complex inputs are allowed: 

384 

385 >>> np.geomspace(1000, 1, num=4) 

386 array([1000., 100., 10., 1.]) 

387 >>> np.geomspace(-1000, -1, num=4) 

388 array([-1000., -100., -10., -1.]) 

389 >>> np.geomspace(1j, 1000j, num=4) # Straight line 

390 array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j]) 

391 >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle 

392 array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j, 

393 6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j, 

394 1.00000000e+00+0.00000000e+00j]) 

395 

396 Graphical illustration of `endpoint` parameter: 

397 

398 >>> import matplotlib.pyplot as plt 

399 >>> N = 10 

400 >>> y = np.zeros(N) 

401 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o') 

402 [<matplotlib.lines.Line2D object at 0x...>] 

403 >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o') 

404 [<matplotlib.lines.Line2D object at 0x...>] 

405 >>> plt.axis([0.5, 2000, 0, 3]) 

406 [0.5, 2000, 0, 3] 

407 >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both') 

408 >>> plt.show() 

409 

410 """ 

411 start = asanyarray(start) 

412 stop = asanyarray(stop) 

413 if _nx.any(start == 0) or _nx.any(stop == 0): 

414 raise ValueError('Geometric sequence cannot include zero') 

415 

416 dt = result_type(start, stop, float(num), _nx.zeros((), dtype)) 

417 if dtype is None: 

418 dtype = dt 

419 else: 

420 # complex to dtype('complex128'), for instance 

421 dtype = _nx.dtype(dtype) 

422 

423 # Promote both arguments to the same dtype in case, for instance, one is 

424 # complex and another is negative and log would produce NaN otherwise. 

425 # Copy since we may change things in-place further down. 

426 start = start.astype(dt, copy=True) 

427 stop = stop.astype(dt, copy=True) 

428 

429 out_sign = _nx.ones(_nx.broadcast(start, stop).shape, dt) 

430 # Avoid negligible real or imaginary parts in output by rotating to 

431 # positive real, calculating, then undoing rotation 

432 if _nx.issubdtype(dt, _nx.complexfloating): 

433 all_imag = (start.real == 0.) & (stop.real == 0.) 

434 if _nx.any(all_imag): 

435 start[all_imag] = start[all_imag].imag 

436 stop[all_imag] = stop[all_imag].imag 

437 out_sign[all_imag] = 1j 

438 

439 both_negative = (_nx.sign(start) == -1) & (_nx.sign(stop) == -1) 

440 if _nx.any(both_negative): 

441 _nx.negative(start, out=start, where=both_negative) 

442 _nx.negative(stop, out=stop, where=both_negative) 

443 _nx.negative(out_sign, out=out_sign, where=both_negative) 

444 

445 log_start = _nx.log10(start) 

446 log_stop = _nx.log10(stop) 

447 result = logspace(log_start, log_stop, num=num, 

448 endpoint=endpoint, base=10.0, dtype=dtype) 

449 

450 # Make sure the endpoints match the start and stop arguments. This is 

451 # necessary because np.exp(np.log(x)) is not necessarily equal to x. 

452 if num > 0: 

453 result[0] = start 

454 if num > 1 and endpoint: 

455 result[-1] = stop 

456 

457 result = out_sign * result 

458 

459 if axis != 0: 

460 result = _nx.moveaxis(result, 0, axis) 

461 

462 return result.astype(dtype, copy=False) 

463 

464 

465def _needs_add_docstring(obj): 

466 """ 

467 Returns true if the only way to set the docstring of `obj` from python is 

468 via add_docstring. 

469 

470 This function errs on the side of being overly conservative. 

471 """ 

472 Py_TPFLAGS_HEAPTYPE = 1 << 9 

473 

474 if isinstance(obj, (types.FunctionType, types.MethodType, property)): 

475 return False 

476 

477 if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE: 

478 return False 

479 

480 return True 

481 

482 

483def _add_docstring(obj, doc, warn_on_python): 

484 if warn_on_python and not _needs_add_docstring(obj): 

485 warnings.warn( 

486 "add_newdoc was used on a pure-python object {}. " 

487 "Prefer to attach it directly to the source." 

488 .format(obj), 

489 UserWarning, 

490 stacklevel=3) 

491 try: 

492 add_docstring(obj, doc) 

493 except Exception: 

494 pass 

495 

496 

497def add_newdoc(place, obj, doc, warn_on_python=True): 

498 """ 

499 Add documentation to an existing object, typically one defined in C 

500 

501 The purpose is to allow easier editing of the docstrings without requiring 

502 a re-compile. This exists primarily for internal use within numpy itself. 

503 

504 Parameters 

505 ---------- 

506 place : str 

507 The absolute name of the module to import from 

508 obj : str 

509 The name of the object to add documentation to, typically a class or 

510 function name 

511 doc : {str, Tuple[str, str], List[Tuple[str, str]]} 

512 If a string, the documentation to apply to `obj` 

513 

514 If a tuple, then the first element is interpreted as an attribute of 

515 `obj` and the second as the docstring to apply - ``(method, docstring)`` 

516 

517 If a list, then each element of the list should be a tuple of length 

518 two - ``[(method1, docstring1), (method2, docstring2), ...]`` 

519 warn_on_python : bool 

520 If True, the default, emit `UserWarning` if this is used to attach 

521 documentation to a pure-python object. 

522 

523 Notes 

524 ----- 

525 This routine never raises an error if the docstring can't be written, but 

526 will raise an error if the object being documented does not exist. 

527 

528 This routine cannot modify read-only docstrings, as appear 

529 in new-style classes or built-in functions. Because this 

530 routine never raises an error the caller must check manually 

531 that the docstrings were changed. 

532 

533 Since this function grabs the ``char *`` from a c-level str object and puts 

534 it into the ``tp_doc`` slot of the type of `obj`, it violates a number of 

535 C-API best-practices, by: 

536 

537 - modifying a `PyTypeObject` after calling `PyType_Ready` 

538 - calling `Py_INCREF` on the str and losing the reference, so the str 

539 will never be released 

540 

541 If possible it should be avoided. 

542 """ 

543 new = getattr(__import__(place, globals(), {}, [obj]), obj) 

544 if isinstance(doc, str): 

545 _add_docstring(new, doc.strip(), warn_on_python) 

546 elif isinstance(doc, tuple): 

547 attr, docstring = doc 

548 _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python) 

549 elif isinstance(doc, list): 

550 for attr, docstring in doc: 

551 _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)