Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/numpy/lib/scimath.py: 41%

70 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2Wrapper functions to more user-friendly calling of certain math functions 

3whose output data-type is different than the input data-type in certain 

4domains of the input. 

5 

6For example, for functions like `log` with branch cuts, the versions in this 

7module provide the mathematically valid answers in the complex plane:: 

8 

9 >>> import math 

10 >>> np.emath.log(-math.exp(1)) == (1+1j*math.pi) 

11 True 

12 

13Similarly, `sqrt`, other base logarithms, `power` and trig functions are 

14correctly handled. See their respective docstrings for specific examples. 

15 

16Functions 

17--------- 

18 

19.. autosummary:: 

20 :toctree: generated/ 

21 

22 sqrt 

23 log 

24 log2 

25 logn 

26 log10 

27 power 

28 arccos 

29 arcsin 

30 arctanh 

31 

32""" 

33import numpy.core.numeric as nx 

34import numpy.core.numerictypes as nt 

35from numpy.core.numeric import asarray, any 

36from numpy.core.overrides import array_function_dispatch 

37from numpy.lib.type_check import isreal 

38 

39 

40__all__ = [ 

41 'sqrt', 'log', 'log2', 'logn', 'log10', 'power', 'arccos', 'arcsin', 

42 'arctanh' 

43 ] 

44 

45 

46_ln2 = nx.log(2.0) 

47 

48 

49def _tocomplex(arr): 

50 """Convert its input `arr` to a complex array. 

51 

52 The input is returned as a complex array of the smallest type that will fit 

53 the original data: types like single, byte, short, etc. become csingle, 

54 while others become cdouble. 

55 

56 A copy of the input is always made. 

57 

58 Parameters 

59 ---------- 

60 arr : array 

61 

62 Returns 

63 ------- 

64 array 

65 An array with the same input data as the input but in complex form. 

66 

67 Examples 

68 -------- 

69 

70 First, consider an input of type short: 

71 

72 >>> a = np.array([1,2,3],np.short) 

73 

74 >>> ac = np.lib.scimath._tocomplex(a); ac 

75 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) 

76 

77 >>> ac.dtype 

78 dtype('complex64') 

79 

80 If the input is of type double, the output is correspondingly of the 

81 complex double type as well: 

82 

83 >>> b = np.array([1,2,3],np.double) 

84 

85 >>> bc = np.lib.scimath._tocomplex(b); bc 

86 array([1.+0.j, 2.+0.j, 3.+0.j]) 

87 

88 >>> bc.dtype 

89 dtype('complex128') 

90 

91 Note that even if the input was complex to begin with, a copy is still 

92 made, since the astype() method always copies: 

93 

94 >>> c = np.array([1,2,3],np.csingle) 

95 

96 >>> cc = np.lib.scimath._tocomplex(c); cc 

97 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) 

98 

99 >>> c *= 2; c 

100 array([2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64) 

101 

102 >>> cc 

103 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) 

104 """ 

105 if issubclass(arr.dtype.type, (nt.single, nt.byte, nt.short, nt.ubyte, 

106 nt.ushort, nt.csingle)): 

107 return arr.astype(nt.csingle) 

108 else: 

109 return arr.astype(nt.cdouble) 

110 

111 

112def _fix_real_lt_zero(x): 

113 """Convert `x` to complex if it has real, negative components. 

114 

115 Otherwise, output is just the array version of the input (via asarray). 

116 

117 Parameters 

118 ---------- 

119 x : array_like 

120 

121 Returns 

122 ------- 

123 array 

124 

125 Examples 

126 -------- 

127 >>> np.lib.scimath._fix_real_lt_zero([1,2]) 

128 array([1, 2]) 

129 

130 >>> np.lib.scimath._fix_real_lt_zero([-1,2]) 

131 array([-1.+0.j, 2.+0.j]) 

132 

133 """ 

134 x = asarray(x) 

135 if any(isreal(x) & (x < 0)): 

136 x = _tocomplex(x) 

137 return x 

138 

139 

140def _fix_int_lt_zero(x): 

141 """Convert `x` to double if it has real, negative components. 

142 

143 Otherwise, output is just the array version of the input (via asarray). 

144 

145 Parameters 

146 ---------- 

147 x : array_like 

148 

149 Returns 

150 ------- 

151 array 

152 

153 Examples 

154 -------- 

155 >>> np.lib.scimath._fix_int_lt_zero([1,2]) 

156 array([1, 2]) 

157 

158 >>> np.lib.scimath._fix_int_lt_zero([-1,2]) 

159 array([-1., 2.]) 

160 """ 

161 x = asarray(x) 

162 if any(isreal(x) & (x < 0)): 

163 x = x * 1.0 

164 return x 

165 

166 

167def _fix_real_abs_gt_1(x): 

168 """Convert `x` to complex if it has real components x_i with abs(x_i)>1. 

169 

170 Otherwise, output is just the array version of the input (via asarray). 

171 

172 Parameters 

173 ---------- 

174 x : array_like 

175 

176 Returns 

177 ------- 

178 array 

179 

180 Examples 

181 -------- 

182 >>> np.lib.scimath._fix_real_abs_gt_1([0,1]) 

183 array([0, 1]) 

184 

185 >>> np.lib.scimath._fix_real_abs_gt_1([0,2]) 

186 array([0.+0.j, 2.+0.j]) 

187 """ 

188 x = asarray(x) 

189 if any(isreal(x) & (abs(x) > 1)): 

190 x = _tocomplex(x) 

191 return x 

192 

193 

194def _unary_dispatcher(x): 

195 return (x,) 

196 

197 

198@array_function_dispatch(_unary_dispatcher) 

199def sqrt(x): 

200 """ 

201 Compute the square root of x. 

202 

203 For negative input elements, a complex value is returned 

204 (unlike `numpy.sqrt` which returns NaN). 

205 

206 Parameters 

207 ---------- 

208 x : array_like 

209 The input value(s). 

210 

211 Returns 

212 ------- 

213 out : ndarray or scalar 

214 The square root of `x`. If `x` was a scalar, so is `out`, 

215 otherwise an array is returned. 

216 

217 See Also 

218 -------- 

219 numpy.sqrt 

220 

221 Examples 

222 -------- 

223 For real, non-negative inputs this works just like `numpy.sqrt`: 

224 

225 >>> np.emath.sqrt(1) 

226 1.0 

227 >>> np.emath.sqrt([1, 4]) 

228 array([1., 2.]) 

229 

230 But it automatically handles negative inputs: 

231 

232 >>> np.emath.sqrt(-1) 

233 1j 

234 >>> np.emath.sqrt([-1,4]) 

235 array([0.+1.j, 2.+0.j]) 

236 

237 Different results are expected because: 

238 floating point 0.0 and -0.0 are distinct. 

239 

240 For more control, explicitly use complex() as follows: 

241 

242 >>> np.emath.sqrt(complex(-4.0, 0.0)) 

243 2j 

244 >>> np.emath.sqrt(complex(-4.0, -0.0)) 

245 -2j 

246 """ 

247 x = _fix_real_lt_zero(x) 

248 return nx.sqrt(x) 

249 

250 

251@array_function_dispatch(_unary_dispatcher) 

252def log(x): 

253 """ 

254 Compute the natural logarithm of `x`. 

255 

256 Return the "principal value" (for a description of this, see `numpy.log`) 

257 of :math:`log_e(x)`. For real `x > 0`, this is a real number (``log(0)`` 

258 returns ``-inf`` and ``log(np.inf)`` returns ``inf``). Otherwise, the 

259 complex principle value is returned. 

260 

261 Parameters 

262 ---------- 

263 x : array_like 

264 The value(s) whose log is (are) required. 

265 

266 Returns 

267 ------- 

268 out : ndarray or scalar 

269 The log of the `x` value(s). If `x` was a scalar, so is `out`, 

270 otherwise an array is returned. 

271 

272 See Also 

273 -------- 

274 numpy.log 

275 

276 Notes 

277 ----- 

278 For a log() that returns ``NAN`` when real `x < 0`, use `numpy.log` 

279 (note, however, that otherwise `numpy.log` and this `log` are identical, 

280 i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`, and, 

281 notably, the complex principle value if ``x.imag != 0``). 

282 

283 Examples 

284 -------- 

285 >>> np.emath.log(np.exp(1)) 

286 1.0 

287 

288 Negative arguments are handled "correctly" (recall that 

289 ``exp(log(x)) == x`` does *not* hold for real ``x < 0``): 

290 

291 >>> np.emath.log(-np.exp(1)) == (1 + np.pi * 1j) 

292 True 

293 

294 """ 

295 x = _fix_real_lt_zero(x) 

296 return nx.log(x) 

297 

298 

299@array_function_dispatch(_unary_dispatcher) 

300def log10(x): 

301 """ 

302 Compute the logarithm base 10 of `x`. 

303 

304 Return the "principal value" (for a description of this, see 

305 `numpy.log10`) of :math:`log_{10}(x)`. For real `x > 0`, this 

306 is a real number (``log10(0)`` returns ``-inf`` and ``log10(np.inf)`` 

307 returns ``inf``). Otherwise, the complex principle value is returned. 

308 

309 Parameters 

310 ---------- 

311 x : array_like or scalar 

312 The value(s) whose log base 10 is (are) required. 

313 

314 Returns 

315 ------- 

316 out : ndarray or scalar 

317 The log base 10 of the `x` value(s). If `x` was a scalar, so is `out`, 

318 otherwise an array object is returned. 

319 

320 See Also 

321 -------- 

322 numpy.log10 

323 

324 Notes 

325 ----- 

326 For a log10() that returns ``NAN`` when real `x < 0`, use `numpy.log10` 

327 (note, however, that otherwise `numpy.log10` and this `log10` are 

328 identical, i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`, 

329 and, notably, the complex principle value if ``x.imag != 0``). 

330 

331 Examples 

332 -------- 

333 

334 (We set the printing precision so the example can be auto-tested) 

335 

336 >>> np.set_printoptions(precision=4) 

337 

338 >>> np.emath.log10(10**1) 

339 1.0 

340 

341 >>> np.emath.log10([-10**1, -10**2, 10**2]) 

342 array([1.+1.3644j, 2.+1.3644j, 2.+0.j ]) 

343 

344 """ 

345 x = _fix_real_lt_zero(x) 

346 return nx.log10(x) 

347 

348 

349def _logn_dispatcher(n, x): 

350 return (n, x,) 

351 

352 

353@array_function_dispatch(_logn_dispatcher) 

354def logn(n, x): 

355 """ 

356 Take log base n of x. 

357 

358 If `x` contains negative inputs, the answer is computed and returned in the 

359 complex domain. 

360 

361 Parameters 

362 ---------- 

363 n : array_like 

364 The integer base(s) in which the log is taken. 

365 x : array_like 

366 The value(s) whose log base `n` is (are) required. 

367 

368 Returns 

369 ------- 

370 out : ndarray or scalar 

371 The log base `n` of the `x` value(s). If `x` was a scalar, so is 

372 `out`, otherwise an array is returned. 

373 

374 Examples 

375 -------- 

376 >>> np.set_printoptions(precision=4) 

377 

378 >>> np.emath.logn(2, [4, 8]) 

379 array([2., 3.]) 

380 >>> np.emath.logn(2, [-4, -8, 8]) 

381 array([2.+4.5324j, 3.+4.5324j, 3.+0.j ]) 

382 

383 """ 

384 x = _fix_real_lt_zero(x) 

385 n = _fix_real_lt_zero(n) 

386 return nx.log(x)/nx.log(n) 

387 

388 

389@array_function_dispatch(_unary_dispatcher) 

390def log2(x): 

391 """ 

392 Compute the logarithm base 2 of `x`. 

393 

394 Return the "principal value" (for a description of this, see 

395 `numpy.log2`) of :math:`log_2(x)`. For real `x > 0`, this is 

396 a real number (``log2(0)`` returns ``-inf`` and ``log2(np.inf)`` returns 

397 ``inf``). Otherwise, the complex principle value is returned. 

398 

399 Parameters 

400 ---------- 

401 x : array_like 

402 The value(s) whose log base 2 is (are) required. 

403 

404 Returns 

405 ------- 

406 out : ndarray or scalar 

407 The log base 2 of the `x` value(s). If `x` was a scalar, so is `out`, 

408 otherwise an array is returned. 

409 

410 See Also 

411 -------- 

412 numpy.log2 

413 

414 Notes 

415 ----- 

416 For a log2() that returns ``NAN`` when real `x < 0`, use `numpy.log2` 

417 (note, however, that otherwise `numpy.log2` and this `log2` are 

418 identical, i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`, 

419 and, notably, the complex principle value if ``x.imag != 0``). 

420 

421 Examples 

422 -------- 

423 We set the printing precision so the example can be auto-tested: 

424 

425 >>> np.set_printoptions(precision=4) 

426 

427 >>> np.emath.log2(8) 

428 3.0 

429 >>> np.emath.log2([-4, -8, 8]) 

430 array([2.+4.5324j, 3.+4.5324j, 3.+0.j ]) 

431 

432 """ 

433 x = _fix_real_lt_zero(x) 

434 return nx.log2(x) 

435 

436 

437def _power_dispatcher(x, p): 

438 return (x, p) 

439 

440 

441@array_function_dispatch(_power_dispatcher) 

442def power(x, p): 

443 """ 

444 Return x to the power p, (x**p). 

445 

446 If `x` contains negative values, the output is converted to the 

447 complex domain. 

448 

449 Parameters 

450 ---------- 

451 x : array_like 

452 The input value(s). 

453 p : array_like of ints 

454 The power(s) to which `x` is raised. If `x` contains multiple values, 

455 `p` has to either be a scalar, or contain the same number of values 

456 as `x`. In the latter case, the result is 

457 ``x[0]**p[0], x[1]**p[1], ...``. 

458 

459 Returns 

460 ------- 

461 out : ndarray or scalar 

462 The result of ``x**p``. If `x` and `p` are scalars, so is `out`, 

463 otherwise an array is returned. 

464 

465 See Also 

466 -------- 

467 numpy.power 

468 

469 Examples 

470 -------- 

471 >>> np.set_printoptions(precision=4) 

472 

473 >>> np.emath.power([2, 4], 2) 

474 array([ 4, 16]) 

475 >>> np.emath.power([2, 4], -2) 

476 array([0.25 , 0.0625]) 

477 >>> np.emath.power([-2, 4], 2) 

478 array([ 4.-0.j, 16.+0.j]) 

479 

480 """ 

481 x = _fix_real_lt_zero(x) 

482 p = _fix_int_lt_zero(p) 

483 return nx.power(x, p) 

484 

485 

486@array_function_dispatch(_unary_dispatcher) 

487def arccos(x): 

488 """ 

489 Compute the inverse cosine of x. 

490 

491 Return the "principal value" (for a description of this, see 

492 `numpy.arccos`) of the inverse cosine of `x`. For real `x` such that 

493 `abs(x) <= 1`, this is a real number in the closed interval 

494 :math:`[0, \\pi]`. Otherwise, the complex principle value is returned. 

495 

496 Parameters 

497 ---------- 

498 x : array_like or scalar 

499 The value(s) whose arccos is (are) required. 

500 

501 Returns 

502 ------- 

503 out : ndarray or scalar 

504 The inverse cosine(s) of the `x` value(s). If `x` was a scalar, so 

505 is `out`, otherwise an array object is returned. 

506 

507 See Also 

508 -------- 

509 numpy.arccos 

510 

511 Notes 

512 ----- 

513 For an arccos() that returns ``NAN`` when real `x` is not in the 

514 interval ``[-1,1]``, use `numpy.arccos`. 

515 

516 Examples 

517 -------- 

518 >>> np.set_printoptions(precision=4) 

519 

520 >>> np.emath.arccos(1) # a scalar is returned 

521 0.0 

522 

523 >>> np.emath.arccos([1,2]) 

524 array([0.-0.j , 0.-1.317j]) 

525 

526 """ 

527 x = _fix_real_abs_gt_1(x) 

528 return nx.arccos(x) 

529 

530 

531@array_function_dispatch(_unary_dispatcher) 

532def arcsin(x): 

533 """ 

534 Compute the inverse sine of x. 

535 

536 Return the "principal value" (for a description of this, see 

537 `numpy.arcsin`) of the inverse sine of `x`. For real `x` such that 

538 `abs(x) <= 1`, this is a real number in the closed interval 

539 :math:`[-\\pi/2, \\pi/2]`. Otherwise, the complex principle value is 

540 returned. 

541 

542 Parameters 

543 ---------- 

544 x : array_like or scalar 

545 The value(s) whose arcsin is (are) required. 

546 

547 Returns 

548 ------- 

549 out : ndarray or scalar 

550 The inverse sine(s) of the `x` value(s). If `x` was a scalar, so 

551 is `out`, otherwise an array object is returned. 

552 

553 See Also 

554 -------- 

555 numpy.arcsin 

556 

557 Notes 

558 ----- 

559 For an arcsin() that returns ``NAN`` when real `x` is not in the 

560 interval ``[-1,1]``, use `numpy.arcsin`. 

561 

562 Examples 

563 -------- 

564 >>> np.set_printoptions(precision=4) 

565 

566 >>> np.emath.arcsin(0) 

567 0.0 

568 

569 >>> np.emath.arcsin([0,1]) 

570 array([0. , 1.5708]) 

571 

572 """ 

573 x = _fix_real_abs_gt_1(x) 

574 return nx.arcsin(x) 

575 

576 

577@array_function_dispatch(_unary_dispatcher) 

578def arctanh(x): 

579 """ 

580 Compute the inverse hyperbolic tangent of `x`. 

581 

582 Return the "principal value" (for a description of this, see 

583 `numpy.arctanh`) of ``arctanh(x)``. For real `x` such that 

584 ``abs(x) < 1``, this is a real number. If `abs(x) > 1`, or if `x` is 

585 complex, the result is complex. Finally, `x = 1` returns``inf`` and 

586 ``x=-1`` returns ``-inf``. 

587 

588 Parameters 

589 ---------- 

590 x : array_like 

591 The value(s) whose arctanh is (are) required. 

592 

593 Returns 

594 ------- 

595 out : ndarray or scalar 

596 The inverse hyperbolic tangent(s) of the `x` value(s). If `x` was 

597 a scalar so is `out`, otherwise an array is returned. 

598 

599 

600 See Also 

601 -------- 

602 numpy.arctanh 

603 

604 Notes 

605 ----- 

606 For an arctanh() that returns ``NAN`` when real `x` is not in the 

607 interval ``(-1,1)``, use `numpy.arctanh` (this latter, however, does 

608 return +/-inf for ``x = +/-1``). 

609 

610 Examples 

611 -------- 

612 >>> np.set_printoptions(precision=4) 

613 

614 >>> from numpy.testing import suppress_warnings 

615 >>> with suppress_warnings() as sup: 

616 ... sup.filter(RuntimeWarning) 

617 ... np.emath.arctanh(np.eye(2)) 

618 array([[inf, 0.], 

619 [ 0., inf]]) 

620 >>> np.emath.arctanh([1j]) 

621 array([0.+0.7854j]) 

622 

623 """ 

624 x = _fix_real_abs_gt_1(x) 

625 return nx.arctanh(x)