Hide keyboard shortcuts

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

""" 

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

and the Python code for the NumPy-namespace function 

 

""" 

import warnings 

 

from numpy.core import multiarray as mu 

from numpy.core import umath as um 

from numpy.core._asarray import asanyarray 

from numpy.core import numerictypes as nt 

from numpy.core import _exceptions 

from numpy._globals import _NoValue 

from numpy.compat import pickle, os_fspath, contextlib_nullcontext 

 

# save those O(100) nanoseconds! 

umr_maximum = um.maximum.reduce 

umr_minimum = um.minimum.reduce 

umr_sum = um.add.reduce 

umr_prod = um.multiply.reduce 

umr_any = um.logical_or.reduce 

umr_all = um.logical_and.reduce 

 

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

_complex_to_float = { 

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

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

} 

# Special case for windows: ensure double takes precedence 

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

_complex_to_float.update({ 

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

}) 

 

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

# small reductions 

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

initial=_NoValue, where=True): 

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

 

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

initial=_NoValue, where=True): 

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

 

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

initial=_NoValue, where=True): 

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

 

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

initial=_NoValue, where=True): 

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

 

def _any(a, axis=None, dtype=None, out=None, keepdims=False): 

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

 

def _all(a, axis=None, dtype=None, out=None, keepdims=False): 

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

 

def _count_reduce_items(arr, axis): 

if axis is None: 

axis = tuple(range(arr.ndim)) 

if not isinstance(axis, tuple): 

axis = (axis,) 

items = 1 

for ax in axis: 

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

return items 

 

# Numpy 1.17.0, 2019-02-24 

# Various clip behavior deprecations, marked with _clip_dep as a prefix. 

 

def _clip_dep_is_scalar_nan(a): 

# guarded to protect circular imports 

from numpy.core.fromnumeric import ndim 

if ndim(a) != 0: 

return False 

try: 

return um.isnan(a) 

except TypeError: 

return False 

 

def _clip_dep_is_byte_swapped(a): 

if isinstance(a, mu.ndarray): 

return not a.dtype.isnative 

return False 

 

def _clip_dep_invoke_with_casting(ufunc, *args, out=None, casting=None, **kwargs): 

# normal path 

if casting is not None: 

return ufunc(*args, out=out, casting=casting, **kwargs) 

 

# try to deal with broken casting rules 

try: 

return ufunc(*args, out=out, **kwargs) 

except _exceptions._UFuncOutputCastingError as e: 

# Numpy 1.17.0, 2019-02-24 

warnings.warn( 

"Converting the output of clip from {!r} to {!r} is deprecated. " 

"Pass `casting=\"unsafe\"` explicitly to silence this warning, or " 

"correct the type of the variables.".format(e.from_, e.to), 

DeprecationWarning, 

stacklevel=2 

) 

return ufunc(*args, out=out, casting="unsafe", **kwargs) 

 

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

if min is None and max is None: 

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

 

# Numpy 1.17.0, 2019-02-24 

# This deprecation probably incurs a substantial slowdown for small arrays, 

# it will be good to get rid of it. 

if not _clip_dep_is_byte_swapped(a) and not _clip_dep_is_byte_swapped(out): 

using_deprecated_nan = False 

if _clip_dep_is_scalar_nan(min): 

min = -float('inf') 

using_deprecated_nan = True 

if _clip_dep_is_scalar_nan(max): 

max = float('inf') 

using_deprecated_nan = True 

if using_deprecated_nan: 

warnings.warn( 

"Passing `np.nan` to mean no clipping in np.clip has always " 

"been unreliable, and is now deprecated. " 

"In future, this will always return nan, like it already does " 

"when min or max are arrays that contain nan. " 

"To skip a bound, pass either None or an np.inf of an " 

"appropriate sign.", 

DeprecationWarning, 

stacklevel=2 

) 

 

if min is None: 

return _clip_dep_invoke_with_casting( 

um.minimum, a, max, out=out, casting=casting, **kwargs) 

elif max is None: 

return _clip_dep_invoke_with_casting( 

um.maximum, a, min, out=out, casting=casting, **kwargs) 

else: 

return _clip_dep_invoke_with_casting( 

um.clip, a, min, max, out=out, casting=casting, **kwargs) 

 

def _mean(a, axis=None, dtype=None, out=None, keepdims=False): 

arr = asanyarray(a) 

 

is_float16_result = False 

rcount = _count_reduce_items(arr, axis) 

# Make this warning show up first 

if rcount == 0: 

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

 

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

if dtype is None: 

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

dtype = mu.dtype('f8') 

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

dtype = mu.dtype('f4') 

is_float16_result = True 

 

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

if isinstance(ret, mu.ndarray): 

ret = um.true_divide( 

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

if is_float16_result and out is None: 

ret = arr.dtype.type(ret) 

elif hasattr(ret, 'dtype'): 

if is_float16_result: 

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

else: 

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

else: 

ret = ret / rcount 

 

return ret 

 

def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False): 

arr = asanyarray(a) 

 

rcount = _count_reduce_items(arr, axis) 

# Make this warning show up on top. 

if ddof >= rcount: 

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

stacklevel=2) 

 

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

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

dtype = mu.dtype('f8') 

 

# Compute the mean. 

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

# not be either. 

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

if isinstance(arrmean, mu.ndarray): 

arrmean = um.true_divide( 

arrmean, rcount, out=arrmean, casting='unsafe', subok=False) 

else: 

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

 

# Compute sum of squared deviations from mean 

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

# not a scalar. 

x = asanyarray(arr - arrmean) 

 

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

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

# Fast-paths for built-in complex types 

elif x.dtype in _complex_to_float: 

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

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

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

# Most general case; includes handling object arrays containing imaginary 

# numbers and complex types with non-native byteorder 

else: 

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

 

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

 

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

rcount = max([rcount - ddof, 0]) 

 

# divide by degrees of freedom 

if isinstance(ret, mu.ndarray): 

ret = um.true_divide( 

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

elif hasattr(ret, 'dtype'): 

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

else: 

ret = ret / rcount 

 

return ret 

 

def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False): 

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

keepdims=keepdims) 

 

if isinstance(ret, mu.ndarray): 

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

elif hasattr(ret, 'dtype'): 

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

else: 

ret = um.sqrt(ret) 

 

return ret 

 

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

return um.subtract( 

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

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

out 

) 

 

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

if hasattr(file, 'write'): 

ctx = contextlib_nullcontext(file) 

else: 

ctx = open(os_fspath(file), "wb") 

with ctx as f: 

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

 

def _dumps(self, protocol=2): 

return pickle.dumps(self, protocol=protocol)