The following table contains the elementary types currently defined by Numba.
|Type Name||Alias||Result Type|
Types can be used to specify the signature of a function:
@jit('f8(f8[:])') def sum1d(array): sum = 0.0 for i in range(array.shape): sum += array[i] return sum
Types can also be used in Numba to declare local variables in a function:
@jit(locals=dict(array=double[:, :], scalar1=double)) def func(array): scalar1 = array[0, 0] # scalar is declared double scalar2 = double(array[0, 0])
Of course, declaring types in this example is unnecessary since the type inferencer knows the input type of array, and hence knows the type of array[i, j] to be the dtype of array.
Type declarations or casts can be useful in cases where the type inferencer doesn’t know the type, or if you want to override the type inferencer’s rules (e.g. force 32-bit floating point precision).
Variables declared in the locals dict have a single type throughout the entire function. However, any variable not declared in locals can assume different types, just like in Python:
@jit def variable_ressign(arg): arg = 1.0 arg = "hello" arg = object() var = arg var = "world"
However, there are some restrictions, namely that variables must have a unifyable type at control flow merge points. For example, the following code will not compile:
@jit def incompatible_types(arg): if arg > 10: x = 1+2j else: x = 3.3 return x # ERROR! Inconsistent type for x!
This code is invalid because strings and integers are not compatible. However, if we do not read x after the if block, the code will compile fine, since it does not need to unify the type:
@jit def compatible_types(arg): if arg > 10: x = "hello" else: x = arg x = func() return x
The same goes for loop carried dependencies and variables escaping loops, e.g.:
@jit def incompatible_types2(N): x = "hello" for i in range(N): print x # ERROR! Inconsistent type for x! x = i return x @jit def incompatible_types3(N): x = "hello" for i in range(N): x = i print x return x # ERROR! Inconsistent type for x if N <= 0
Cases where the type inferencer doesn’t know the type is often when you call a Python function or method that is not a numba function and numba doesn’t otherwise recognize.
Numba allows you to obtain the type of a expression or variable through the typeof function in a Numba function. This type can then be used for instance to cast other values:
type = numba.typeof(x + y) value = type(value)
When used outside of a Numba function, it returns the type the type inferencer would infer for that value:
>>> numba.typeof(1.0) double >>> numba.typeof(cmath.sqrt(-1)) complex128
Numba is in the process of being refactored to better define more complex types such as structs, pointers, strings and user defined classes. More on this soon...