The np_inline module was written as a simplified replacement for scipy.weave.inline for numeric computations on numpy arrays.
from np_inline import inline_debug as inline
code = r’printf("Program #%i: Hello world.\n", i);’
inline(’hello_world_example’,
args=(1, ),
py_types=((int, ’i’), ),
code=code)
Note that inline cannot be used without passing at least one argument in args. This is a feature.
import numpy as np
from np_inline import inline_debug as inline
arr = np.array((
(0, 1, 2, 3),
(4, 5, 6, 7),
(8, 9, 0, 1)), dtype=np.float32)
m = 0.5
code = r”’
int i, j;
for(i = 0; i < arr_shape(0); ++i) {
for(j = 0; j < arr_shape(1); ++j) {
arr(i, j) = m * arr(i, j);
}
}
”’
inline(’array_mult_example’,
args=(m, arr),
py_types=((float, ’m’), ),
np_types=((np.float32, 2, ’arr’), ),
code=code)
print(arr)
import numpy as np
from np_inline import inline_debug as inline
arr = np.arange(0, 10, 0.5, dtype=np.float32)
code = r”’
int i;
return_val = 0;
for(i=0; i < arr_shape(0); ++i) {
return_val += arr(i);
}
”’
inline(’return_val_test’,
args=(arr, ),
np_types=((np.float32, 1, ’arr’), ),
code=code,
return_type=float)
The primitive python types that can be passed as arguments are int and double, while almost any numeric type of numpy ndarray can be pass as an argument. The arguments must be sorted so the primitive python types precede the numpy types.
Python primitive types are converted to C types as follows:
int --> long int
float --> double
For each primitive python object passed in, the type and name must be provided in the py_types argument. For example, to pass an integer argument, i, and a float argument, f, the py_types argument would be
((int, ’i’), (float, ’f’))
Numpy defines C data types corresponding to each numeric type:
uint8 --> npy_uint8
uint16 --> npy_uint16
uint32 --> npy_uint32
uint64 --> npy_uint64
int8 --> npy_int8
int16 --> npy_int16
int32 --> npy_int32
int64 --> npy_int64
float32 --> npy_float32
float64 --> npy_float64
float128 --> npy_float128
For each numpy array passed in, the numpy type, dimension, and name must be provided in the np_types argument. For example, to pass in a 1D int32 array, arr, and a 3D float64 array, arr3d, the np_types argument would be
((np.int32, 1, ’arr’), (np.float64, 3, ’arr3d’))
For an N-dimensional numpy array, arr, several variables and a macro are available for use in the C code:
py_arr <-- The PyArrayObject pointer.
arr(i1, i2, ..., iN) <-- Macro indexing into the array.
arr_ndim <-- Macro giving the number of dimensions of arr.
arr_shape(i) <-- Macro giving the length of arr in dimension i.
Like arr.shape[i] in python.
The function can return three types of values, int, float, or None, depending on the value of the return_type argument. In order to set the return value in the C code, set the variable return_val to the return value in your C code.
In order to utilize the macros above to access array variables in functions given in the support code, the PyArrayObject pointer would need to be passed with the same name. That is, if the array is named arr, then the function would need to take an argument of the form
PyArrayObject *py_arr
Both the function’s C-code and the support-code can be stored in external files, and accessed using the code_path and support_code_path arguments.
In order to link external libraries, the appropriate keyword arguments need to be supplied to the distutils.core.Extension constructor. These arguments can be passed into the inline or inline_debug functions as a dictionary via the extension_kwargs argument.
There are two inline functions in np_inline. One is called inline, and the other is called inline_debug. The inline_debug function performs several checks of the incoming data before calling the inline function. It also forces the code to be compiled the first time it is called, instead of checking if the module exists on disk. A simple way to switch between the two is to use the following imports:
from np_inline import inline_debug as inline # Uses debugging.
from np_inline import inline # No debugging.
Generated source files are stored in ~/.np_inline using the unique name provided by the user. The C extension file is built and installed in the same directory using distutils.
Compilation is triggered only if the user-supplied unique name changes, or the module file doesn’t exist.