def slice_indices(context, builder, sig, args): length = args[1] sli = context.make_helper(builder, sig.args[0], args[0]) with builder.if_then(cgutils.is_neg_int(builder, length), likely=False): context.call_conv.return_user_exc(builder, ValueError, ("length should not be negative", )) with builder.if_then(cgutils.is_scalar_zero(builder, sli.step), likely=False): context.call_conv.return_user_exc(builder, ValueError, ("slice step cannot be zero", )) fix_slice(builder, sli, length) return context.make_tuple(builder, sig.return_type, (sli.start, sli.stop, sli.step))
def impl(context, builder, sig, args): [tyinp1, tyinp2, tyout] = sig.args [inp1, inp2, out] = args if isinstance(tyinp1, types.Array): scalar_inp1 = False scalar_tyinp1 = tyinp1.dtype inp1_ndim = tyinp1.ndim elif tyinp1 in types.number_domain: scalar_inp1 = True scalar_tyinp1 = tyinp1 inp1_ndim = 1 else: raise TypeError('unknown type for first input operand') if isinstance(tyinp2, types.Array): scalar_inp2 = False scalar_tyinp2 = tyinp2.dtype inp2_ndim = tyinp2.ndim elif tyinp2 in types.number_domain: scalar_inp2 = True scalar_tyinp2 = tyinp2 inp2_ndim = 1 else: raise TypeError('unknown type for second input operand') out_ndim = tyout.ndim if asfloat: promote_type = types.float64 elif scalar_tyinp1 in types.real_domain or \ scalar_tyinp2 in types.real_domain: promote_type = types.float64 elif scalar_tyinp1 in types.signed_domain or \ scalar_tyinp2 in types.signed_domain: promote_type = types.int64 else: promote_type = types.uint64 result_type = promote_type # Temporary hack for __ftol2 llvm bug. Don't allow storing # float results in uint64 array on windows. if result_type in types.real_domain and \ tyout.dtype is types.uint64 and \ sys.platform.startswith('win32'): raise TypeError('Cannot store result in uint64 array') sig = typing.signature(result_type, promote_type, promote_type) if not scalar_inp1: i1ary = context.make_array(tyinp1)(context, builder, inp1) if not scalar_inp2: i2ary = context.make_array(tyinp2)(context, builder, inp2) oary = context.make_array(tyout)(context, builder, out) fnwork = context.get_function(funckey, sig) intpty = context.get_value_type(types.intp) if not scalar_inp1: inp1_shape = cgutils.unpack_tuple(builder, i1ary.shape, inp1_ndim) inp1_strides = cgutils.unpack_tuple(builder, i1ary.strides, inp1_ndim) inp1_data = i1ary.data inp1_layout = tyinp1.layout if not scalar_inp2: inp2_shape = cgutils.unpack_tuple(builder, i2ary.shape, inp2_ndim) inp2_strides = cgutils.unpack_tuple(builder, i2ary.strides, inp2_ndim) inp2_data = i2ary.data inp2_layout = tyinp2.layout out_shape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) out_strides = cgutils.unpack_tuple(builder, oary.strides, out_ndim) out_data = oary.data out_layout = tyout.layout ZERO = Constant.int(Type.int(intpty.width), 0) ONE = Constant.int(Type.int(intpty.width), 1) inp1_indices = None if not scalar_inp1: inp1_indices = [] for i in range(inp1_ndim): x = builder.alloca(Type.int(intpty.width)) builder.store(ZERO, x) inp1_indices.append(x) inp2_indices = None if not scalar_inp2: inp2_indices = [] for i in range(inp2_ndim): x = builder.alloca(Type.int(intpty.width)) builder.store(ZERO, x) inp2_indices.append(x) loopshape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: # Increment input indices. # Since the output dimensions are already being incremented, # we'll use that to set the input indices. In order to # handle broadcasting, any input dimension of size 1 won't be # incremented. def build_increment_blocks(inp_indices, inp_shape, inp_ndim, inp_num): bb_inc_inp_index = [cgutils.append_basic_block(builder, '.inc_inp{0}_index{1}'.format(inp_num, str(i))) for i in range(inp_ndim)] bb_end_inc_index = cgutils.append_basic_block(builder, '.end_inc{0}_index'.format(inp_num)) builder.branch(bb_inc_inp_index[0]) for i in range(inp_ndim): with cgutils.goto_block(builder, bb_inc_inp_index[i]): # If the shape of this dimension is 1, then leave the # index at 0 so that this dimension is broadcasted over # the corresponding input and output dimensions. cond = builder.icmp(ICMP_UGT, inp_shape[i], ONE) with cgutils.ifthen(builder, cond): builder.store(indices[out_ndim-inp_ndim+i], inp_indices[i]) if i + 1 == inp_ndim: builder.branch(bb_end_inc_index) else: builder.branch(bb_inc_inp_index[i+1]) builder.position_at_end(bb_end_inc_index) if not scalar_inp1: build_increment_blocks(inp1_indices, inp1_shape, inp1_ndim, '1') if not scalar_inp2: build_increment_blocks(inp2_indices, inp2_shape, inp2_ndim, '2') if scalar_inp1: x = inp1 else: inds = [builder.load(index) for index in inp1_indices] px = cgutils.get_item_pointer2(builder, data=inp1_data, shape=inp1_shape, strides=inp1_strides, layout=inp1_layout, inds=inds) x = builder.load(px) if scalar_inp2: y = inp2 else: inds = [builder.load(index) for index in inp2_indices] py = cgutils.get_item_pointer2(builder, data=inp2_data, shape=inp2_shape, strides=inp2_strides, layout=inp2_layout, inds=inds) y = builder.load(py) po = cgutils.get_item_pointer2(builder, data=out_data, shape=out_shape, strides=out_strides, layout=out_layout, inds=indices) if divbyzero: # Handle division iszero = cgutils.is_scalar_zero(builder, y) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if (scalar_tyinp1 in types.real_domain or scalar_tyinp2 in types.real_domain) or \ not numpy_support.int_divbyzero_returns_zero: # If y is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(result_type) shouldretnan = cgutils.is_scalar_zero(builder, x) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) tempres = builder.select(shouldretnan, nan, inf) res = context.cast(builder, tempres, result_type, tyout.dtype) elif tyout.dtype in types.signed_domain and \ not numpy_support.int_divbyzero_returns_zero: res = Constant.int(context.get_data_type(tyout.dtype), 0x1 << (y.type.width-1)) else: res = Constant.null(context.get_data_type(tyout.dtype)) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) with orelse: # Normal d_x = context.cast(builder, x, scalar_tyinp1, promote_type) d_y = context.cast(builder, y, scalar_tyinp2, promote_type) tempres = fnwork(builder, [d_x, d_y]) res = context.cast(builder, tempres, result_type, tyout.dtype) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) else: # Handle non-division operations d_x = context.cast(builder, x, scalar_tyinp1, promote_type) d_y = context.cast(builder, y, scalar_tyinp2, promote_type) tempres = fnwork(builder, [d_x, d_y]) res = context.cast(builder, tempres, result_type, tyout.dtype) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) return out
def impl(context, builder, sig, args): [tyinp1, tyinp2, tyout] = sig.args [inp1, inp2, out] = args if scalar_inputs: ndim = 1 else: ndim = tyinp1.ndim # Temporary hack for __ftol2 llvm bug. Don't allow storing # float results in uint64 array on windows. if scalar_inputs and tyinp1 in types.real_domain and \ tyout.dtype is types.uint64 and \ sys.platform.startswith('win32'): raise TypeError('Cannot store result in uint64 array') if not scalar_inputs and tyinp1.dtype in types.real_domain and \ tyout.dtype is types.uint64 and \ sys.platform.startswith('win32'): raise TypeError('Cannot store result in uint64 array') if not scalar_inputs: i1ary = context.make_array(tyinp1)(context, builder, inp1) i2ary = context.make_array(tyinp2)(context, builder, inp2) oary = context.make_array(tyout)(context, builder, out) if asfloat and not divbyzero: sig = typing.signature(types.float64, types.float64, types.float64) else: if scalar_inputs: sig = typing.signature(tyout.dtype, tyinp1, tyinp2) else: sig = typing.signature(tyout.dtype, tyinp1.dtype, tyinp2.dtype) fnwork = context.get_function(funckey, sig) intpty = context.get_value_type(types.intp) # TODO handle differing shape by mimicking broadcasting loopshape = cgutils.unpack_tuple(builder, oary.shape, ndim) if scalar_inputs: xyo_shape = [cgutils.unpack_tuple(builder, ary.shape, ndim) for ary in (oary,)] xyo_strides = [cgutils.unpack_tuple(builder, ary.strides, ndim) for ary in (oary,)] xyo_data = [ary.data for ary in (oary,)] xyo_layout = [ty.layout for ty in (tyout,)] else: xyo_shape = [cgutils.unpack_tuple(builder, ary.shape, ndim) for ary in (i1ary, i2ary, oary)] xyo_strides = [cgutils.unpack_tuple(builder, ary.strides, ndim) for ary in (i1ary, i2ary, oary)] xyo_data = [ary.data for ary in (i1ary, i2ary, oary)] xyo_layout = [ty.layout for ty in (tyinp1, tyinp2, tyout)] with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: if scalar_inputs: [po] = [cgutils.get_item_pointer2(builder, data=data, shape=shape, strides=strides, layout=layout, inds=indices) for data, shape, strides, layout in zip(xyo_data, xyo_shape, xyo_strides, xyo_layout)] else: [px, py, po] = [cgutils.get_item_pointer2(builder, data=data, shape=shape, strides=strides, layout=layout, inds=indices) for data, shape, strides, layout in zip(xyo_data, xyo_shape, xyo_strides, xyo_layout)] if scalar_inputs: x = inp1 y = inp2 else: x = builder.load(px) y = builder.load(py) if divbyzero: # Handle division iszero = cgutils.is_scalar_zero(builder, y) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if ((scalar_inputs and tyinp2 in types.real_domain) or (not scalar_inputs and tyinp2.dtype in types.real_domain) or not numpy_support.int_divbyzero_returns_zero): # If y is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(tyout.dtype) shouldretnan = cgutils.is_scalar_zero(builder, x) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) res = builder.select(shouldretnan, nan, inf) elif (scalar_inputs and tyout in types.signed_domain and not numpy_support.int_divbyzero_returns_zero): res = Constant.int(context.get_data_type(tyout), 0x1 << (y.type.width-1)) elif (not scalar_inputs and tyout.dtype in types.signed_domain and not numpy_support.int_divbyzero_returns_zero): res = Constant.int(context.get_data_type(tyout.dtype), 0x1 << (y.type.width-1)) else: res = Constant.null(context.get_data_type(tyout.dtype)) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) with orelse: # Normal tempres = fnwork(builder, (x, y)) if scalar_inputs and tyinp1 in types.real_domain: res = context.cast(builder, tempres, tyinp1, tyout.dtype) elif (not scalar_inputs and tyinp1.dtype in types.real_domain): res = context.cast(builder, tempres, tyinp1.dtype, tyout.dtype) else: res = context.cast(builder, tempres, types.float64, tyout.dtype) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) else: # Handle non-division operations if asfloat: if scalar_inputs: d_x = context.cast(builder, x, tyinp1, types.float64) d_y = context.cast(builder, y, tyinp2, types.float64) else: d_x = context.cast(builder, x, tyinp1.dtype, types.float64) d_y = context.cast(builder, y, tyinp2.dtype, types.float64) tempres = fnwork(builder, [d_x, d_y]) res = context.cast(builder, tempres, types.float64, tyout.dtype) elif scalar_inputs: if tyinp1 != tyout.dtype: tempres = fnwork(builder, [x, y]) res = context.cast(builder, tempres, tyinp1, tyout.dtype) else: res = fnwork(builder, (x, y)) elif tyinp1.dtype != tyout.dtype: tempres = fnwork(builder, [x, y]) res = context.cast(builder, tempres, tyinp1.dtype, tyout.dtype) else: res = fnwork(builder, (x, y)) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) return out
def impl(context, builder, sig, args): [tyvx, tywy, tyout] = sig.args [vx, wy, out] = args assert tyvx.dtype == tywy.dtype ndim = tyvx.ndim xary = context.make_array(tyvx)(context, builder, vx) yary = context.make_array(tywy)(context, builder, wy) oary = context.make_array(tyout)(context, builder, out) intpty = context.get_value_type(types.intp) # TODO handle differing shape by mimicking broadcasting loopshape = cgutils.unpack_tuple(builder, xary.shape, ndim) xyo_shape = [cgutils.unpack_tuple(builder, ary.shape, ndim) for ary in (xary, yary, oary)] xyo_strides = [cgutils.unpack_tuple(builder, ary.strides, ndim) for ary in (xary, yary, oary)] xyo_data = [ary.data for ary in (xary, yary, oary)] xyo_layout = [ty.layout for ty in (tyvx, tywy, tyout)] with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: [px, py, po] = [cgutils.get_item_pointer2(builder, data=data, shape=shape, strides=strides, layout=layout, inds=indices) for data, shape, strides, layout in zip(xyo_data, xyo_shape, xyo_strides, xyo_layout)] x = builder.load(px) y = builder.load(py) if divbyzero: # Handle division iszero = cgutils.is_scalar_zero(builder, y) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if tyout.dtype in types.real_domain: # If x is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(tyout.dtype) shouldretnan = cgutils.is_scalar_zero(builder, x) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) res = builder.select(shouldretnan, nan, inf) elif (tyout.dtype in types.signed_domain and not numpy_support.int_divbyzero_returns_zero): res = Constant.int(y.type, 0x1 << (y.type.width-1)) else: res = Constant.null(y.type) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) with orelse: # Normal res = core(builder, (x, y)) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) else: # Handle other operations res = core(builder, (x, y)) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) return out