def test_lift_arrfunc(self): # First get a ckernel from numpy requiregil = False af = _lowlevel.arrfunc_from_ufunc(np.ldexp, (np.float64, np.float64, np.int32), requiregil) self.assertEqual(nd.as_py(af.proto), ndt.type("(float64, int32) -> float64")) # Now lift it af_lifted = _lowlevel.lift_arrfunc(af) self.assertEqual(nd.as_py(af_lifted.proto), ndt.type("(Dims... * float64, Dims... * int32) -> Dims... * float64")) # Create some compatible arguments in0 = nd.array([[1, 2, 3], [4, 5], [6], [7,9,10]], type='fixed * var * float64') in1 = nd.array([[-1], [10], [100], [-12]], type='fixed * 1 * int32') # Instantiate and call the kernel on these arguments out = af_lifted(in0, in1) # Verify that we got the expected result self.assertEqual(nd.as_py(out), [[0.5, 1.0, 1.5], [4096.0, 5120.0], [float(6*2**100)], [0.001708984375, 0.002197265625, 0.00244140625]])
def test_arrfunc_from_instantiate_pyfunc(self): # Test wrapping make_assignment_ckernel as an arrfunc def instantiate_assignment(out_ckb, ckb_offset, dst_tp, dst_arrmeta, src_tp, src_arrmeta, kernreq, ectx): out_ckb = _lowlevel.CKernelBuilderStruct.from_address(out_ckb) return _lowlevel.make_assignment_ckernel(out_ckb, ckb_offset, dst_tp, dst_arrmeta, src_tp[0], src_arrmeta[0], kernreq, ectx) af = _lowlevel.arrfunc_from_instantiate_pyfunc( instantiate_assignment, "(date) -> string") self.assertEqual(nd.as_py(af.proto), ndt.type("(date) -> string")) in0 = nd.array('2012-11-05', ndt.date) out = af(in0) self.assertEqual(nd.as_py(out), '2012-11-05') # Also test it as a lifted kernel af_lifted = _lowlevel.lift_arrfunc(af) self.assertEqual(nd.as_py(af_lifted.proto), ndt.type("(Dims... * date) -> Dims... * string")) from datetime import date in0 = nd.array([['2013-03-11', date(2010, 10, 10)], [date(1999, 12, 31)], []], type='3 * var * date') out = af_lifted(in0) self.assertEqual(nd.as_py(out), [['2013-03-11', '2010-10-10'], ['1999-12-31'], []])
def op_ckernel(self, op): op_ndim = len(op.type.shape) result_ndim = self.env.get('result-ndim', 0) ckernel, args = op.args in_types = [self.get_arg_type(arg) for arg in args[1:]] out_type = ndt.type(str(args[0].type)) if isinstance(ckernel, dict): tag = ckernel['tag'] if tag == 'elwise': ck = ckernel['ckernel'] if op.metadata['rank'] < op_ndim and \ self.env.get('stream-outer', False) and result_ndim == op_ndim: # Replace the leading dimension type with 'strided' in each operand # if we're streaming it for processing BLZ # TODO: Add dynd tp.subarray(N) function like datashape has for i, tp in enumerate(in_types): if tp.ndim == result_ndim: in_types[i] = ndt.make_strided_dim(tp.element_type) out_type = ndt.make_strided_dim(out_type.element_type) op.args[0] = _lowlevel.lift_arrfunc(ck) elif tag == 'reduction': ck = ckernel['ckernel'] assoc = ckernel['assoc'] comm = ckernel['comm'] ident = ckernel['ident'] ident = None if ident is None else nd.asarray(ident) axis = ckernel['axis'] keepdims = ckernel['keepdims'] op.args[0] = _lowlevel.lift_reduction_arrfunc( ck, in_types[0], axis=axis, keepdims=keepdims, associative=assoc, commutative=comm, reduction_identity=ident) elif tag == 'rolling': ck = ckernel['ckernel'] window = ckernel['window'] minp = ckernel['minp'] if minp != 0: raise ValueError('rolling window with minp != 0 not supported yet') op.args[0] = _lowlevel.make_rolling_arrfunc(ck, window) elif tag == 'ckfactory': ckfactory = ckernel['ckernel_factory'] ck = ckfactory(out_type, *in_types) op.args[0] = ck else: raise RuntimeError('unnrecognized ckernel tag %s' % tag) else: op.args[0] = ckernel
def check_from_numpy_int32_add(self, requiregil): # Get int32 add as an arrfunc af = _lowlevel.arrfunc_from_ufunc(np.add, (np.int32, np.int32, np.int32), requiregil) self.assertEqual(nd.as_py(af.proto), ndt.type("(int32, int32) -> int32")) a = nd.array(10, ndt.int32) b = nd.array(21, ndt.int32) c = af(a, b) self.assertEqual(nd.type_of(c), ndt.int32) self.assertEqual(nd.as_py(c), 31) af_lift = _lowlevel.lift_arrfunc(af) a = af_lift([[1], [2, 3], [4, 5, 6]], [[5, 10], [2], [1, 5, 1]]) self.assertEqual(nd.type_of(a), ndt.type('3 * var * int')) self.assertEqual(nd.as_py(a), [[6, 11], [4, 5], [5, 10, 7]])
def test_arrfunc_from_pyfunc(self): # Create an arrfunc out of a python function def myweightedsum(wt, a): wt = nd.as_py(wt) a = nd.as_py(a) return sum(x * y for x, y in zip(wt, a)) / sum(wt) af = _lowlevel.arrfunc_from_pyfunc(myweightedsum, "(var * real, var * real) -> real") in0 = nd.array([0.5, 1.0, 0.5], type="var * real") in1 = nd.array([1, 3, 5], type="var * real") out = af(in0, in1) self.assertEqual(nd.as_py(out), (0.5 + 3.0 + 2.5) / 2.0) # Also test it as a lifted kernel af_lifted = _lowlevel.lift_arrfunc(af) in0 = nd.array([[0.25, 0.75], [0.5, 1.0, 0.5], [1.0]], type="fixed * var * real") in1 = nd.array([[1, 3], [1, 3, 5], [5]], type="fixed * var * real") out = af_lifted(in0, in1) self.assertEqual(nd.as_py(out), [(0.25 + 0.75 * 3), (0.5 + 3.0 + 2.5) / 2.0, 5.0])
def test_ctypes_callback_deferred(self): # Create a deferred ckernel via a closure def instantiate_ckernel(out_ckb, ckb_offset, dst_tp, dst_arrmeta, src_tp, src_arrmeta, kernreq, ectx): out_ckb = _lowlevel.CKernelBuilder(out_ckb) def my_kernel_func_single(dst_ptr, src_ptr, kdp): dst = ctypes.c_int32.from_address(dst_ptr) src = ctypes.c_double.from_address(src_ptr[0]) dst.value = int(src.value * 3.5) def my_kernel_func_strided(dst_ptr, dst_stride, src_ptr, src_stride, count, kdp): src_ptr0 = src_ptr[0] src_stride0 = src_stride[0] for i in range(count): my_kernel_func_single(dst_ptr, [src_ptr0], kdp) dst_ptr += dst_stride src_ptr0 += src_stride0 if kernreq == 'single': kfunc = _lowlevel.ExprSingleOperation(my_kernel_func_single) else: kfunc = _lowlevel.ExprStridedOperation(my_kernel_func_strided) return ckernel.wrap_ckernel_func(out_ckb, ckb_offset, kfunc, kfunc) ckd = _lowlevel.arrfunc_from_instantiate_pyfunc(instantiate_ckernel, "(float64) -> int32") # Test calling the ckd out = nd.empty(ndt.int32) in0 = nd.array(4.0, type=ndt.float64) ckd.execute(out, in0) self.assertEqual(nd.as_py(out), 14) # Also call it lifted ckd_lifted = _lowlevel.lift_arrfunc(ckd) out = nd.empty('2 * var * int32') in0 = nd.array([[1.0, 3.0, 2.5], [1.25, -1.5]], type='2 * var * float64') ckd_lifted.execute(out, in0) self.assertEqual(nd.as_py(out), [[3, 10, 8], [4, -5]])