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""" 

2Functions for changing global ufunc configuration 

3 

4This provides helpers which wrap `umath.geterrobj` and `umath.seterrobj` 

5""" 

6import collections.abc 

7import contextlib 

8 

9from .overrides import set_module 

10from .umath import ( 

11 UFUNC_BUFSIZE_DEFAULT, 

12 ERR_IGNORE, ERR_WARN, ERR_RAISE, ERR_CALL, ERR_PRINT, ERR_LOG, ERR_DEFAULT, 

13 SHIFT_DIVIDEBYZERO, SHIFT_OVERFLOW, SHIFT_UNDERFLOW, SHIFT_INVALID, 

14) 

15from . import umath 

16 

17__all__ = [ 

18 "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall", 

19 "errstate", 

20] 

21 

22_errdict = {"ignore": ERR_IGNORE, 

23 "warn": ERR_WARN, 

24 "raise": ERR_RAISE, 

25 "call": ERR_CALL, 

26 "print": ERR_PRINT, 

27 "log": ERR_LOG} 

28 

29_errdict_rev = {value: key for key, value in _errdict.items()} 

30 

31 

32@set_module('numpy') 

33def seterr(all=None, divide=None, over=None, under=None, invalid=None): 

34 """ 

35 Set how floating-point errors are handled. 

36 

37 Note that operations on integer scalar types (such as `int16`) are 

38 handled like floating point, and are affected by these settings. 

39 

40 Parameters 

41 ---------- 

42 all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

43 Set treatment for all types of floating-point errors at once: 

44 

45 - ignore: Take no action when the exception occurs. 

46 - warn: Print a `RuntimeWarning` (via the Python `warnings` module). 

47 - raise: Raise a `FloatingPointError`. 

48 - call: Call a function specified using the `seterrcall` function. 

49 - print: Print a warning directly to ``stdout``. 

50 - log: Record error in a Log object specified by `seterrcall`. 

51 

52 The default is not to change the current behavior. 

53 divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

54 Treatment for division by zero. 

55 over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

56 Treatment for floating-point overflow. 

57 under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

58 Treatment for floating-point underflow. 

59 invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

60 Treatment for invalid floating-point operation. 

61 

62 Returns 

63 ------- 

64 old_settings : dict 

65 Dictionary containing the old settings. 

66 

67 See also 

68 -------- 

69 seterrcall : Set a callback function for the 'call' mode. 

70 geterr, geterrcall, errstate 

71 

72 Notes 

73 ----- 

74 The floating-point exceptions are defined in the IEEE 754 standard [1]_: 

75 

76 - Division by zero: infinite result obtained from finite numbers. 

77 - Overflow: result too large to be expressed. 

78 - Underflow: result so close to zero that some precision 

79 was lost. 

80 - Invalid operation: result is not an expressible number, typically 

81 indicates that a NaN was produced. 

82 

83 .. [1] https://en.wikipedia.org/wiki/IEEE_754 

84 

85 Examples 

86 -------- 

87 >>> old_settings = np.seterr(all='ignore') #seterr to known value 

88 >>> np.seterr(over='raise') 

89 {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'} 

90 >>> np.seterr(**old_settings) # reset to default 

91 {'divide': 'ignore', 'over': 'raise', 'under': 'ignore', 'invalid': 'ignore'} 

92 

93 >>> np.int16(32000) * np.int16(3) 

94 30464 

95 >>> old_settings = np.seterr(all='warn', over='raise') 

96 >>> np.int16(32000) * np.int16(3) 

97 Traceback (most recent call last): 

98 File "<stdin>", line 1, in <module> 

99 FloatingPointError: overflow encountered in short_scalars 

100 

101 >>> from collections import OrderedDict 

102 >>> old_settings = np.seterr(all='print') 

103 >>> OrderedDict(np.geterr()) 

104 OrderedDict([('divide', 'print'), ('over', 'print'), ('under', 'print'), ('invalid', 'print')]) 

105 >>> np.int16(32000) * np.int16(3) 

106 30464 

107 

108 """ 

109 

110 pyvals = umath.geterrobj() 

111 old = geterr() 

112 

113 if divide is None: 

114 divide = all or old['divide'] 

115 if over is None: 

116 over = all or old['over'] 

117 if under is None: 

118 under = all or old['under'] 

119 if invalid is None: 

120 invalid = all or old['invalid'] 

121 

122 maskvalue = ((_errdict[divide] << SHIFT_DIVIDEBYZERO) + 

123 (_errdict[over] << SHIFT_OVERFLOW) + 

124 (_errdict[under] << SHIFT_UNDERFLOW) + 

125 (_errdict[invalid] << SHIFT_INVALID)) 

126 

127 pyvals[1] = maskvalue 

128 umath.seterrobj(pyvals) 

129 return old 

130 

131 

132@set_module('numpy') 

133def geterr(): 

134 """ 

135 Get the current way of handling floating-point errors. 

136 

137 Returns 

138 ------- 

139 res : dict 

140 A dictionary with keys "divide", "over", "under", and "invalid", 

141 whose values are from the strings "ignore", "print", "log", "warn", 

142 "raise", and "call". The keys represent possible floating-point 

143 exceptions, and the values define how these exceptions are handled. 

144 

145 See Also 

146 -------- 

147 geterrcall, seterr, seterrcall 

148 

149 Notes 

150 ----- 

151 For complete documentation of the types of floating-point exceptions and 

152 treatment options, see `seterr`. 

153 

154 Examples 

155 -------- 

156 >>> from collections import OrderedDict 

157 >>> sorted(np.geterr().items()) 

158 [('divide', 'warn'), ('invalid', 'warn'), ('over', 'warn'), ('under', 'ignore')] 

159 >>> np.arange(3.) / np.arange(3.) 

160 array([nan, 1., 1.]) 

161 

162 >>> oldsettings = np.seterr(all='warn', over='raise') 

163 >>> OrderedDict(sorted(np.geterr().items())) 

164 OrderedDict([('divide', 'warn'), ('invalid', 'warn'), ('over', 'raise'), ('under', 'warn')]) 

165 >>> np.arange(3.) / np.arange(3.) 

166 array([nan, 1., 1.]) 

167 

168 """ 

169 maskvalue = umath.geterrobj()[1] 

170 mask = 7 

171 res = {} 

172 val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask 

173 res['divide'] = _errdict_rev[val] 

174 val = (maskvalue >> SHIFT_OVERFLOW) & mask 

175 res['over'] = _errdict_rev[val] 

176 val = (maskvalue >> SHIFT_UNDERFLOW) & mask 

177 res['under'] = _errdict_rev[val] 

178 val = (maskvalue >> SHIFT_INVALID) & mask 

179 res['invalid'] = _errdict_rev[val] 

180 return res 

181 

182 

183@set_module('numpy') 

184def setbufsize(size): 

185 """ 

186 Set the size of the buffer used in ufuncs. 

187 

188 Parameters 

189 ---------- 

190 size : int 

191 Size of buffer. 

192 

193 """ 

194 if size > 10e6: 

195 raise ValueError("Buffer size, %s, is too big." % size) 

196 if size < 5: 

197 raise ValueError("Buffer size, %s, is too small." % size) 

198 if size % 16 != 0: 

199 raise ValueError("Buffer size, %s, is not a multiple of 16." % size) 

200 

201 pyvals = umath.geterrobj() 

202 old = getbufsize() 

203 pyvals[0] = size 

204 umath.seterrobj(pyvals) 

205 return old 

206 

207 

208@set_module('numpy') 

209def getbufsize(): 

210 """ 

211 Return the size of the buffer used in ufuncs. 

212 

213 Returns 

214 ------- 

215 getbufsize : int 

216 Size of ufunc buffer in bytes. 

217 

218 """ 

219 return umath.geterrobj()[0] 

220 

221 

222@set_module('numpy') 

223def seterrcall(func): 

224 """ 

225 Set the floating-point error callback function or log object. 

226 

227 There are two ways to capture floating-point error messages. The first 

228 is to set the error-handler to 'call', using `seterr`. Then, set 

229 the function to call using this function. 

230 

231 The second is to set the error-handler to 'log', using `seterr`. 

232 Floating-point errors then trigger a call to the 'write' method of 

233 the provided object. 

234 

235 Parameters 

236 ---------- 

237 func : callable f(err, flag) or object with write method 

238 Function to call upon floating-point errors ('call'-mode) or 

239 object whose 'write' method is used to log such message ('log'-mode). 

240 

241 The call function takes two arguments. The first is a string describing 

242 the type of error (such as "divide by zero", "overflow", "underflow", 

243 or "invalid value"), and the second is the status flag. The flag is a 

244 byte, whose four least-significant bits indicate the type of error, one 

245 of "divide", "over", "under", "invalid":: 

246 

247 [0 0 0 0 divide over under invalid] 

248 

249 In other words, ``flags = divide + 2*over + 4*under + 8*invalid``. 

250 

251 If an object is provided, its write method should take one argument, 

252 a string. 

253 

254 Returns 

255 ------- 

256 h : callable, log instance or None 

257 The old error handler. 

258 

259 See Also 

260 -------- 

261 seterr, geterr, geterrcall 

262 

263 Examples 

264 -------- 

265 Callback upon error: 

266 

267 >>> def err_handler(type, flag): 

268 ... print("Floating point error (%s), with flag %s" % (type, flag)) 

269 ... 

270 

271 >>> saved_handler = np.seterrcall(err_handler) 

272 >>> save_err = np.seterr(all='call') 

273 >>> from collections import OrderedDict 

274 

275 >>> np.array([1, 2, 3]) / 0.0 

276 Floating point error (divide by zero), with flag 1 

277 array([inf, inf, inf]) 

278 

279 >>> np.seterrcall(saved_handler) 

280 <function err_handler at 0x...> 

281 >>> OrderedDict(sorted(np.seterr(**save_err).items())) 

282 OrderedDict([('divide', 'call'), ('invalid', 'call'), ('over', 'call'), ('under', 'call')]) 

283 

284 Log error message: 

285 

286 >>> class Log: 

287 ... def write(self, msg): 

288 ... print("LOG: %s" % msg) 

289 ... 

290 

291 >>> log = Log() 

292 >>> saved_handler = np.seterrcall(log) 

293 >>> save_err = np.seterr(all='log') 

294 

295 >>> np.array([1, 2, 3]) / 0.0 

296 LOG: Warning: divide by zero encountered in true_divide 

297 array([inf, inf, inf]) 

298 

299 >>> np.seterrcall(saved_handler) 

300 <numpy.core.numeric.Log object at 0x...> 

301 >>> OrderedDict(sorted(np.seterr(**save_err).items())) 

302 OrderedDict([('divide', 'log'), ('invalid', 'log'), ('over', 'log'), ('under', 'log')]) 

303 

304 """ 

305 if func is not None and not isinstance(func, collections.abc.Callable): 

306 if (not hasattr(func, 'write') or 

307 not isinstance(func.write, collections.abc.Callable)): 

308 raise ValueError("Only callable can be used as callback") 

309 pyvals = umath.geterrobj() 

310 old = geterrcall() 

311 pyvals[2] = func 

312 umath.seterrobj(pyvals) 

313 return old 

314 

315 

316@set_module('numpy') 

317def geterrcall(): 

318 """ 

319 Return the current callback function used on floating-point errors. 

320 

321 When the error handling for a floating-point error (one of "divide", 

322 "over", "under", or "invalid") is set to 'call' or 'log', the function 

323 that is called or the log instance that is written to is returned by 

324 `geterrcall`. This function or log instance has been set with 

325 `seterrcall`. 

326 

327 Returns 

328 ------- 

329 errobj : callable, log instance or None 

330 The current error handler. If no handler was set through `seterrcall`, 

331 ``None`` is returned. 

332 

333 See Also 

334 -------- 

335 seterrcall, seterr, geterr 

336 

337 Notes 

338 ----- 

339 For complete documentation of the types of floating-point exceptions and 

340 treatment options, see `seterr`. 

341 

342 Examples 

343 -------- 

344 >>> np.geterrcall() # we did not yet set a handler, returns None 

345 

346 >>> oldsettings = np.seterr(all='call') 

347 >>> def err_handler(type, flag): 

348 ... print("Floating point error (%s), with flag %s" % (type, flag)) 

349 >>> oldhandler = np.seterrcall(err_handler) 

350 >>> np.array([1, 2, 3]) / 0.0 

351 Floating point error (divide by zero), with flag 1 

352 array([inf, inf, inf]) 

353 

354 >>> cur_handler = np.geterrcall() 

355 >>> cur_handler is err_handler 

356 True 

357 

358 """ 

359 return umath.geterrobj()[2] 

360 

361 

362class _unspecified: 

363 pass 

364 

365 

366_Unspecified = _unspecified() 

367 

368 

369@set_module('numpy') 

370class errstate(contextlib.ContextDecorator): 

371 """ 

372 errstate(**kwargs) 

373 

374 Context manager for floating-point error handling. 

375 

376 Using an instance of `errstate` as a context manager allows statements in 

377 that context to execute with a known error handling behavior. Upon entering 

378 the context the error handling is set with `seterr` and `seterrcall`, and 

379 upon exiting it is reset to what it was before. 

380 

381 .. versionchanged:: 1.17.0 

382 `errstate` is also usable as a function decorator, saving 

383 a level of indentation if an entire function is wrapped. 

384 See :py:class:`contextlib.ContextDecorator` for more information. 

385 

386 Parameters 

387 ---------- 

388 kwargs : {divide, over, under, invalid} 

389 Keyword arguments. The valid keywords are the possible floating-point 

390 exceptions. Each keyword should have a string value that defines the 

391 treatment for the particular error. Possible values are 

392 {'ignore', 'warn', 'raise', 'call', 'print', 'log'}. 

393 

394 See Also 

395 -------- 

396 seterr, geterr, seterrcall, geterrcall 

397 

398 Notes 

399 ----- 

400 For complete documentation of the types of floating-point exceptions and 

401 treatment options, see `seterr`. 

402 

403 Examples 

404 -------- 

405 >>> from collections import OrderedDict 

406 >>> olderr = np.seterr(all='ignore') # Set error handling to known state. 

407 

408 >>> np.arange(3) / 0. 

409 array([nan, inf, inf]) 

410 >>> with np.errstate(divide='warn'): 

411 ... np.arange(3) / 0. 

412 array([nan, inf, inf]) 

413 

414 >>> np.sqrt(-1) 

415 nan 

416 >>> with np.errstate(invalid='raise'): 

417 ... np.sqrt(-1) 

418 Traceback (most recent call last): 

419 File "<stdin>", line 2, in <module> 

420 FloatingPointError: invalid value encountered in sqrt 

421 

422 Outside the context the error handling behavior has not changed: 

423 

424 >>> OrderedDict(sorted(np.geterr().items())) 

425 OrderedDict([('divide', 'ignore'), ('invalid', 'ignore'), ('over', 'ignore'), ('under', 'ignore')]) 

426 

427 """ 

428 

429 def __init__(self, *, call=_Unspecified, **kwargs): 

430 self.call = call 

431 self.kwargs = kwargs 

432 

433 def __enter__(self): 

434 self.oldstate = seterr(**self.kwargs) 

435 if self.call is not _Unspecified: 

436 self.oldcall = seterrcall(self.call) 

437 

438 def __exit__(self, *exc_info): 

439 seterr(**self.oldstate) 

440 if self.call is not _Unspecified: 

441 seterrcall(self.oldcall) 

442 

443 

444def _setdef(): 

445 defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None] 

446 umath.seterrobj(defval) 

447 

448 

449# set the default values 

450_setdef()