Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/numpy/lib/scimath.py : 38%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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 >>> from numpy.lib import scimath
11 >>> scimath.log(-math.exp(1)) == (1+1j*math.pi)
12 True
14Similarly, `sqrt`, other base logarithms, `power` and trig functions are
15correctly handled. See their respective docstrings for specific examples.
17"""
18import numpy.core.numeric as nx
19import numpy.core.numerictypes as nt
20from numpy.core.numeric import asarray, any
21from numpy.core.overrides import array_function_dispatch
22from numpy.lib.type_check import isreal
25__all__ = [
26 'sqrt', 'log', 'log2', 'logn', 'log10', 'power', 'arccos', 'arcsin',
27 'arctanh'
28 ]
31_ln2 = nx.log(2.0)
34def _tocomplex(arr):
35 """Convert its input `arr` to a complex array.
37 The input is returned as a complex array of the smallest type that will fit
38 the original data: types like single, byte, short, etc. become csingle,
39 while others become cdouble.
41 A copy of the input is always made.
43 Parameters
44 ----------
45 arr : array
47 Returns
48 -------
49 array
50 An array with the same input data as the input but in complex form.
52 Examples
53 --------
55 First, consider an input of type short:
57 >>> a = np.array([1,2,3],np.short)
59 >>> ac = np.lib.scimath._tocomplex(a); ac
60 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
62 >>> ac.dtype
63 dtype('complex64')
65 If the input is of type double, the output is correspondingly of the
66 complex double type as well:
68 >>> b = np.array([1,2,3],np.double)
70 >>> bc = np.lib.scimath._tocomplex(b); bc
71 array([1.+0.j, 2.+0.j, 3.+0.j])
73 >>> bc.dtype
74 dtype('complex128')
76 Note that even if the input was complex to begin with, a copy is still
77 made, since the astype() method always copies:
79 >>> c = np.array([1,2,3],np.csingle)
81 >>> cc = np.lib.scimath._tocomplex(c); cc
82 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
84 >>> c *= 2; c
85 array([2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64)
87 >>> cc
88 array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
89 """
90 if issubclass(arr.dtype.type, (nt.single, nt.byte, nt.short, nt.ubyte,
91 nt.ushort, nt.csingle)):
92 return arr.astype(nt.csingle)
93 else:
94 return arr.astype(nt.cdouble)
97def _fix_real_lt_zero(x):
98 """Convert `x` to complex if it has real, negative components.
100 Otherwise, output is just the array version of the input (via asarray).
102 Parameters
103 ----------
104 x : array_like
106 Returns
107 -------
108 array
110 Examples
111 --------
112 >>> np.lib.scimath._fix_real_lt_zero([1,2])
113 array([1, 2])
115 >>> np.lib.scimath._fix_real_lt_zero([-1,2])
116 array([-1.+0.j, 2.+0.j])
118 """
119 x = asarray(x)
120 if any(isreal(x) & (x < 0)):
121 x = _tocomplex(x)
122 return x
125def _fix_int_lt_zero(x):
126 """Convert `x` to double if it has real, negative components.
128 Otherwise, output is just the array version of the input (via asarray).
130 Parameters
131 ----------
132 x : array_like
134 Returns
135 -------
136 array
138 Examples
139 --------
140 >>> np.lib.scimath._fix_int_lt_zero([1,2])
141 array([1, 2])
143 >>> np.lib.scimath._fix_int_lt_zero([-1,2])
144 array([-1., 2.])
145 """
146 x = asarray(x)
147 if any(isreal(x) & (x < 0)):
148 x = x * 1.0
149 return x
152def _fix_real_abs_gt_1(x):
153 """Convert `x` to complex if it has real components x_i with abs(x_i)>1.
155 Otherwise, output is just the array version of the input (via asarray).
157 Parameters
158 ----------
159 x : array_like
161 Returns
162 -------
163 array
165 Examples
166 --------
167 >>> np.lib.scimath._fix_real_abs_gt_1([0,1])
168 array([0, 1])
170 >>> np.lib.scimath._fix_real_abs_gt_1([0,2])
171 array([0.+0.j, 2.+0.j])
172 """
173 x = asarray(x)
174 if any(isreal(x) & (abs(x) > 1)):
175 x = _tocomplex(x)
176 return x
179def _unary_dispatcher(x):
180 return (x,)
183@array_function_dispatch(_unary_dispatcher)
184def sqrt(x):
185 """
186 Compute the square root of x.
188 For negative input elements, a complex value is returned
189 (unlike `numpy.sqrt` which returns NaN).
191 Parameters
192 ----------
193 x : array_like
194 The input value(s).
196 Returns
197 -------
198 out : ndarray or scalar
199 The square root of `x`. If `x` was a scalar, so is `out`,
200 otherwise an array is returned.
202 See Also
203 --------
204 numpy.sqrt
206 Examples
207 --------
208 For real, non-negative inputs this works just like `numpy.sqrt`:
210 >>> np.lib.scimath.sqrt(1)
211 1.0
212 >>> np.lib.scimath.sqrt([1, 4])
213 array([1., 2.])
215 But it automatically handles negative inputs:
217 >>> np.lib.scimath.sqrt(-1)
218 1j
219 >>> np.lib.scimath.sqrt([-1,4])
220 array([0.+1.j, 2.+0.j])
222 """
223 x = _fix_real_lt_zero(x)
224 return nx.sqrt(x)
227@array_function_dispatch(_unary_dispatcher)
228def log(x):
229 """
230 Compute the natural logarithm of `x`.
232 Return the "principal value" (for a description of this, see `numpy.log`)
233 of :math:`log_e(x)`. For real `x > 0`, this is a real number (``log(0)``
234 returns ``-inf`` and ``log(np.inf)`` returns ``inf``). Otherwise, the
235 complex principle value is returned.
237 Parameters
238 ----------
239 x : array_like
240 The value(s) whose log is (are) required.
242 Returns
243 -------
244 out : ndarray or scalar
245 The log of the `x` value(s). If `x` was a scalar, so is `out`,
246 otherwise an array is returned.
248 See Also
249 --------
250 numpy.log
252 Notes
253 -----
254 For a log() that returns ``NAN`` when real `x < 0`, use `numpy.log`
255 (note, however, that otherwise `numpy.log` and this `log` are identical,
256 i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`, and,
257 notably, the complex principle value if ``x.imag != 0``).
259 Examples
260 --------
261 >>> np.emath.log(np.exp(1))
262 1.0
264 Negative arguments are handled "correctly" (recall that
265 ``exp(log(x)) == x`` does *not* hold for real ``x < 0``):
267 >>> np.emath.log(-np.exp(1)) == (1 + np.pi * 1j)
268 True
270 """
271 x = _fix_real_lt_zero(x)
272 return nx.log(x)
275@array_function_dispatch(_unary_dispatcher)
276def log10(x):
277 """
278 Compute the logarithm base 10 of `x`.
280 Return the "principal value" (for a description of this, see
281 `numpy.log10`) of :math:`log_{10}(x)`. For real `x > 0`, this
282 is a real number (``log10(0)`` returns ``-inf`` and ``log10(np.inf)``
283 returns ``inf``). Otherwise, the complex principle value is returned.
285 Parameters
286 ----------
287 x : array_like or scalar
288 The value(s) whose log base 10 is (are) required.
290 Returns
291 -------
292 out : ndarray or scalar
293 The log base 10 of the `x` value(s). If `x` was a scalar, so is `out`,
294 otherwise an array object is returned.
296 See Also
297 --------
298 numpy.log10
300 Notes
301 -----
302 For a log10() that returns ``NAN`` when real `x < 0`, use `numpy.log10`
303 (note, however, that otherwise `numpy.log10` and this `log10` are
304 identical, i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`,
305 and, notably, the complex principle value if ``x.imag != 0``).
307 Examples
308 --------
310 (We set the printing precision so the example can be auto-tested)
312 >>> np.set_printoptions(precision=4)
314 >>> np.emath.log10(10**1)
315 1.0
317 >>> np.emath.log10([-10**1, -10**2, 10**2])
318 array([1.+1.3644j, 2.+1.3644j, 2.+0.j ])
320 """
321 x = _fix_real_lt_zero(x)
322 return nx.log10(x)
325def _logn_dispatcher(n, x):
326 return (n, x,)
329@array_function_dispatch(_logn_dispatcher)
330def logn(n, x):
331 """
332 Take log base n of x.
334 If `x` contains negative inputs, the answer is computed and returned in the
335 complex domain.
337 Parameters
338 ----------
339 n : array_like
340 The integer base(s) in which the log is taken.
341 x : array_like
342 The value(s) whose log base `n` is (are) required.
344 Returns
345 -------
346 out : ndarray or scalar
347 The log base `n` of the `x` value(s). If `x` was a scalar, so is
348 `out`, otherwise an array is returned.
350 Examples
351 --------
352 >>> np.set_printoptions(precision=4)
354 >>> np.lib.scimath.logn(2, [4, 8])
355 array([2., 3.])
356 >>> np.lib.scimath.logn(2, [-4, -8, 8])
357 array([2.+4.5324j, 3.+4.5324j, 3.+0.j ])
359 """
360 x = _fix_real_lt_zero(x)
361 n = _fix_real_lt_zero(n)
362 return nx.log(x)/nx.log(n)
365@array_function_dispatch(_unary_dispatcher)
366def log2(x):
367 """
368 Compute the logarithm base 2 of `x`.
370 Return the "principal value" (for a description of this, see
371 `numpy.log2`) of :math:`log_2(x)`. For real `x > 0`, this is
372 a real number (``log2(0)`` returns ``-inf`` and ``log2(np.inf)`` returns
373 ``inf``). Otherwise, the complex principle value is returned.
375 Parameters
376 ----------
377 x : array_like
378 The value(s) whose log base 2 is (are) required.
380 Returns
381 -------
382 out : ndarray or scalar
383 The log base 2 of the `x` value(s). If `x` was a scalar, so is `out`,
384 otherwise an array is returned.
386 See Also
387 --------
388 numpy.log2
390 Notes
391 -----
392 For a log2() that returns ``NAN`` when real `x < 0`, use `numpy.log2`
393 (note, however, that otherwise `numpy.log2` and this `log2` are
394 identical, i.e., both return ``-inf`` for `x = 0`, ``inf`` for `x = inf`,
395 and, notably, the complex principle value if ``x.imag != 0``).
397 Examples
398 --------
399 We set the printing precision so the example can be auto-tested:
401 >>> np.set_printoptions(precision=4)
403 >>> np.emath.log2(8)
404 3.0
405 >>> np.emath.log2([-4, -8, 8])
406 array([2.+4.5324j, 3.+4.5324j, 3.+0.j ])
408 """
409 x = _fix_real_lt_zero(x)
410 return nx.log2(x)
413def _power_dispatcher(x, p):
414 return (x, p)
417@array_function_dispatch(_power_dispatcher)
418def power(x, p):
419 """
420 Return x to the power p, (x**p).
422 If `x` contains negative values, the output is converted to the
423 complex domain.
425 Parameters
426 ----------
427 x : array_like
428 The input value(s).
429 p : array_like of ints
430 The power(s) to which `x` is raised. If `x` contains multiple values,
431 `p` has to either be a scalar, or contain the same number of values
432 as `x`. In the latter case, the result is
433 ``x[0]**p[0], x[1]**p[1], ...``.
435 Returns
436 -------
437 out : ndarray or scalar
438 The result of ``x**p``. If `x` and `p` are scalars, so is `out`,
439 otherwise an array is returned.
441 See Also
442 --------
443 numpy.power
445 Examples
446 --------
447 >>> np.set_printoptions(precision=4)
449 >>> np.lib.scimath.power([2, 4], 2)
450 array([ 4, 16])
451 >>> np.lib.scimath.power([2, 4], -2)
452 array([0.25 , 0.0625])
453 >>> np.lib.scimath.power([-2, 4], 2)
454 array([ 4.-0.j, 16.+0.j])
456 """
457 x = _fix_real_lt_zero(x)
458 p = _fix_int_lt_zero(p)
459 return nx.power(x, p)
462@array_function_dispatch(_unary_dispatcher)
463def arccos(x):
464 """
465 Compute the inverse cosine of x.
467 Return the "principal value" (for a description of this, see
468 `numpy.arccos`) of the inverse cosine of `x`. For real `x` such that
469 `abs(x) <= 1`, this is a real number in the closed interval
470 :math:`[0, \\pi]`. Otherwise, the complex principle value is returned.
472 Parameters
473 ----------
474 x : array_like or scalar
475 The value(s) whose arccos is (are) required.
477 Returns
478 -------
479 out : ndarray or scalar
480 The inverse cosine(s) of the `x` value(s). If `x` was a scalar, so
481 is `out`, otherwise an array object is returned.
483 See Also
484 --------
485 numpy.arccos
487 Notes
488 -----
489 For an arccos() that returns ``NAN`` when real `x` is not in the
490 interval ``[-1,1]``, use `numpy.arccos`.
492 Examples
493 --------
494 >>> np.set_printoptions(precision=4)
496 >>> np.emath.arccos(1) # a scalar is returned
497 0.0
499 >>> np.emath.arccos([1,2])
500 array([0.-0.j , 0.-1.317j])
502 """
503 x = _fix_real_abs_gt_1(x)
504 return nx.arccos(x)
507@array_function_dispatch(_unary_dispatcher)
508def arcsin(x):
509 """
510 Compute the inverse sine of x.
512 Return the "principal value" (for a description of this, see
513 `numpy.arcsin`) of the inverse sine of `x`. For real `x` such that
514 `abs(x) <= 1`, this is a real number in the closed interval
515 :math:`[-\\pi/2, \\pi/2]`. Otherwise, the complex principle value is
516 returned.
518 Parameters
519 ----------
520 x : array_like or scalar
521 The value(s) whose arcsin is (are) required.
523 Returns
524 -------
525 out : ndarray or scalar
526 The inverse sine(s) of the `x` value(s). If `x` was a scalar, so
527 is `out`, otherwise an array object is returned.
529 See Also
530 --------
531 numpy.arcsin
533 Notes
534 -----
535 For an arcsin() that returns ``NAN`` when real `x` is not in the
536 interval ``[-1,1]``, use `numpy.arcsin`.
538 Examples
539 --------
540 >>> np.set_printoptions(precision=4)
542 >>> np.emath.arcsin(0)
543 0.0
545 >>> np.emath.arcsin([0,1])
546 array([0. , 1.5708])
548 """
549 x = _fix_real_abs_gt_1(x)
550 return nx.arcsin(x)
553@array_function_dispatch(_unary_dispatcher)
554def arctanh(x):
555 """
556 Compute the inverse hyperbolic tangent of `x`.
558 Return the "principal value" (for a description of this, see
559 `numpy.arctanh`) of `arctanh(x)`. For real `x` such that
560 `abs(x) < 1`, this is a real number. If `abs(x) > 1`, or if `x` is
561 complex, the result is complex. Finally, `x = 1` returns``inf`` and
562 `x=-1` returns ``-inf``.
564 Parameters
565 ----------
566 x : array_like
567 The value(s) whose arctanh is (are) required.
569 Returns
570 -------
571 out : ndarray or scalar
572 The inverse hyperbolic tangent(s) of the `x` value(s). If `x` was
573 a scalar so is `out`, otherwise an array is returned.
576 See Also
577 --------
578 numpy.arctanh
580 Notes
581 -----
582 For an arctanh() that returns ``NAN`` when real `x` is not in the
583 interval ``(-1,1)``, use `numpy.arctanh` (this latter, however, does
584 return +/-inf for `x = +/-1`).
586 Examples
587 --------
588 >>> np.set_printoptions(precision=4)
590 >>> from numpy.testing import suppress_warnings
591 >>> with suppress_warnings() as sup:
592 ... sup.filter(RuntimeWarning)
593 ... np.emath.arctanh(np.eye(2))
594 array([[inf, 0.],
595 [ 0., inf]])
596 >>> np.emath.arctanh([1j])
597 array([0.+0.7854j])
599 """
600 x = _fix_real_abs_gt_1(x)
601 return nx.arctanh(x)