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

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._multiarray_umath import _array_converter 

11from numpy._core import overrides 

12 

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

14 

15 

16array_function_dispatch = functools.partial( 

17 overrides.array_function_dispatch, module='numpy') 

18 

19 

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

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

22 return (start, stop) 

23 

24 

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. 

30 

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

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

33 

34 The endpoint of the interval can optionally be excluded. 

35 

36 .. versionchanged:: 1.16.0 

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

38 

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)`` 

43 

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. 

66 

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. 

72 

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. 

77 

78 .. versionadded:: 2.0.0 

79 

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 

88 

89 Size of spacing between samples. 

90 

91 

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` 

101 

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) 

110 

111 Graphical illustration: 

112 

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() 

125 

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 

133 

134 conv = _array_converter(start, stop) 

135 start, stop = conv.as_arrays() 

136 dt = conv.result_type(ensure_inexact=True) 

137 

138 if dtype is None: 

139 dtype = dt 

140 integer_dtype = False 

141 else: 

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

143 

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)) 

149 

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 

177 

178 y += start 

179 

180 if endpoint and num > 1: 

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

182 

183 if axis != 0: 

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

185 

186 if integer_dtype: 

187 _nx.floor(y, out=y) 

188 

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

190 if retstep: 

191 return y, step 

192 else: 

193 return y 

194 

195 

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

197 dtype=None, axis=None): 

198 return (start, stop, base) 

199 

200 

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. 

206 

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). 

210 

211 .. versionchanged:: 1.16.0 

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

213 

214 .. versionchanged:: 1.25.0 

215 Non-scalar 'base` is now supported 

216 

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. 

245 

246 .. versionadded:: 1.16.0 

247 

248 

249 Returns 

250 ------- 

251 samples : ndarray 

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

253 

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` 

263 

264 Notes 

265 ----- 

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

267 

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

269 ... # doctest: +SKIP 

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

271 ... # doctest: +SKIP 

272 

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. ]]) 

284 

285 Graphical illustration: 

286 

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() 

299 

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) 

314 

315 

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

317 axis=None): 

318 return (start, stop) 

319 

320 

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). 

325 

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

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

328 

329 .. versionchanged:: 1.16.0 

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

331 

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. 

355 

356 .. versionadded:: 1.16.0 

357 

358 Returns 

359 ------- 

360 samples : ndarray 

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

362 

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` 

372 

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.) 

378 

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.]) 

389 

390 Note that the above may not produce exact integers: 

391 

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]) 

396 

397 Negative, decreasing, and complex inputs are allowed: 

398 

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]) 

409 

410 Graphical illustration of `endpoint` parameter: 

411 

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() 

423 

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') 

429 

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) 

436 

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) 

442 

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 

449 

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) 

454 

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 

461 

462 result *= out_sign 

463 

464 if axis != 0: 

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

466 

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

468 

469 

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. 

474 

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

476 """ 

477 Py_TPFLAGS_HEAPTYPE = 1 << 9 

478 

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

480 return False 

481 

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

483 return False 

484 

485 return True 

486 

487 

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 

500 

501 

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

503 """ 

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

505 

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. 

508 

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` 

518 

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)`` 

522 

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. 

528 

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. 

533 

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. 

538 

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: 

542 

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 

546 

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 )