Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/_core/_methods.py: 26%

143 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-09 06:12 +0000

1""" 

2Array methods which are called by both the C-code for the method 

3and the Python code for the NumPy-namespace function 

4 

5""" 

6import os 

7import pickle 

8import warnings 

9from contextlib import nullcontext 

10 

11from numpy._core import multiarray as mu 

12from numpy._core import umath as um 

13from numpy._core.multiarray import asanyarray 

14from numpy._core import numerictypes as nt 

15from numpy._core import _exceptions 

16from numpy._core._ufunc_config import _no_nep50_warning 

17from numpy._globals import _NoValue 

18 

19# save those O(100) nanoseconds! 

20bool_dt = mu.dtype("bool") 

21umr_maximum = um.maximum.reduce 

22umr_minimum = um.minimum.reduce 

23umr_sum = um.add.reduce 

24umr_prod = um.multiply.reduce 

25umr_bitwise_count = um.bitwise_count 

26umr_any = um.logical_or.reduce 

27umr_all = um.logical_and.reduce 

28 

29# Complex types to -> (2,)float view for fast-path computation in _var() 

30_complex_to_float = { 

31 nt.dtype(nt.csingle) : nt.dtype(nt.single), 

32 nt.dtype(nt.cdouble) : nt.dtype(nt.double), 

33} 

34# Special case for windows: ensure double takes precedence 

35if nt.dtype(nt.longdouble) != nt.dtype(nt.double): 

36 _complex_to_float.update({ 

37 nt.dtype(nt.clongdouble) : nt.dtype(nt.longdouble), 

38 }) 

39 

40# avoid keyword arguments to speed up parsing, saves about 15%-20% for very 

41# small reductions 

42def _amax(a, axis=None, out=None, keepdims=False, 

43 initial=_NoValue, where=True): 

44 return umr_maximum(a, axis, None, out, keepdims, initial, where) 

45 

46def _amin(a, axis=None, out=None, keepdims=False, 

47 initial=_NoValue, where=True): 

48 return umr_minimum(a, axis, None, out, keepdims, initial, where) 

49 

50def _sum(a, axis=None, dtype=None, out=None, keepdims=False, 

51 initial=_NoValue, where=True): 

52 return umr_sum(a, axis, dtype, out, keepdims, initial, where) 

53 

54def _prod(a, axis=None, dtype=None, out=None, keepdims=False, 

55 initial=_NoValue, where=True): 

56 return umr_prod(a, axis, dtype, out, keepdims, initial, where) 

57 

58def _any(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): 

59 # By default, return a boolean for any and all 

60 if dtype is None: 

61 dtype = bool_dt 

62 # Parsing keyword arguments is currently fairly slow, so avoid it for now 

63 if where is True: 

64 return umr_any(a, axis, dtype, out, keepdims) 

65 return umr_any(a, axis, dtype, out, keepdims, where=where) 

66 

67def _all(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): 

68 # By default, return a boolean for any and all 

69 if dtype is None: 

70 dtype = bool_dt 

71 # Parsing keyword arguments is currently fairly slow, so avoid it for now 

72 if where is True: 

73 return umr_all(a, axis, dtype, out, keepdims) 

74 return umr_all(a, axis, dtype, out, keepdims, where=where) 

75 

76def _count_reduce_items(arr, axis, keepdims=False, where=True): 

77 # fast-path for the default case 

78 if where is True: 

79 # no boolean mask given, calculate items according to axis 

80 if axis is None: 

81 axis = tuple(range(arr.ndim)) 

82 elif not isinstance(axis, tuple): 

83 axis = (axis,) 

84 items = 1 

85 for ax in axis: 

86 items *= arr.shape[mu.normalize_axis_index(ax, arr.ndim)] 

87 items = nt.intp(items) 

88 else: 

89 # TODO: Optimize case when `where` is broadcast along a non-reduction 

90 # axis and full sum is more excessive than needed. 

91 

92 # guarded to protect circular imports 

93 from numpy.lib._stride_tricks_impl import broadcast_to 

94 # count True values in (potentially broadcasted) boolean mask 

95 items = umr_sum(broadcast_to(where, arr.shape), axis, nt.intp, None, 

96 keepdims) 

97 return items 

98 

99def _clip(a, min=None, max=None, out=None, **kwargs): 

100 if min is None and max is None: 

101 raise ValueError("One of max or min must be given") 

102 

103 if min is None: 

104 return um.minimum(a, max, out=out, **kwargs) 

105 elif max is None: 

106 return um.maximum(a, min, out=out, **kwargs) 

107 else: 

108 return um.clip(a, min, max, out=out, **kwargs) 

109 

110def _mean(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): 

111 arr = asanyarray(a) 

112 

113 is_float16_result = False 

114 

115 rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where) 

116 if rcount == 0 if where is True else umr_any(rcount == 0, axis=None): 

117 warnings.warn("Mean of empty slice.", RuntimeWarning, stacklevel=2) 

118 

119 # Cast bool, unsigned int, and int to float64 by default 

120 if dtype is None: 

121 if issubclass(arr.dtype.type, (nt.integer, nt.bool)): 

122 dtype = mu.dtype('f8') 

123 elif issubclass(arr.dtype.type, nt.float16): 

124 dtype = mu.dtype('f4') 

125 is_float16_result = True 

126 

127 ret = umr_sum(arr, axis, dtype, out, keepdims, where=where) 

128 if isinstance(ret, mu.ndarray): 

129 with _no_nep50_warning(): 

130 ret = um.true_divide( 

131 ret, rcount, out=ret, casting='unsafe', subok=False) 

132 if is_float16_result and out is None: 

133 ret = arr.dtype.type(ret) 

134 elif hasattr(ret, 'dtype'): 

135 if is_float16_result: 

136 ret = arr.dtype.type(ret / rcount) 

137 else: 

138 ret = ret.dtype.type(ret / rcount) 

139 else: 

140 ret = ret / rcount 

141 

142 return ret 

143 

144def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *, 

145 where=True, mean=None): 

146 arr = asanyarray(a) 

147 

148 rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where) 

149 # Make this warning show up on top. 

150 if ddof >= rcount if where is True else umr_any(ddof >= rcount, axis=None): 

151 warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, 

152 stacklevel=2) 

153 

154 # Cast bool, unsigned int, and int to float64 by default 

155 if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool)): 

156 dtype = mu.dtype('f8') 

157 

158 if mean is not None: 

159 arrmean = mean 

160 else: 

161 # Compute the mean. 

162 # Note that if dtype is not of inexact type then arraymean will 

163 # not be either. 

164 arrmean = umr_sum(arr, axis, dtype, keepdims=True, where=where) 

165 # The shape of rcount has to match arrmean to not change the shape of 

166 # out in broadcasting. Otherwise, it cannot be stored back to arrmean. 

167 if rcount.ndim == 0: 

168 # fast-path for default case when where is True 

169 div = rcount 

170 else: 

171 # matching rcount to arrmean when where is specified as array 

172 div = rcount.reshape(arrmean.shape) 

173 if isinstance(arrmean, mu.ndarray): 

174 with _no_nep50_warning(): 

175 arrmean = um.true_divide(arrmean, div, out=arrmean, 

176 casting='unsafe', subok=False) 

177 elif hasattr(arrmean, "dtype"): 

178 arrmean = arrmean.dtype.type(arrmean / rcount) 

179 else: 

180 arrmean = arrmean / rcount 

181 

182 # Compute sum of squared deviations from mean 

183 # Note that x may not be inexact and that we need it to be an array, 

184 # not a scalar. 

185 x = asanyarray(arr - arrmean) 

186 

187 if issubclass(arr.dtype.type, (nt.floating, nt.integer)): 

188 x = um.multiply(x, x, out=x) 

189 # Fast-paths for built-in complex types 

190 elif x.dtype in _complex_to_float: 

191 xv = x.view(dtype=(_complex_to_float[x.dtype], (2,))) 

192 um.multiply(xv, xv, out=xv) 

193 x = um.add(xv[..., 0], xv[..., 1], out=x.real).real 

194 # Most general case; includes handling object arrays containing imaginary 

195 # numbers and complex types with non-native byteorder 

196 else: 

197 x = um.multiply(x, um.conjugate(x), out=x).real 

198 

199 ret = umr_sum(x, axis, dtype, out, keepdims=keepdims, where=where) 

200 

201 # Compute degrees of freedom and make sure it is not negative. 

202 rcount = um.maximum(rcount - ddof, 0) 

203 

204 # divide by degrees of freedom 

205 if isinstance(ret, mu.ndarray): 

206 with _no_nep50_warning(): 

207 ret = um.true_divide( 

208 ret, rcount, out=ret, casting='unsafe', subok=False) 

209 elif hasattr(ret, 'dtype'): 

210 ret = ret.dtype.type(ret / rcount) 

211 else: 

212 ret = ret / rcount 

213 

214 return ret 

215 

216def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *, 

217 where=True, mean=None): 

218 ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof, 

219 keepdims=keepdims, where=where, mean=mean) 

220 

221 if isinstance(ret, mu.ndarray): 

222 ret = um.sqrt(ret, out=ret) 

223 elif hasattr(ret, 'dtype'): 

224 ret = ret.dtype.type(um.sqrt(ret)) 

225 else: 

226 ret = um.sqrt(ret) 

227 

228 return ret 

229 

230def _ptp(a, axis=None, out=None, keepdims=False): 

231 return um.subtract( 

232 umr_maximum(a, axis, None, out, keepdims), 

233 umr_minimum(a, axis, None, None, keepdims), 

234 out 

235 ) 

236 

237def _dump(self, file, protocol=2): 

238 if hasattr(file, 'write'): 

239 ctx = nullcontext(file) 

240 else: 

241 ctx = open(os.fspath(file), "wb") 

242 with ctx as f: 

243 pickle.dump(self, f, protocol=protocol) 

244 

245def _dumps(self, protocol=2): 

246 return pickle.dumps(self, protocol=protocol) 

247 

248def _bitwise_count(a, out=None, *, where=True, casting='same_kind', 

249 order='K', dtype=None, subok=True): 

250 return umr_bitwise_count(a, out, where=where, casting=casting, 

251 order=order, dtype=dtype, subok=subok)