Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/numpy/_core/function_base.py: 35%

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

122 statements  

1import functools 

2import inspect 

3import operator 

4import types 

5import warnings 

6 

7import numpy as np 

8from numpy._core import overrides 

9from numpy._core._multiarray_umath import _array_converter 

10from numpy._core.multiarray import add_docstring 

11 

12from . import numeric as _nx 

13from .numeric import asanyarray, nan, ndim, result_type 

14 

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

16 

17 

18array_function_dispatch = functools.partial( 

19 overrides.array_function_dispatch, module='numpy') 

20 

21 

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

23 dtype=None, axis=None, *, device=None): 

24 return (start, stop) 

25 

26 

27@array_function_dispatch(_linspace_dispatcher) 

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

29 axis=0, *, device=None): 

30 """ 

31 Return evenly spaced numbers over a specified interval. 

32 

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

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

35 

36 The endpoint of the interval can optionally be excluded. 

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 axis : int, optional 

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

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

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

69 device : str, optional 

70 The device on which to place the created array. Default: None. 

71 For Array-API interoperability only, so must be ``"cpu"`` if passed. 

72 

73 .. versionadded:: 2.0.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 >>> import numpy as np 

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

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

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

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

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

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

106 

107 Graphical illustration: 

108 

109 >>> import matplotlib.pyplot as plt 

110 >>> N = 8 

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

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

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

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

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

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

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

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

119 (-0.5, 1) 

120 >>> plt.show() 

121 

122 """ 

123 num = operator.index(num) 

124 if num < 0: 

125 raise ValueError( 

126 f"Number of samples, {num}, must be non-negative." 

127 ) 

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

129 

130 conv = _array_converter(start, stop) 

131 start, stop = conv.as_arrays() 

132 dt = conv.result_type(ensure_inexact=True) 

133 

134 if dtype is None: 

135 dtype = dt 

136 integer_dtype = False 

137 else: 

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

139 

140 # Use `dtype=type(dt)` to enforce a floating point evaluation: 

141 delta = np.subtract(stop, start, dtype=type(dt)) 

142 y = _nx.arange( 

143 0, num, dtype=dt, device=device 

144 ).reshape((-1,) + (1,) * ndim(delta)) 

145 

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

147 # the multiplicant from overriding what class is produced, and thus 

148 # prevents, e.g. use of Quantities, see gh-7142. Hence, we multiply 

149 # in place only for standard scalar types. 

150 if div > 0: 

151 _mult_inplace = _nx.isscalar(delta) 

152 step = delta / div 

153 any_step_zero = ( 

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

155 if any_step_zero: 

156 # Special handling for denormal numbers, gh-5437 

157 y /= div 

158 if _mult_inplace: 

159 y *= delta 

160 else: 

161 y = y * delta 

162 elif _mult_inplace: 

163 y *= step 

164 else: 

165 y = y * step 

166 else: 

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

168 # have an undefined step 

169 step = nan 

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

171 y = y * delta 

172 

173 y += start 

174 

175 if endpoint and num > 1: 

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

177 

178 if axis != 0: 

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

180 

181 if integer_dtype: 

182 _nx.floor(y, out=y) 

183 

184 y = conv.wrap(y.astype(dtype, copy=False)) 

185 if retstep: 

186 return y, step 

187 else: 

188 return y 

189 

190 

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

192 dtype=None, axis=None): 

193 return (start, stop, base) 

194 

195 

196@array_function_dispatch(_logspace_dispatcher) 

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

198 axis=0): 

199 """ 

200 Return numbers spaced evenly on a log scale. 

201 

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

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

204 (see `endpoint` below). 

205 

206 .. versionchanged:: 1.25.0 

207 Non-scalar 'base` is now supported 

208 

209 Parameters 

210 ---------- 

211 start : array_like 

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

213 stop : array_like 

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

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

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

217 length `num`) are returned. 

218 num : integer, optional 

219 Number of samples to generate. Default is 50. 

220 endpoint : boolean, optional 

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

222 Default is True. 

223 base : array_like, optional 

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

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

226 Default is 10.0. 

227 dtype : dtype 

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

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

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

231 array of integers. 

232 axis : int, optional 

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

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

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

236 the end. 

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 >>> import numpy as np 

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

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

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

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

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

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

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

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

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

274 

275 Graphical illustration: 

276 

277 >>> import matplotlib.pyplot as plt 

278 >>> N = 10 

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

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

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

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

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

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

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

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

287 (-0.5, 1) 

288 >>> plt.show() 

289 

290 """ 

291 if not isinstance(base, (float, int)) and np.ndim(base): 

292 # If base is non-scalar, broadcast it with the others, since it 

293 # may influence how axis is interpreted. 

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

295 start, stop, base = ( 

296 np.array(a, copy=None, subok=True, ndmin=ndmax) 

297 for a in (start, stop, base) 

298 ) 

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

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

301 if dtype is None: 

302 return _nx.power(base, y) 

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

304 

305 

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

307 axis=None): 

308 return (start, stop) 

309 

310 

311@array_function_dispatch(_geomspace_dispatcher) 

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

313 """ 

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

315 

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

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

318 

319 Parameters 

320 ---------- 

321 start : array_like 

322 The starting value of the sequence. 

323 stop : array_like 

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

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

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

327 length `num`) are returned. 

328 num : integer, optional 

329 Number of samples to generate. Default is 50. 

330 endpoint : boolean, optional 

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

332 Default is True. 

333 dtype : dtype 

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

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

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

337 array of integers. 

338 axis : int, optional 

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

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

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

342 

343 Returns 

344 ------- 

345 samples : ndarray 

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

347 

348 See Also 

349 -------- 

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

351 and base. 

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

353 progression. 

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

355 number of samples. 

356 :ref:`how-to-partition` 

357 

358 Notes 

359 ----- 

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

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

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

363 

364 Examples 

365 -------- 

366 >>> import numpy as np 

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 # Allow negative real values and ensure a consistent result for complex 

430 # (including avoiding negligible real or imaginary parts in output) by 

431 # rotating start to positive real, calculating, then undoing rotation. 

432 out_sign = _nx.sign(start) 

433 start /= out_sign 

434 stop = stop / out_sign 

435 

436 log_start = _nx.log10(start) 

437 log_stop = _nx.log10(stop) 

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

439 endpoint=endpoint, base=10.0, dtype=dt) 

440 

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

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

443 if num > 0: 

444 result[0] = start 

445 if num > 1 and endpoint: 

446 result[-1] = stop 

447 

448 result *= out_sign 

449 

450 if axis != 0: 

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

452 

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

454 

455 

456def _needs_add_docstring(obj): 

457 """ 

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

459 via add_docstring. 

460 

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

462 """ 

463 Py_TPFLAGS_HEAPTYPE = 1 << 9 

464 

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

466 return False 

467 

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

469 return False 

470 

471 return True 

472 

473 

474def _add_docstring(obj, doc, warn_on_python): 

475 if warn_on_python and not _needs_add_docstring(obj): 

476 warnings.warn( 

477 f"add_newdoc was used on a pure-python object {obj}. " 

478 "Prefer to attach it directly to the source.", 

479 UserWarning, 

480 stacklevel=3) 

481 

482 doc = inspect.cleandoc(doc) 

483 

484 try: 

485 add_docstring(obj, doc) 

486 except Exception: 

487 pass 

488 

489 

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

491 """ 

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

493 

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

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

496 

497 Parameters 

498 ---------- 

499 place : str 

500 The absolute name of the module to import from 

501 obj : str | None 

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

503 function name. 

504 doc : str | tuple[str, str] | list[tuple[str, str]] 

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

506 

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

508 of `obj` and the second as the docstring to apply - 

509 ``(method, docstring)`` 

510 

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

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

513 warn_on_python : bool 

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

515 documentation to a pure-python object. 

516 

517 Notes 

518 ----- 

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

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

521 

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

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

524 routine never raises an error the caller must check manually 

525 that the docstrings were changed. 

526 

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

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

529 C-API best-practices, by: 

530 

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

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

533 will never be released 

534 

535 If possible it should be avoided. 

536 """ 

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

538 if isinstance(doc, str): 

539 if "${ARRAY_FUNCTION_LIKE}" in doc: 

540 doc = overrides.get_array_function_like_doc(new, doc) 

541 _add_docstring(new, doc, warn_on_python) 

542 elif isinstance(doc, tuple): 

543 attr, docstring = doc 

544 _add_docstring(getattr(new, attr), docstring, warn_on_python) 

545 elif isinstance(doc, list): 

546 for attr, docstring in doc: 

547 _add_docstring(getattr(new, attr), docstring, warn_on_python)