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
« 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.
6For example, for functions like `log` with branch cuts, the versions in this
7module provide the mathematically valid answers in the complex plane::
9 >>> import math
10 >>> np.emath.log(-math.exp(1)) == (1+1j*math.pi)
11 True
13Similarly, `sqrt`, other base logarithms, `power` and trig functions are
14correctly handled. See their respective docstrings for specific examples.
16Functions
17---------
19.. autosummary::
20 :toctree: generated/
22 sqrt
23 log
24 log2
25 logn
26 log10
27 power
28 arccos
29 arcsin
30 arctanh
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
40__all__ = [
41 'sqrt', 'log', 'log2', 'logn', 'log10', 'power', 'arccos', 'arcsin',
42 'arctanh'
43 ]
46_ln2 = nx.log(2.0)
49def _tocomplex(arr):
50 """Convert its input `arr` to a complex array.
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.
56 A copy of the input is always made.
58 Parameters
59 ----------
60 arr : array
62 Returns
63 -------
64 array
65 An array with the same input data as the input but in complex form.
67 Examples
68 --------
70 First, consider an input of type short:
72 >>> a = np.array([1,2,3],np.short)
74 >>> ac = np.lib.scimath._tocomplex(a); ac
75 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
77 >>> ac.dtype
78 dtype('complex64')
80 If the input is of type double, the output is correspondingly of the
81 complex double type as well:
83 >>> b = np.array([1,2,3],np.double)
85 >>> bc = np.lib.scimath._tocomplex(b); bc
86 array([1.+0.j, 2.+0.j, 3.+0.j])
88 >>> bc.dtype
89 dtype('complex128')
91 Note that even if the input was complex to begin with, a copy is still
92 made, since the astype() method always copies:
94 >>> c = np.array([1,2,3],np.csingle)
96 >>> cc = np.lib.scimath._tocomplex(c); cc
97 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
99 >>> c *= 2; c
100 array([2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64)
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)
112def _fix_real_lt_zero(x):
113 """Convert `x` to complex if it has real, negative components.
115 Otherwise, output is just the array version of the input (via asarray).
117 Parameters
118 ----------
119 x : array_like
121 Returns
122 -------
123 array
125 Examples
126 --------
127 >>> np.lib.scimath._fix_real_lt_zero([1,2])
128 array([1, 2])
130 >>> np.lib.scimath._fix_real_lt_zero([-1,2])
131 array([-1.+0.j, 2.+0.j])
133 """
134 x = asarray(x)
135 if any(isreal(x) & (x < 0)):
136 x = _tocomplex(x)
137 return x
140def _fix_int_lt_zero(x):
141 """Convert `x` to double if it has real, negative components.
143 Otherwise, output is just the array version of the input (via asarray).
145 Parameters
146 ----------
147 x : array_like
149 Returns
150 -------
151 array
153 Examples
154 --------
155 >>> np.lib.scimath._fix_int_lt_zero([1,2])
156 array([1, 2])
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
167def _fix_real_abs_gt_1(x):
168 """Convert `x` to complex if it has real components x_i with abs(x_i)>1.
170 Otherwise, output is just the array version of the input (via asarray).
172 Parameters
173 ----------
174 x : array_like
176 Returns
177 -------
178 array
180 Examples
181 --------
182 >>> np.lib.scimath._fix_real_abs_gt_1([0,1])
183 array([0, 1])
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
194def _unary_dispatcher(x):
195 return (x,)
198@array_function_dispatch(_unary_dispatcher)
199def sqrt(x):
200 """
201 Compute the square root of x.
203 For negative input elements, a complex value is returned
204 (unlike `numpy.sqrt` which returns NaN).
206 Parameters
207 ----------
208 x : array_like
209 The input value(s).
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.
217 See Also
218 --------
219 numpy.sqrt
221 Examples
222 --------
223 For real, non-negative inputs this works just like `numpy.sqrt`:
225 >>> np.emath.sqrt(1)
226 1.0
227 >>> np.emath.sqrt([1, 4])
228 array([1., 2.])
230 But it automatically handles negative inputs:
232 >>> np.emath.sqrt(-1)
233 1j
234 >>> np.emath.sqrt([-1,4])
235 array([0.+1.j, 2.+0.j])
237 Different results are expected because:
238 floating point 0.0 and -0.0 are distinct.
240 For more control, explicitly use complex() as follows:
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)
251@array_function_dispatch(_unary_dispatcher)
252def log(x):
253 """
254 Compute the natural logarithm of `x`.
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.
261 Parameters
262 ----------
263 x : array_like
264 The value(s) whose log is (are) required.
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.
272 See Also
273 --------
274 numpy.log
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``).
283 Examples
284 --------
285 >>> np.emath.log(np.exp(1))
286 1.0
288 Negative arguments are handled "correctly" (recall that
289 ``exp(log(x)) == x`` does *not* hold for real ``x < 0``):
291 >>> np.emath.log(-np.exp(1)) == (1 + np.pi * 1j)
292 True
294 """
295 x = _fix_real_lt_zero(x)
296 return nx.log(x)
299@array_function_dispatch(_unary_dispatcher)
300def log10(x):
301 """
302 Compute the logarithm base 10 of `x`.
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.
309 Parameters
310 ----------
311 x : array_like or scalar
312 The value(s) whose log base 10 is (are) required.
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.
320 See Also
321 --------
322 numpy.log10
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``).
331 Examples
332 --------
334 (We set the printing precision so the example can be auto-tested)
336 >>> np.set_printoptions(precision=4)
338 >>> np.emath.log10(10**1)
339 1.0
341 >>> np.emath.log10([-10**1, -10**2, 10**2])
342 array([1.+1.3644j, 2.+1.3644j, 2.+0.j ])
344 """
345 x = _fix_real_lt_zero(x)
346 return nx.log10(x)
349def _logn_dispatcher(n, x):
350 return (n, x,)
353@array_function_dispatch(_logn_dispatcher)
354def logn(n, x):
355 """
356 Take log base n of x.
358 If `x` contains negative inputs, the answer is computed and returned in the
359 complex domain.
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.
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.
374 Examples
375 --------
376 >>> np.set_printoptions(precision=4)
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 ])
383 """
384 x = _fix_real_lt_zero(x)
385 n = _fix_real_lt_zero(n)
386 return nx.log(x)/nx.log(n)
389@array_function_dispatch(_unary_dispatcher)
390def log2(x):
391 """
392 Compute the logarithm base 2 of `x`.
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.
399 Parameters
400 ----------
401 x : array_like
402 The value(s) whose log base 2 is (are) required.
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.
410 See Also
411 --------
412 numpy.log2
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``).
421 Examples
422 --------
423 We set the printing precision so the example can be auto-tested:
425 >>> np.set_printoptions(precision=4)
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 ])
432 """
433 x = _fix_real_lt_zero(x)
434 return nx.log2(x)
437def _power_dispatcher(x, p):
438 return (x, p)
441@array_function_dispatch(_power_dispatcher)
442def power(x, p):
443 """
444 Return x to the power p, (x**p).
446 If `x` contains negative values, the output is converted to the
447 complex domain.
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], ...``.
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.
465 See Also
466 --------
467 numpy.power
469 Examples
470 --------
471 >>> np.set_printoptions(precision=4)
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])
480 """
481 x = _fix_real_lt_zero(x)
482 p = _fix_int_lt_zero(p)
483 return nx.power(x, p)
486@array_function_dispatch(_unary_dispatcher)
487def arccos(x):
488 """
489 Compute the inverse cosine of x.
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.
496 Parameters
497 ----------
498 x : array_like or scalar
499 The value(s) whose arccos is (are) required.
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.
507 See Also
508 --------
509 numpy.arccos
511 Notes
512 -----
513 For an arccos() that returns ``NAN`` when real `x` is not in the
514 interval ``[-1,1]``, use `numpy.arccos`.
516 Examples
517 --------
518 >>> np.set_printoptions(precision=4)
520 >>> np.emath.arccos(1) # a scalar is returned
521 0.0
523 >>> np.emath.arccos([1,2])
524 array([0.-0.j , 0.-1.317j])
526 """
527 x = _fix_real_abs_gt_1(x)
528 return nx.arccos(x)
531@array_function_dispatch(_unary_dispatcher)
532def arcsin(x):
533 """
534 Compute the inverse sine of x.
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.
542 Parameters
543 ----------
544 x : array_like or scalar
545 The value(s) whose arcsin is (are) required.
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.
553 See Also
554 --------
555 numpy.arcsin
557 Notes
558 -----
559 For an arcsin() that returns ``NAN`` when real `x` is not in the
560 interval ``[-1,1]``, use `numpy.arcsin`.
562 Examples
563 --------
564 >>> np.set_printoptions(precision=4)
566 >>> np.emath.arcsin(0)
567 0.0
569 >>> np.emath.arcsin([0,1])
570 array([0. , 1.5708])
572 """
573 x = _fix_real_abs_gt_1(x)
574 return nx.arcsin(x)
577@array_function_dispatch(_unary_dispatcher)
578def arctanh(x):
579 """
580 Compute the inverse hyperbolic tangent of `x`.
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``.
588 Parameters
589 ----------
590 x : array_like
591 The value(s) whose arctanh is (are) required.
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.
600 See Also
601 --------
602 numpy.arctanh
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``).
610 Examples
611 --------
612 >>> np.set_printoptions(precision=4)
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])
623 """
624 x = _fix_real_abs_gt_1(x)
625 return nx.arctanh(x)