_methods.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. """
  2. Array methods which are called by both the C-code for the method
  3. and the Python code for the NumPy-namespace function
  4. """
  5. from __future__ import division, absolute_import, print_function
  6. import warnings
  7. from numpy.core import multiarray as mu
  8. from numpy.core import umath as um
  9. from numpy.core.numeric import asanyarray
  10. from numpy.core import numerictypes as nt
  11. from numpy._globals import _NoValue
  12. # save those O(100) nanoseconds!
  13. umr_maximum = um.maximum.reduce
  14. umr_minimum = um.minimum.reduce
  15. umr_sum = um.add.reduce
  16. umr_prod = um.multiply.reduce
  17. umr_any = um.logical_or.reduce
  18. umr_all = um.logical_and.reduce
  19. # avoid keyword arguments to speed up parsing, saves about 15%-20% for very
  20. # small reductions
  21. def _amax(a, axis=None, out=None, keepdims=False,
  22. initial=_NoValue):
  23. return umr_maximum(a, axis, None, out, keepdims, initial)
  24. def _amin(a, axis=None, out=None, keepdims=False,
  25. initial=_NoValue):
  26. return umr_minimum(a, axis, None, out, keepdims, initial)
  27. def _sum(a, axis=None, dtype=None, out=None, keepdims=False,
  28. initial=_NoValue):
  29. return umr_sum(a, axis, dtype, out, keepdims, initial)
  30. def _prod(a, axis=None, dtype=None, out=None, keepdims=False,
  31. initial=_NoValue):
  32. return umr_prod(a, axis, dtype, out, keepdims, initial)
  33. def _any(a, axis=None, dtype=None, out=None, keepdims=False):
  34. return umr_any(a, axis, dtype, out, keepdims)
  35. def _all(a, axis=None, dtype=None, out=None, keepdims=False):
  36. return umr_all(a, axis, dtype, out, keepdims)
  37. def _count_reduce_items(arr, axis):
  38. if axis is None:
  39. axis = tuple(range(arr.ndim))
  40. if not isinstance(axis, tuple):
  41. axis = (axis,)
  42. items = 1
  43. for ax in axis:
  44. items *= arr.shape[ax]
  45. return items
  46. def _mean(a, axis=None, dtype=None, out=None, keepdims=False):
  47. arr = asanyarray(a)
  48. is_float16_result = False
  49. rcount = _count_reduce_items(arr, axis)
  50. # Make this warning show up first
  51. if rcount == 0:
  52. warnings.warn("Mean of empty slice.", RuntimeWarning, stacklevel=2)
  53. # Cast bool, unsigned int, and int to float64 by default
  54. if dtype is None:
  55. if issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
  56. dtype = mu.dtype('f8')
  57. elif issubclass(arr.dtype.type, nt.float16):
  58. dtype = mu.dtype('f4')
  59. is_float16_result = True
  60. ret = umr_sum(arr, axis, dtype, out, keepdims)
  61. if isinstance(ret, mu.ndarray):
  62. ret = um.true_divide(
  63. ret, rcount, out=ret, casting='unsafe', subok=False)
  64. if is_float16_result and out is None:
  65. ret = arr.dtype.type(ret)
  66. elif hasattr(ret, 'dtype'):
  67. if is_float16_result:
  68. ret = arr.dtype.type(ret / rcount)
  69. else:
  70. ret = ret.dtype.type(ret / rcount)
  71. else:
  72. ret = ret / rcount
  73. return ret
  74. def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
  75. arr = asanyarray(a)
  76. rcount = _count_reduce_items(arr, axis)
  77. # Make this warning show up on top.
  78. if ddof >= rcount:
  79. warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning,
  80. stacklevel=2)
  81. # Cast bool, unsigned int, and int to float64 by default
  82. if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
  83. dtype = mu.dtype('f8')
  84. # Compute the mean.
  85. # Note that if dtype is not of inexact type then arraymean will
  86. # not be either.
  87. arrmean = umr_sum(arr, axis, dtype, keepdims=True)
  88. if isinstance(arrmean, mu.ndarray):
  89. arrmean = um.true_divide(
  90. arrmean, rcount, out=arrmean, casting='unsafe', subok=False)
  91. else:
  92. arrmean = arrmean.dtype.type(arrmean / rcount)
  93. # Compute sum of squared deviations from mean
  94. # Note that x may not be inexact and that we need it to be an array,
  95. # not a scalar.
  96. x = asanyarray(arr - arrmean)
  97. if issubclass(arr.dtype.type, nt.complexfloating):
  98. x = um.multiply(x, um.conjugate(x), out=x).real
  99. else:
  100. x = um.multiply(x, x, out=x)
  101. ret = umr_sum(x, axis, dtype, out, keepdims)
  102. # Compute degrees of freedom and make sure it is not negative.
  103. rcount = max([rcount - ddof, 0])
  104. # divide by degrees of freedom
  105. if isinstance(ret, mu.ndarray):
  106. ret = um.true_divide(
  107. ret, rcount, out=ret, casting='unsafe', subok=False)
  108. elif hasattr(ret, 'dtype'):
  109. ret = ret.dtype.type(ret / rcount)
  110. else:
  111. ret = ret / rcount
  112. return ret
  113. def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
  114. ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
  115. keepdims=keepdims)
  116. if isinstance(ret, mu.ndarray):
  117. ret = um.sqrt(ret, out=ret)
  118. elif hasattr(ret, 'dtype'):
  119. ret = ret.dtype.type(um.sqrt(ret))
  120. else:
  121. ret = um.sqrt(ret)
  122. return ret
  123. def _ptp(a, axis=None, out=None, keepdims=False):
  124. return um.subtract(
  125. umr_maximum(a, axis, None, out, keepdims),
  126. umr_minimum(a, axis, None, None, keepdims),
  127. out
  128. )