Chris@87: """ Chris@87: ============= Chris@87: Miscellaneous Chris@87: ============= Chris@87: Chris@87: IEEE 754 Floating Point Special Values Chris@87: -------------------------------------- Chris@87: Chris@87: Special values defined in numpy: nan, inf, Chris@87: Chris@87: NaNs can be used as a poor-man's mask (if you don't care what the Chris@87: original value was) Chris@87: Chris@87: Note: cannot use equality to test NaNs. E.g.: :: Chris@87: Chris@87: >>> myarr = np.array([1., 0., np.nan, 3.]) Chris@87: >>> np.where(myarr == np.nan) Chris@87: >>> np.nan == np.nan # is always False! Use special numpy functions instead. Chris@87: False Chris@87: >>> myarr[myarr == np.nan] = 0. # doesn't work Chris@87: >>> myarr Chris@87: array([ 1., 0., NaN, 3.]) Chris@87: >>> myarr[np.isnan(myarr)] = 0. # use this instead find Chris@87: >>> myarr Chris@87: array([ 1., 0., 0., 3.]) Chris@87: Chris@87: Other related special value functions: :: Chris@87: Chris@87: isinf(): True if value is inf Chris@87: isfinite(): True if not nan or inf Chris@87: nan_to_num(): Map nan to 0, inf to max float, -inf to min float Chris@87: Chris@87: The following corresponds to the usual functions except that nans are excluded Chris@87: from the results: :: Chris@87: Chris@87: nansum() Chris@87: nanmax() Chris@87: nanmin() Chris@87: nanargmax() Chris@87: nanargmin() Chris@87: Chris@87: >>> x = np.arange(10.) Chris@87: >>> x[3] = np.nan Chris@87: >>> x.sum() Chris@87: nan Chris@87: >>> np.nansum(x) Chris@87: 42.0 Chris@87: Chris@87: How numpy handles numerical exceptions Chris@87: -------------------------------------- Chris@87: Chris@87: The default is to ``'warn'`` for ``invalid``, ``divide``, and ``overflow`` Chris@87: and ``'ignore'`` for ``underflow``. But this can be changed, and it can be Chris@87: set individually for different kinds of exceptions. The different behaviors Chris@87: are: Chris@87: Chris@87: - 'ignore' : Take no action when the exception occurs. Chris@87: - 'warn' : Print a `RuntimeWarning` (via the Python `warnings` module). Chris@87: - 'raise' : Raise a `FloatingPointError`. Chris@87: - 'call' : Call a function specified using the `seterrcall` function. Chris@87: - 'print' : Print a warning directly to ``stdout``. Chris@87: - 'log' : Record error in a Log object specified by `seterrcall`. Chris@87: Chris@87: These behaviors can be set for all kinds of errors or specific ones: Chris@87: Chris@87: - all : apply to all numeric exceptions Chris@87: - invalid : when NaNs are generated Chris@87: - divide : divide by zero (for integers as well!) Chris@87: - overflow : floating point overflows Chris@87: - underflow : floating point underflows Chris@87: Chris@87: Note that integer divide-by-zero is handled by the same machinery. Chris@87: These behaviors are set on a per-thread basis. Chris@87: Chris@87: Examples Chris@87: -------- Chris@87: Chris@87: :: Chris@87: Chris@87: >>> oldsettings = np.seterr(all='warn') Chris@87: >>> np.zeros(5,dtype=np.float32)/0. Chris@87: invalid value encountered in divide Chris@87: >>> j = np.seterr(under='ignore') Chris@87: >>> np.array([1.e-100])**10 Chris@87: >>> j = np.seterr(invalid='raise') Chris@87: >>> np.sqrt(np.array([-1.])) Chris@87: FloatingPointError: invalid value encountered in sqrt Chris@87: >>> def errorhandler(errstr, errflag): Chris@87: ... print "saw stupid error!" Chris@87: >>> np.seterrcall(errorhandler) Chris@87: Chris@87: >>> j = np.seterr(all='call') Chris@87: >>> np.zeros(5, dtype=np.int32)/0 Chris@87: FloatingPointError: invalid value encountered in divide Chris@87: saw stupid error! Chris@87: >>> j = np.seterr(**oldsettings) # restore previous Chris@87: ... # error-handling settings Chris@87: Chris@87: Interfacing to C Chris@87: ---------------- Chris@87: Only a survey of the choices. Little detail on how each works. Chris@87: Chris@87: 1) Bare metal, wrap your own C-code manually. Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - Efficient Chris@87: - No dependencies on other tools Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - Lots of learning overhead: Chris@87: Chris@87: - need to learn basics of Python C API Chris@87: - need to learn basics of numpy C API Chris@87: - need to learn how to handle reference counting and love it. Chris@87: Chris@87: - Reference counting often difficult to get right. Chris@87: Chris@87: - getting it wrong leads to memory leaks, and worse, segfaults Chris@87: Chris@87: - API will change for Python 3.0! Chris@87: Chris@87: 2) Cython Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - avoid learning C API's Chris@87: - no dealing with reference counting Chris@87: - can code in pseudo python and generate C code Chris@87: - can also interface to existing C code Chris@87: - should shield you from changes to Python C api Chris@87: - has become the de-facto standard within the scientific Python community Chris@87: - fast indexing support for arrays Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - Can write code in non-standard form which may become obsolete Chris@87: - Not as flexible as manual wrapping Chris@87: Chris@87: 4) ctypes Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - part of Python standard library Chris@87: - good for interfacing to existing sharable libraries, particularly Chris@87: Windows DLLs Chris@87: - avoids API/reference counting issues Chris@87: - good numpy support: arrays have all these in their ctypes Chris@87: attribute: :: Chris@87: Chris@87: a.ctypes.data a.ctypes.get_strides Chris@87: a.ctypes.data_as a.ctypes.shape Chris@87: a.ctypes.get_as_parameter a.ctypes.shape_as Chris@87: a.ctypes.get_data a.ctypes.strides Chris@87: a.ctypes.get_shape a.ctypes.strides_as Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - can't use for writing code to be turned into C extensions, only a wrapper Chris@87: tool. Chris@87: Chris@87: 5) SWIG (automatic wrapper generator) Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - around a long time Chris@87: - multiple scripting language support Chris@87: - C++ support Chris@87: - Good for wrapping large (many functions) existing C libraries Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - generates lots of code between Python and the C code Chris@87: - can cause performance problems that are nearly impossible to optimize Chris@87: out Chris@87: - interface files can be hard to write Chris@87: - doesn't necessarily avoid reference counting issues or needing to know Chris@87: API's Chris@87: Chris@87: 7) scipy.weave Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - can turn many numpy expressions into C code Chris@87: - dynamic compiling and loading of generated C code Chris@87: - can embed pure C code in Python module and have weave extract, generate Chris@87: interfaces and compile, etc. Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - Future very uncertain: it's the only part of Scipy not ported to Python 3 Chris@87: and is effectively deprecated in favor of Cython. Chris@87: Chris@87: 8) Psyco Chris@87: Chris@87: - Plusses: Chris@87: Chris@87: - Turns pure python into efficient machine code through jit-like Chris@87: optimizations Chris@87: - very fast when it optimizes well Chris@87: Chris@87: - Minuses: Chris@87: Chris@87: - Only on intel (windows?) Chris@87: - Doesn't do much for numpy? Chris@87: Chris@87: Interfacing to Fortran: Chris@87: ----------------------- Chris@87: The clear choice to wrap Fortran code is Chris@87: `f2py `_. Chris@87: Chris@87: Pyfort is an older alternative, but not supported any longer. Chris@87: Fwrap is a newer project that looked promising but isn't being developed any Chris@87: longer. Chris@87: Chris@87: Interfacing to C++: Chris@87: ------------------- Chris@87: 1) Cython Chris@87: 2) CXX Chris@87: 3) Boost.python Chris@87: 4) SWIG Chris@87: 5) SIP (used mainly in PyQT) Chris@87: Chris@87: """ Chris@87: from __future__ import division, absolute_import, print_function