def test_1d_slicing(self, flags=enable_pyobj_flags): pyfunc = slicing_1d_usecase arraytype = types.Array(types.int32, 1, 'C') argtys = (arraytype, types.int32, types.int32, types.int32) cr = compile_isolated(pyfunc, argtys, flags=flags) cfunc = cr.entry_point a = np.arange(10, dtype='i4') for indices in [ (0, 10, 1), (2, 3, 1), (10, 0, 1), (0, 10, -1), (0, 10, 2), (9, 0, -1), (-5, -2, 1), (0, -1, 1), ]: expected = pyfunc(a, *indices) self.assertPreciseEqual(cfunc(a, *indices), expected)
def compile_scalar_func(pyfunc, argtypes, restype): # First compile a scalar device function assert not any(isinstance(tp, types.Array) for tp in argtypes) assert not isinstance(restype, types.Array) device_func = cuda.jit(restype(*argtypes), device=True)(pyfunc) kernel_types = [ types.Array(tp, 1, "C") for tp in [restype] + list(argtypes) ] if len(argtypes) == 1: def kernel_func(out, a): i = cuda.grid(1) if i < out.shape[0]: out[i] = device_func(a[i]) elif len(argtypes) == 2: def kernel_func(out, a, b): i = cuda.grid(1) if i < out.shape[0]: out[i] = device_func(a[i], b[i]) else: assert 0 kernel = cuda.jit(tuple(kernel_types))(kernel_func) def kernel_wrapper(values): n = len(values) inputs = [ np.empty(n, dtype=numpy_support.as_dtype(tp)) for tp in argtypes ] output = np.empty(n, dtype=numpy_support.as_dtype(restype)) for i, vs in enumerate(values): for v, inp in zip(vs, inputs): inp[i] = v args = [output] + inputs kernel[int(math.ceil(n / 256)), 256](*args) return list(output) return kernel_wrapper
def check_1d_slicing_set_sequence(self, flags, seqty, seq): """ Generic sequence to 1d slice assignment """ pyfunc = slicing_1d_usecase_set dest_type = types.Array(types.int32, 1, 'C') argtys = (dest_type, seqty, types.int32, types.int32, types.int32) cr = compile_isolated(pyfunc, argtys, flags=flags) cfunc = cr.entry_point N = 10 k = len(seq) arg = np.arange(N, dtype=np.int32) args = (seq, 1, -N + k + 1, 1) expected = pyfunc(arg.copy(), *args) got = cfunc(arg.copy(), *args) self.assertPreciseEqual(expected, got) args = (seq, 1, -N + k, 1) with self.assertRaises(ValueError) as raises: cfunc(arg.copy(), *args)
def test_redefinition_analysis_same_block(self): # checks that a redefinition in a block with prunable potential doesn't # break def impl(array, x, a=None): b = 2 if x < 4: b = 12 if a is None: # known true a = 7 # live else: b = 15 # dead if a < 0: # valid as a result of the redefinition of 'a' return 10 return 30 + b + a self.assert_prune(impl, ( types.Array(types.float64, 2, 'C'), types.float64, types.NoneType('none'), ), [None, False, None], np.zeros((2, 3)), 1., None)
def load(self, context, builder, data, ind): arytyp = types.Array(dtype=self.dtype, ndim=self.ndim, layout="A") arycls = context.make_array(arytyp) array = arycls(context, builder) offseted_data = cgutils.pointer_add(builder, data, builder.mul(self.core_step, ind)) shape, strides = self._shape_and_strides(context, builder) itemsize = context.get_abi_sizeof(context.get_data_type(self.dtype)) context.populate_array(array, data=builder.bitcast(offseted_data, array.data.type), shape=shape, strides=strides, itemsize=context.get_constant( types.intp, itemsize), meminfo=None) return array._getvalue()
def test_redefinition_analysis_same_block(self): # checks that a redefinition in a block with prunable potential doesn't # break def impl(array, x, a=None): b = 0 if x < 4: b = 12 if a is None: a = 0 else: b = 12 if a < 0: return 10 return 30 + b + a self.assert_prune(impl, ( types.Array(types.float64, 2, 'C'), types.float64, types.NoneType('none'), ), [None, None, None], np.zeros((2, 3)), 1., None)
def generic(self, args, kws): ufunc = self.ufunc base_types, explicit_outputs, ndims, layout = self._handle_inputs( ufunc, args, kws) ufunc_loop = ufunc_find_matching_loop(ufunc, base_types) if ufunc_loop is None: raise TypingError("can't resolve ufunc {0} for types {1}".format(ufunc.__name__, args)) # check if all the types involved in the ufunc loop are supported in this mode if not supported_ufunc_loop(ufunc, ufunc_loop): msg = "ufunc '{0}' using the loop '{1}' not supported in this mode" raise TypingError(msg=msg.format(ufunc.__name__, ufunc_loop.ufunc_sig)) # if there is any explicit output type, check that it is valid explicit_outputs_np = [as_dtype(tp.dtype) for tp in explicit_outputs] # Numpy will happily use unsafe conversions (although it will actually warn) if not all (np.can_cast(fromty, toty, 'unsafe') for (fromty, toty) in zip(ufunc_loop.numpy_outputs, explicit_outputs_np)): msg = "ufunc '{0}' can't cast result to explicit result type" raise TypingError(msg=msg.format(ufunc.__name__)) # A valid loop was found that is compatible. The result of type inference should # be based on the explicit output types, and when not available with the type given # by the selected NumPy loop out = list(explicit_outputs) implicit_output_count = ufunc.nout - len(explicit_outputs) if implicit_output_count > 0: # XXX this is sometimes wrong for datetime64 and timedelta64, # as ufunc_find_matching_loop() doesn't do any type inference ret_tys = ufunc_loop.outputs[-implicit_output_count:] if ndims > 0: assert layout is not None ret_tys = [types.Array(dtype=ret_ty, ndim=ndims, layout=layout) for ret_ty in ret_tys] ret_tys = [resolve_output_type(self.context, args, ret_ty) for ret_ty in ret_tys] out.extend(ret_tys) return _ufunc_loop_sig(out, args)
def test_array_ndenumerate_empty(self): arr = np.zeros(0, dtype=np.int32) arr = arr.reshape(0, 2) arrty = types.Array(types.int32, 2, layout='C') self.check_array_ndenumerate_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='F') self.check_array_ndenumerate_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='A') self.check_array_ndenumerate_sum(arr, arrty) arr = arr.reshape(2, 0) arrty = types.Array(types.int32, 2, layout='C') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='F') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='A') self.check_array_flat_sum(arr, arrty)
def _type_me(self, argtys, kwtys): """ Implement AbstractTemplate.generic() for the typing class built by DUFunc._install_type(). Return the call-site signature after either validating the element-wise signature or compiling for it. """ assert not kwtys ufunc = self.ufunc _handle_inputs_result = npydecl.Numpy_rules_ufunc._handle_inputs( ufunc, argtys, kwtys) base_types, explicit_outputs, ndims, layout = _handle_inputs_result explicit_output_count = len(explicit_outputs) if explicit_output_count > 0: ewise_types = tuple(base_types[:-len(explicit_outputs)]) else: ewise_types = tuple(base_types) sig, cres = self.find_ewise_function(ewise_types) if sig is None: # Matching element-wise signature was not found; must # compile. if self._frozen: raise TypeError("cannot call %s with types %s" % (self, argtys)) self._compile_for_argtys(ewise_types) sig, cres = self.find_ewise_function(ewise_types) assert sig is not None if explicit_output_count > 0: outtys = list(explicit_outputs) elif ufunc.nout == 1: if ndims > 0: outtys = [types.Array(sig.return_type, ndims, layout)] else: outtys = [sig.return_type] else: raise NotImplementedError("typing gufuncs (nout > 1)") outtys.extend(argtys) return signature(*outtys)
def test_record_arg_transform(self): """ Testing that transforming the name of a record type argument to a function does not result in the fields of the record being used to uniquely identify them, and that no other condition results in the transformed name being excessively long. """ rec = numpy_support.from_dtype(recordtype3) transformed = mangle_type(rec) self.assertNotIn('first', transformed) self.assertNotIn('second', transformed) # len(transformed) is generally 10, but could be longer if a large # number of typecodes are in use. Checking <20 should provide enough # tolerance. self.assertLess(len(transformed), 20) struct_arr = types.Array(rec, 1, 'C') transformed = mangle_type(struct_arr) self.assertIn('Array', transformed) self.assertNotIn('first', transformed) self.assertNotIn('second', transformed) # Length is usually 50 - 5 chars tolerance as above. self.assertLess(len(transformed), 50)
def test_redefinition_analysis_different_block_can_exec(self): # checks that a redefinition in a block that may be executed prevents # pruning def impl(array, x, a=None): b = 0 if x > 5: a = 11 # a redefined, cannot tell statically if this will exec if x < 4: b = 12 if a is None: # cannot prune, cannot determine if re-defn occurred b += 5 else: b += 7 if a < 0: return 10 return 30 + b self.assert_prune(impl, ( types.Array(types.float64, 2, 'C'), types.float64, types.NoneType('none'), ), [None, None, None, None], np.zeros((2, 3)), 1., None)
def test_1d_slicing_broadcast(self, flags=enable_pyobj_flags): """ scalar to 1d slice assignment """ pyfunc = slicing_1d_usecase_set arraytype = types.Array(types.int32, 1, 'C') # Note heterogeneous types for the source scalar and the destination # array (int16 -> int32[:]) argtys = (arraytype, types.int16, types.int32, types.int32, types.int32) cr = compile_isolated(pyfunc, argtys, flags=flags) cfunc = cr.entry_point N = 10 arg = np.arange(N, dtype='i4') val = 42 bounds = [0, 2, N - 2, N, N + 1, N + 3, -2, -N + 2, -N, -N - 1, -N - 3] for start, stop in itertools.product(bounds, bounds): for step in (1, 2, -1, -2): args = val, start, stop, step pyleft = pyfunc(arg.copy(), *args) cleft = cfunc(arg.copy(), *args) self.assertPreciseEqual(pyleft, cleft)
def test_array_flat_empty(self): # Test .flat with various shapes of empty arrays, contiguous # and non-contiguous (see issue #846). arr = np.zeros(0, dtype=np.int32) arr = arr.reshape(0, 2) arrty = types.Array(types.int32, 2, layout='C') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='F') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='A') self.check_array_flat_sum(arr, arrty) arr = arr.reshape(2, 0) arrty = types.Array(types.int32, 2, layout='C') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='F') self.check_array_flat_sum(arr, arrty) arrty = types.Array(types.int32, 2, layout='A') self.check_array_flat_sum(arr, arrty)
def empty_inferred(typingctx, shape): """A version of numpy.empty whose dtype is inferred by the type system. Expects `shape` to be a int-tuple. There is special logic in the type-inferencer to handle the "refine"-ing of undefined dtype. """ from numba.np.arrayobj import _empty_nd_impl def codegen(context, builder, signature, args): # check that the return type is now defined arrty = signature.return_type assert arrty.is_precise() shapes = unpack_tuple(builder, args[0]) # redirect implementation to np.empty res = _empty_nd_impl(context, builder, arrty, shapes) return impl_ret_new_ref(context, builder, arrty, res._getvalue()) # make function signature nd = len(shape) array_ty = types.Array(ndim=nd, layout="C", dtype=types.undefined) sig = array_ty(shape) return sig, codegen
def sum_expand(self, args, kws): """ sum can be called with or without an axis parameter, and with or without a dtype parameter """ pysig = None if 'axis' in kws and 'dtype' not in kws: def sum_stub(axis): pass pysig = utils.pysignature(sum_stub) # rewrite args args = list(args) + [kws['axis']] elif 'dtype' in kws and 'axis' not in kws: def sum_stub(dtype): pass pysig = utils.pysignature(sum_stub) # rewrite args args = list(args) + [kws['dtype']] elif 'dtype' in kws and 'axis' in kws: def sum_stub(axis, dtype): pass pysig = utils.pysignature(sum_stub) # rewrite args args = list(args) + [kws['axis'], kws['dtype']] args_len = len(args) assert args_len <= 2 if args_len == 0: # No axis or dtype parameter so the return type of the summation is a scalar # of the type of the array. out = signature(_expand_integer(self.this.dtype), *args, recvr=self.this) elif args_len == 1 and 'dtype' not in kws: # There is an axis parameter, either arg or kwarg if self.this.ndim == 1: # 1d reduces to a scalar return_type = self.this.dtype else: # the return type of this summation is an array of dimension one # less than the input array. return_type = types.Array(dtype=_expand_integer(self.this.dtype), ndim=self.this.ndim-1, layout='C') out = signature(return_type, *args, recvr=self.this) elif args_len == 1 and 'dtype' in kws: # No axis parameter so the return type of the summation is a scalar # of the dtype parameter. from .npydecl import parse_dtype dtype, = args dtype = parse_dtype(dtype) out = signature(dtype, *args, recvr=self.this) elif args_len == 2: # There is an axis and dtype parameter, either arg or kwarg from .npydecl import parse_dtype dtype = parse_dtype(args[1]) return_type = dtype if self.this.ndim != 1: # 1d reduces to a scalar, 2d and above reduce dim by 1 # the return type of this summation is an array of dimension one # less than the input array. return_type = types.Array(dtype=return_type, ndim=self.this.ndim-1, layout='C') out = signature(return_type, *args, recvr=self.this) else: pass return out.replace(pysig=pysig)
def test_properties(self): def check(ty, dtypes, ndim, layout, indexers=None): self.assertEqual(ty.ndim, ndim) self.assertEqual(ty.layout, layout) self.assertEqual(ty.dtypes, dtypes) views = [types.Array(dtype, 0, "C") for dtype in dtypes] if len(views) > 1: self.assertEqual( ty.yield_type, types.BaseTuple.from_types(views)) else: self.assertEqual(ty.yield_type, views[0]) if indexers is not None: self.assertEqual(ty.indexers, indexers) f32 = types.float32 c64 = types.complex64 i16 = types.int16 a = types.Array(f32, 1, "C") b = types.Array(f32, 2, "C") c = types.Array(c64, 2, "F") d = types.Array(i16, 2, "A") e = types.Array(i16, 0, "C") f = types.Array(f32, 1, "A") g = types.Array(f32, 0, "C") # 0-dim iterator ty = types.NumpyNdIterType((e,)) check(ty, (i16,), 0, "C", [('0d', 0, 0, [0])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((e, g)) check(ty, (i16, f32), 0, "C", [('0d', 0, 0, [0, 1])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((e, c64)) check(ty, (i16, c64), 0, "C", [('0d', 0, 0, [0]), ('scalar', 0, 0, [1])]) self.assertFalse(ty.need_shaped_indexing) # 1-dim iterator ty = types.NumpyNdIterType((a,)) check(ty, (f32,), 1, "C", [('flat', 0, 1, [0])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((a, a)) check(ty, (f32, f32), 1, "C", [('flat', 0, 1, [0, 1])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((a, e, e, c64)) check(ty, (f32, i16, i16, c64), 1, "C", [('flat', 0, 1, [0]), # a ('0d', 0, 0, [1, 2]), # e, e ('scalar', 0, 0, [3]), # c64 ]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((a, f)) check(ty, (f32, f32), 1, "C", [('flat', 0, 1, [0]), ('indexed', 0, 1, [1])]) self.assertTrue(ty.need_shaped_indexing) ty = types.NumpyNdIterType((f,)) check(ty, (f32,), 1, "C", [('indexed', 0, 1, [0])]) self.assertTrue(ty.need_shaped_indexing) # 2-dim C-order iterator ty = types.NumpyNdIterType((b,)) check(ty, (f32,), 2, "C", [('flat', 0, 2, [0])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((b, c)) check( ty, (f32, c64), 2, "C", [ ('flat', 0, 2, [0]), ('indexed', 0, 2, [1])]) self.assertTrue(ty.need_shaped_indexing) ty = types.NumpyNdIterType((d,)) check(ty, (i16,), 2, "C", [('indexed', 0, 2, [0])]) self.assertTrue(ty.need_shaped_indexing) ty = types.NumpyNdIterType((b, c, d, d, e)) check(ty, (f32, c64, i16, i16, i16), 2, "C", [('flat', 0, 2, [0]), # b ('indexed', 0, 2, [1, 2, 3]), # c, d, d ('0d', 0, 0, [4]), # e ]) self.assertTrue(ty.need_shaped_indexing) ty = types.NumpyNdIterType((a, b, c, d, d, f)) check(ty, (f32, f32, c64, i16, i16, f32), 2, "C", [('flat', 1, 2, [0]), # a ('flat', 0, 2, [1]), # b ('indexed', 0, 2, [2, 3, 4]), # c, d, d ('indexed', 1, 2, [5]), # f ]) self.assertTrue(ty.need_shaped_indexing) # 2-dim F-order iterator ty = types.NumpyNdIterType((c,)) check(ty, (c64,), 2, "F", [('flat', 0, 2, [0])]) self.assertFalse(ty.need_shaped_indexing) ty = types.NumpyNdIterType((c, b, c, f)) check(ty, (c64, f32, c64, f32), 2, "F", [('flat', 0, 2, [0, 2]), # c, c ('indexed', 0, 2, [1]), # b ('indexed', 0, 1, [3]), # f ]) self.assertTrue(ty.need_shaped_indexing) ty = types.NumpyNdIterType((b, c, c, d, d, a, e)) check(ty, (f32, c64, c64, i16, i16, f32, i16), 2, "F", [('indexed', 0, 2, [0, 3, 4]), # b, d, d ('flat', 0, 2, [1, 2]), # c, c ('flat', 0, 1, [5]), # a ('0d', 0, 0, [6]), # e ]) self.assertTrue(ty.need_shaped_indexing)
def test_arrays(self): for ndim in (0, 1, 2): for layout in ('A', 'C', 'F'): ty = types.Array(types.int16, ndim, layout) self.check_pickling(ty)
def test_bad_float_index_npm(self): with self.assertTypingError() as raises: compile_isolated(bad_float_index, (types.Array(types.float64, 2, 'C'), )) self.assertIn('unsupported array index type float64', str(raises.exception))
def test_list_type_getitem(self): for listty in (types.int64, types.Array(types.float64, 1, 'C')): l_int = types.List(listty) self.assertTrue(isinstance(l_int, types.List)) self.assertTrue(isinstance(l_int[0], type(listty)))
class Test2DArrayOfComplex128(test_factory()): fe_type = types.Array(types.complex128, 2, "C")
'v2': types.uint64, 'v3': types.uint64, }) def _DOUBLE_ROUND(v0, v1, v2, v3): v0, v1, v2, v3 = _HALF_ROUND(v0, v1, v2, v3, 13, 16) v2, v1, v0, v3 = _HALF_ROUND(v2, v1, v0, v3, 17, 21) v0, v1, v2, v3 = _HALF_ROUND(v0, v1, v2, v3, 13, 16) v2, v1, v0, v3 = _HALF_ROUND(v2, v1, v0, v3, 17, 21) return v0, v1, v2, v3 @register_jitable(locals={'v0': types.uint64, 'v1': types.uint64, 'v2': types.uint64, 'v3': types.uint64, 'b': types.uint64, 'mi': types.uint64, 'tmp': types.Array(types.uint64, 1, 'C'), 't': types.uint64, 'mask': types.uint64, 'jmp': types.uint64, 'ohexefef': types.uint64}) def _siphash24(k0, k1, src, src_sz): b = types.uint64(src_sz) << 56 v0 = k0 ^ types.uint64(0x736f6d6570736575) v1 = k1 ^ types.uint64(0x646f72616e646f6d) v2 = k0 ^ types.uint64(0x6c7967656e657261) v3 = k1 ^ types.uint64(0x7465646279746573) idx = 0 while (src_sz >= 8): mi = grab_uint64_t(src, idx) idx += 1
def test_base_cases(self): def test_0(): a = np.zeros(0) b = np.zeros(1) m = 0 n = 1 c = np.zeros((m, n)) return self._compile_and_test(test_0, (), equivs=[self.with_equiv('a', (0,)), self.with_equiv('b', (1,)), self.with_equiv('c', (0, 1))]) def test_1(n): a = np.zeros(n) b = np.zeros(n) return a + b self._compile_and_test(test_1, (types.intp,), asserts=None) def test_2(m, n): a = np.zeros(n) b = np.zeros(m) return a + b self._compile_and_test(test_2, (types.intp, types.intp), asserts=[self.with_assert('a', 'b')]) def test_3(n): a = np.zeros(n) return a + n self._compile_and_test(test_3, (types.intp,), asserts=None) def test_4(n): a = np.zeros(n) b = a + 1 c = a + 2 return a + c self._compile_and_test(test_4, (types.intp,), asserts=None) def test_5(n): a = np.zeros((n, n)) m = n b = np.zeros((m, n)) return a + b self._compile_and_test(test_5, (types.intp,), asserts=None) def test_6(m, n): a = np.zeros(n) b = np.zeros(m) d = a + b e = a - b return d + e self._compile_and_test(test_6, (types.intp, types.intp), asserts=[self.with_assert('a', 'b'), self.without_assert('d', 'e')]) def test_7(m, n): a = np.zeros(n) b = np.zeros(m) if m == 10: d = a + b else: d = a - b return d + a self._compile_and_test(test_7, (types.intp, types.intp), asserts=[self.with_assert('a', 'b'), self.without_assert('d', 'a')]) def test_8(m, n): a = np.zeros(n) b = np.zeros(m) if m == 10: d = b + a else: d = a + a return b + d self._compile_and_test(test_8, (types.intp, types.intp), asserts=[self.with_assert('b', 'a'), self.with_assert('b', 'd')]) def test_9(m): A = np.ones(m) s = 0 while m < 2: m += 1 B = np.ones(m) s += np.sum(A + B) return s self._compile_and_test(test_9, (types.intp,), asserts=[self.with_assert('A', 'B')]) def test_10(m, n): p = m - 1 q = n + 1 r = q + 1 A = np.zeros(p) B = np.zeros(q) C = np.zeros(r) D = np.zeros(m) s = np.sum(A + B) t = np.sum(C + D) return s + t self._compile_and_test(test_10, (types.intp,types.intp,), asserts=[self.with_assert('A', 'B'), self.without_assert('C', 'D')]) def test_11(): a = np.ones(5) b = np.ones(5) c = a[1:] d = b[:-1] e = len(c) f = len(d) return e == f self._compile_and_test(test_11, (), equivs=[self.with_equiv('e', 'f')]) def test_12(): a = np.ones(25).reshape((5,5)) b = np.ones(25).reshape((5,5)) c = a[1:,:] d = b[:-1,:] e = c.shape[0] f = d.shape[0] g = len(d) return e == f self._compile_and_test(test_12, (), equivs=[self.with_equiv('e', 'f', 'g')]) def test_tup_arg(T): T2 = T return T2[0] int_arr_typ = types.Array(types.intp, 1, 'C') self._compile_and_test(test_tup_arg, (types.Tuple((int_arr_typ, int_arr_typ)),), asserts=None) T = namedtuple("T", ['a','b']) def test_namedtuple(n): r = T(n, n) return r[0] self._compile_and_test(test_namedtuple, (types.intp,), equivs=[self.with_equiv('r', ('n', 'n'))],) # np.where is tricky since it returns tuple of arrays def test_np_where_tup_return(A): c = np.where(A) return len(c[0]) self._compile_and_test(test_np_where_tup_return, (types.Array(types.intp, 1, 'C'),), asserts=None) def test_shape(A): (m, n) = A.shape B = np.ones((m, n)) return A + B self._compile_and_test(test_shape, (types.Array(types.intp, 2, 'C'),), asserts=None) def test_cond(l, m, n): A = np.ones(l) B = np.ones(m) C = np.ones(n) if l == m: r = np.sum(A + B) else: r = 0 if m != n: s = 0 else: s = np.sum(B + C) t = 0 if l == m: if m == n: t = np.sum(A + B + C) return r + s + t self._compile_and_test(test_cond, (types.intp, types.intp, types.intp), asserts=None) def test_assert_1(m, n): assert(m == n) A = np.ones(m) B = np.ones(n) return np.sum(A + B) self._compile_and_test(test_assert_1, (types.intp, types.intp), asserts=None) def test_assert_2(A, B): assert(A.shape == B.shape) return np.sum(A + B) self._compile_and_test(test_assert_2, (types.Array(types.intp, 1, 'C'), types.Array(types.intp, 1, 'C'),), asserts=None) self._compile_and_test(test_assert_2, (types.Array(types.intp, 2, 'C'), types.Array(types.intp, 2, 'C'),), asserts=None) # expected failure with self.assertRaises(AssertionError) as raises: self._compile_and_test(test_assert_2, (types.Array(types.intp, 1, 'C'), types.Array(types.intp, 2, 'C'),), asserts=None) msg = "Dimension mismatch" self.assertIn(msg, str(raises.exception))
class Test0DArrayOfInt32(test_factory()): fe_type = types.Array(types.int32, 0, "C")
def calc_array_sizeof(self, ndim): ''' Calculate the size of an array struct on the CPU target ''' aryty = types.Array(types.int32, ndim, 'A') return self.get_abi_sizeof(self.get_value_type(aryty))
def test_numpy_calls(self): def test_zeros(n): a = np.zeros(n) b = np.zeros((n, n)) c = np.zeros(shape=(n, n)) self._compile_and_test(test_zeros, (types.intp,), equivs=[self.with_equiv('a', 'n'), self.with_equiv('b', ('n', 'n')), self.with_equiv('b', 'c')]) def test_0d_array(n): a = np.array(1) b = np.ones(2) return a + b self._compile_and_test(test_0d_array, (types.intp,), equivs=[self.without_equiv('a', 'b')], asserts=[self.without_shapecall('a')]) def test_ones(n): a = np.ones(n) b = np.ones((n, n)) c = np.ones(shape=(n, n)) self._compile_and_test(test_ones, (types.intp,), equivs=[self.with_equiv('a', 'n'), self.with_equiv('b', ('n', 'n')), self.with_equiv('b', 'c')]) def test_empty(n): a = np.empty(n) b = np.empty((n, n)) c = np.empty(shape=(n, n)) self._compile_and_test(test_empty, (types.intp,), equivs=[self.with_equiv('a', 'n'), self.with_equiv('b', ('n', 'n')), self.with_equiv('b', 'c')]) def test_eye(n): a = np.eye(n) b = np.eye(N=n) c = np.eye(N=n, M=n) d = np.eye(N=n, M=n + 1) self._compile_and_test(test_eye, (types.intp,), equivs=[self.with_equiv('a', ('n', 'n')), self.with_equiv('b', ('n', 'n')), self.with_equiv('b', 'c'), self.without_equiv('b', 'd')]) def test_identity(n): a = np.identity(n) self._compile_and_test(test_identity, (types.intp,), equivs=[self.with_equiv('a', ('n', 'n'))]) def test_diag(n): a = np.identity(n) b = np.diag(a) c = np.diag(b) d = np.diag(a, k=1) self._compile_and_test(test_diag, (types.intp,), equivs=[self.with_equiv('b', ('n',)), self.with_equiv('c', ('n', 'n'))], asserts=[self.with_shapecall('d'), self.without_shapecall('c')]) def test_array_like(a): b = np.empty_like(a) c = np.zeros_like(a) d = np.ones_like(a) e = np.full_like(a, 1) f = np.asfortranarray(a) self._compile_and_test(test_array_like, (types.Array(types.intp, 2, 'C'),), equivs=[ self.with_equiv('a', 'b', 'd', 'e', 'f')], asserts=[self.with_shapecall('a'), self.without_shapecall('b')]) def test_reshape(n): a = np.ones(n * n) b = a.reshape((n, n)) return a.sum() + b.sum() self._compile_and_test(test_reshape, (types.intp,), equivs=[self.with_equiv('b', ('n', 'n'))], asserts=[self.without_shapecall('b')]) def test_transpose(m, n): a = np.ones((m, n)) b = a.T c = a.transpose() # Numba njit cannot compile explicit transpose call! # c = np.transpose(b) self._compile_and_test(test_transpose, (types.intp, types.intp), equivs=[self.with_equiv('a', ('m', 'n')), self.with_equiv('b', ('n', 'm')), self.with_equiv('c', ('n', 'm'))]) def test_transpose_3d(m, n, k): a = np.ones((m, n, k)) b = a.T c = a.transpose() d = a.transpose(2,0,1) dt = a.transpose((2,0,1)) e = a.transpose(0,2,1) et = a.transpose((0,2,1)) # Numba njit cannot compile explicit transpose call! # c = np.transpose(b) self._compile_and_test(test_transpose_3d, (types.intp, types.intp, types.intp), equivs=[self.with_equiv('a', ('m', 'n', 'k')), self.with_equiv('b', ('k', 'n', 'm')), self.with_equiv('c', ('k', 'n', 'm')), self.with_equiv('d', ('k', 'm', 'n')), self.with_equiv('dt', ('k', 'm', 'n')), self.with_equiv('e', ('m', 'k', 'n')), self.with_equiv('et', ('m', 'k', 'n'))]) def test_random(n): a0 = np.random.rand(n) a1 = np.random.rand(n, n) b0 = np.random.randn(n) b1 = np.random.randn(n, n) c0 = np.random.ranf(n) c1 = np.random.ranf((n, n)) c2 = np.random.ranf(size=(n, n)) d0 = np.random.random_sample(n) d1 = np.random.random_sample((n, n)) d2 = np.random.random_sample(size=(n, n)) e0 = np.random.sample(n) e1 = np.random.sample((n, n)) e2 = np.random.sample(size=(n, n)) f0 = np.random.random(n) f1 = np.random.random((n, n)) f2 = np.random.random(size=(n, n)) g0 = np.random.standard_normal(n) g1 = np.random.standard_normal((n, n)) g2 = np.random.standard_normal(size=(n, n)) h0 = np.random.chisquare(10, n) h1 = np.random.chisquare(10, (n, n)) h2 = np.random.chisquare(10, size=(n, n)) i0 = np.random.weibull(10, n) i1 = np.random.weibull(10, (n, n)) i2 = np.random.weibull(10, size=(n, n)) j0 = np.random.power(10, n) j1 = np.random.power(10, (n, n)) j2 = np.random.power(10, size=(n, n)) k0 = np.random.geometric(0.1, n) k1 = np.random.geometric(0.1, (n, n)) k2 = np.random.geometric(0.1, size=(n, n)) l0 = np.random.exponential(10, n) l1 = np.random.exponential(10, (n, n)) l2 = np.random.exponential(10, size=(n, n)) m0 = np.random.poisson(10, n) m1 = np.random.poisson(10, (n, n)) m2 = np.random.poisson(10, size=(n, n)) n0 = np.random.rayleigh(10, n) n1 = np.random.rayleigh(10, (n, n)) n2 = np.random.rayleigh(10, size=(n, n)) o0 = np.random.normal(0, 1, n) o1 = np.random.normal(0, 1, (n, n)) o2 = np.random.normal(0, 1, size=(n, n)) p0 = np.random.uniform(0, 1, n) p1 = np.random.uniform(0, 1, (n, n)) p2 = np.random.uniform(0, 1, size=(n, n)) q0 = np.random.beta(0.1, 1, n) q1 = np.random.beta(0.1, 1, (n, n)) q2 = np.random.beta(0.1, 1, size=(n, n)) r0 = np.random.binomial(0, 1, n) r1 = np.random.binomial(0, 1, (n, n)) r2 = np.random.binomial(0, 1, size=(n, n)) s0 = np.random.f(0.1, 1, n) s1 = np.random.f(0.1, 1, (n, n)) s2 = np.random.f(0.1, 1, size=(n, n)) t0 = np.random.gamma(0.1, 1, n) t1 = np.random.gamma(0.1, 1, (n, n)) t2 = np.random.gamma(0.1, 1, size=(n, n)) u0 = np.random.lognormal(0, 1, n) u1 = np.random.lognormal(0, 1, (n, n)) u2 = np.random.lognormal(0, 1, size=(n, n)) v0 = np.random.laplace(0, 1, n) v1 = np.random.laplace(0, 1, (n, n)) v2 = np.random.laplace(0, 1, size=(n, n)) w0 = np.random.randint(0, 10, n) w1 = np.random.randint(0, 10, (n, n)) w2 = np.random.randint(0, 10, size=(n, n)) x0 = np.random.triangular(-3, 0, 10, n) x1 = np.random.triangular(-3, 0, 10, (n, n)) x2 = np.random.triangular(-3, 0, 10, size=(n, n)) last = ord('x') + 1 vars1d = [('n',)] + [chr(x) + '0' for x in range(ord('a'), last)] vars2d = [('n', 'n')] + [chr(x) + '1' for x in range(ord('a'), last)] vars2d += [chr(x) + '1' for x in range(ord('c'), last)] self._compile_and_test(test_random, (types.intp,), equivs=[self.with_equiv(*vars1d), self.with_equiv(*vars2d)]) def test_concatenate(m, n): a = np.ones(m) b = np.ones(n) c = np.concatenate((a, b)) d = np.ones((2, n)) e = np.ones((3, n)) f = np.concatenate((d, e)) # Numba njit cannot compile concatenate with single array! # g = np.ones((3,4,5)) # h = np.concatenate(g) i = np.ones((m, 2)) j = np.ones((m, 3)) k = np.concatenate((i, j), axis=1) l = np.ones((m, n)) o = np.ones((m, n)) p = np.concatenate((l, o)) # Numba njit cannot support list argument! # q = np.concatenate([d, e]) self._compile_and_test(test_concatenate, (types.intp, types.intp), equivs=[self.with_equiv('f', (5, 'n')), #self.with_equiv('h', (3 + 4 + 5, )), self.with_equiv('k', ('m', 5))], asserts=[self.with_shapecall('c'), self.without_shapecall('f'), self.without_shapecall('k'), self.with_shapecall('p')]) def test_vsd_stack(): k = np.ones((2,)) l = np.ones((2, 3)) o = np.ones((2, 3, 4)) p = np.vstack((k, k)) q = np.vstack((l, l)) r = np.hstack((k, k)) s = np.hstack((l, l)) t = np.dstack((k, k)) u = np.dstack((l, l)) v = np.dstack((o, o)) self._compile_and_test(test_vsd_stack, (), equivs=[self.with_equiv('p', (2, 2)), self.with_equiv('q', (4, 3)), self.with_equiv('r', (4,)), self.with_equiv('s', (2, 6)), self.with_equiv('t', (1, 2, 2)), self.with_equiv('u', (2, 3, 2)), self.with_equiv('v', (2, 3, 8)), ]) def test_stack(m, n): a = np.ones(m) b = np.ones(n) c = np.stack((a, b)) d = np.ones((m, n)) e = np.ones((m, n)) f = np.stack((d, e)) g = np.stack((d, e), axis=0) h = np.stack((d, e), axis=1) i = np.stack((d, e), axis=2) j = np.stack((d, e), axis=-1) self._compile_and_test(test_stack, (types.intp, types.intp), equivs=[self.with_equiv('m', 'n'), self.with_equiv('c', (2, 'm')), self.with_equiv( 'f', 'g', (2, 'm', 'n')), self.with_equiv( 'h', ('m', 2, 'n')), self.with_equiv( 'i', 'j', ('m', 'n', 2)), ]) def test_linspace(m, n): a = np.linspace(m, n) b = np.linspace(m, n, 10) # Numba njit does not support num keyword to linspace call! # c = np.linspace(m,n,num=10) self._compile_and_test(test_linspace, (types.float64, types.float64), equivs=[self.with_equiv('a', (50,)), self.with_equiv('b', (10,))]) def test_dot(l, m, n): a = np.dot(np.ones(1), np.ones(1)) b = np.dot(np.ones(2), np.ones((2, 3))) # Numba njit does not support higher dimensional inputs #c = np.dot(np.ones(2),np.ones((3,2,4))) #d = np.dot(np.ones(2),np.ones((3,5,2,4))) e = np.dot(np.ones((1, 2)), np.ones(2,)) #f = np.dot(np.ones((1,2,3)),np.ones(3,)) #g = np.dot(np.ones((1,2,3,4)),np.ones(4,)) h = np.dot(np.ones((2, 3)), np.ones((3, 4))) i = np.dot(np.ones((m, n)), np.ones((n, m))) j = np.dot(np.ones((m, m)), np.ones((l, l))) self._compile_and_test(test_dot, (types.intp, types.intp, types.intp), equivs=[self.without_equiv('a', (1,)), # not array self.with_equiv('b', (3,)), self.with_equiv('e', (1,)), self.with_equiv('h', (2, 4)), self.with_equiv('i', ('m', 'm')), self.with_equiv('j', ('m', 'm')), ], asserts=[self.with_assert('m', 'l')]) def test_broadcast(m, n): a = np.ones((m, n)) b = np.ones(n) c = a + b d = np.ones((1, n)) e = a + c - d self._compile_and_test(test_broadcast, (types.intp, types.intp), equivs=[self.with_equiv('a', 'c', 'e')], asserts=None)
def test_records(self): recordtype = np.dtype([('a', np.float64), ('b', np.int32), ('c', np.complex64), ('d', (np.str, 5))]) ty = numpy_support.from_dtype(recordtype) self.check_pickling(ty) self.check_pickling(types.Array(ty, 1, 'A'))
def as_array(self): return types.Array(self.dtype, 1, self.layout)
def _generic_array(context, builder, shape, dtype, symbol_name, addrspace, can_dynsized=False): elemcount = reduce(operator.mul, shape, 1) # Check for valid shape for this type of allocation. # Only 1d arrays can be dynamic. dynamic_smem = elemcount <= 0 and can_dynsized and len(shape) == 1 if elemcount <= 0 and not dynamic_smem: raise ValueError("array length <= 0") # Check that we support the requested dtype other_supported_type = isinstance(dtype, (types.Record, types.Boolean)) if dtype not in types.number_domain and not other_supported_type: raise TypeError("unsupported type: %s" % dtype) lldtype = context.get_data_type(dtype) laryty = Type.array(lldtype, elemcount) if addrspace == nvvm.ADDRSPACE_LOCAL: # Special case local address space allocation to use alloca # NVVM is smart enough to only use local memory if no register is # available dataptr = cgutils.alloca_once(builder, laryty, name=symbol_name) else: lmod = builder.module # Create global variable in the requested address space gvmem = lmod.add_global_variable(laryty, symbol_name, addrspace) # Specify alignment to avoid misalignment bug align = context.get_abi_sizeof(lldtype) # Alignment is required to be a power of 2 for shared memory. If it is # not a power of 2 (e.g. for a Record array) then round up accordingly. gvmem.align = 1 << (align - 1).bit_length() if dynamic_smem: gvmem.linkage = lc.LINKAGE_EXTERNAL else: ## Comment out the following line to workaround a NVVM bug ## which generates a invalid symbol name when the linkage ## is internal and in some situation. ## See _get_unique_smem_id() # gvmem.linkage = lc.LINKAGE_INTERNAL gvmem.initializer = lc.Constant.undef(laryty) # Convert to generic address-space conv = nvvmutils.insert_addrspace_conv(lmod, Type.int(8), addrspace) addrspaceptr = gvmem.bitcast(Type.pointer(Type.int(8), addrspace)) dataptr = builder.call(conv, [addrspaceptr]) targetdata = _get_target_data(context) lldtype = context.get_data_type(dtype) itemsize = lldtype.get_abi_size(targetdata) # Compute strides laststride = itemsize rstrides = [] for i, lastsize in enumerate(reversed(shape)): rstrides.append(laststride) laststride *= lastsize strides = [s for s in reversed(rstrides)] kstrides = [context.get_constant(types.intp, s) for s in strides] # Compute shape if dynamic_smem: # Compute the shape based on the dynamic shared memory configuration. # Unfortunately NVVM does not provide an intrinsic for the # %dynamic_smem_size register, so we must read it using inline # assembly. get_dynshared_size = InlineAsm.get(Type.function(Type.int(), []), "mov.u32 $0, %dynamic_smem_size;", '=r', side_effect=True) dynsmem_size = builder.zext(builder.call(get_dynshared_size, []), Type.int(width=64)) # Only 1-D dynamic shared memory is supported so the following is a # sufficient construction of the shape kitemsize = context.get_constant(types.intp, itemsize) kshape = [builder.udiv(dynsmem_size, kitemsize)] else: kshape = [context.get_constant(types.intp, s) for s in shape] # Create array object ndim = len(shape) aryty = types.Array(dtype=dtype, ndim=ndim, layout='C') ary = context.make_array(aryty)(context, builder) context.populate_array(ary, data=builder.bitcast(dataptr, ary.data.type), shape=kshape, strides=kstrides, itemsize=context.get_constant(types.intp, itemsize), meminfo=None) return ary._getvalue()
def test_layout(self): """ Check an appropriate layout is inferred for the result of array indexing. """ func = arraydecl.get_array_index_type cty = types.Array(types.float64, 3, 'C') fty = types.Array(types.float64, 3, 'F') aty = types.Array(types.float64, 3, 'A') indices = [ # Tuples of (indexing arguments, keeps "C" layout, keeps "F" layout) ((), True, True), ((ellipsis, ), True, True), # Indexing from the left => can sometimes keep "C" layout ((intp, ), True, False), ((slice2_type, ), True, False), ((intp, slice2_type), True, False), ((slice2_type, intp), False, False), ((slice2_type, slice2_type), False, False), # Strided slices = > "A" layout ((intp, slice3_type), False, False), ((slice3_type, ), False, False), # Indexing from the right => can sometimes keep "F" layout (( ellipsis, intp, ), False, True), (( ellipsis, slice2_type, ), False, True), (( ellipsis, intp, slice2_type, ), False, False), (( ellipsis, slice2_type, intp, ), False, True), (( ellipsis, slice2_type, slice2_type, ), False, False), # Strided slices = > "A" layout (( ellipsis, slice3_type, ), False, False), (( ellipsis, slice3_type, intp, ), False, False), # Indexing from both sides => only if all dimensions are indexed (( intp, ellipsis, intp, ), False, False), (( slice2_type, ellipsis, slice2_type, ), False, False), (( intp, intp, slice2_type, ), True, False), (( intp, ellipsis, intp, slice2_type, ), True, False), (( slice2_type, intp, intp, ), False, True), (( slice2_type, intp, ellipsis, intp, ), False, True), (( intp, slice2_type, intp, ), False, False), # Strided slices = > "A" layout (( slice3_type, intp, intp, ), False, False), (( intp, intp, slice3_type, ), False, False), ] for index_tuple, keep_c, _ in indices: index = types.Tuple(index_tuple) r = func(cty, index) self.assertEqual(tuple(r.index), index_tuple) self.assertEqual(r.result.layout, 'C' if keep_c else 'A', index_tuple) self.assertFalse(r.advanced) for index_tuple, _, keep_f in indices: index = types.Tuple(index_tuple) r = func(fty, index) self.assertEqual(tuple(r.index), index_tuple) self.assertEqual(r.result.layout, 'F' if keep_f else 'A', index_tuple) self.assertFalse(r.advanced) for index_tuple, _, _ in indices: index = types.Tuple(index_tuple) r = func(aty, index) self.assertEqual(tuple(r.index), index_tuple) self.assertEqual(r.result.layout, 'A') self.assertFalse(r.advanced)
def test_arrays(self): aty = types.Array(i32, 3, "C") bty = types.Array(i32, 3, "A") self.assert_unify(aty, bty, bty) aty = types.Array(i32, 3, "C") bty = types.Array(i32, 3, "F") self.assert_unify(aty, bty, types.Array(i32, 3, "A")) aty = types.Array(i32, 3, "C") bty = types.Array(i32, 3, "C", readonly=True) self.assert_unify(aty, bty, bty) aty = types.Array(i32, 3, "A") bty = types.Array(i32, 3, "C", readonly=True) self.assert_unify(aty, bty, types.Array(i32, 3, "A", readonly=True)) # Failures aty = types.Array(i32, 2, "C") bty = types.Array(i32, 3, "C") self.assert_unify_failure(aty, bty) aty = types.Array(i32, 2, "C") bty = types.Array(u32, 2, "C") self.assert_unify_failure(aty, bty)