def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) data = arr.data ndim = arrty.ndim shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant(types.intp, arrty.ndim)) pointers = cgutils.alloca_once(builder, data.type, size=context.get_constant(types.intp, arrty.ndim)) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) exhausted = cgutils.alloca_once_value(builder, cgutils.false_byte) # Initialize indices and pointers with their start values. for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) ptrptr = cgutils.gep(builder, pointers, dim) builder.store(data, ptrptr) builder.store(zero, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic (see issue #846). dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, exhausted) self.indices = indices self.pointers = pointers self.exhausted = exhausted
def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) data = arr.data ndim = arrty.ndim shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant( types.intp, arrty.ndim)) pointers = cgutils.alloca_once(builder, data.type, size=context.get_constant( types.intp, arrty.ndim)) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) exhausted = cgutils.alloca_once_value(builder, cgutils.false_byte) # Initialize indices and pointers with their start values. for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) ptrptr = cgutils.gep(builder, pointers, dim) builder.store(data, ptrptr) builder.store(zero, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic (see issue #846). dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, exhausted) self.indices = indices self.pointers = pointers self.exhausted = exhausted
def iternext_specific(self, context, builder, arrty, arr, result): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) ndim = arrty.ndim nitems = arr.nitems index = builder.load(self.index) is_valid = builder.icmp(lc.ICMP_SLT, index, nitems) result.set_valid(is_valid) with cgutils.if_likely(builder, is_valid): ptr = builder.load(self.pointer) value = context.unpack_value(builder, arrty.dtype, ptr) if kind == 'flat': result.yield_(value) else: # ndenumerate(): fetch and increment indices indices = self.indices idxvals = [ builder.load(cgutils.gep(builder, indices, dim)) for dim in range(ndim) ] idxtuple = cgutils.pack_array(builder, idxvals) result.yield_( cgutils.make_anonymous_struct( builder, [idxtuple, value])) _increment_indices_array(context, builder, arrty, arr, indices) index = builder.add(index, one) builder.store(index, self.index) ptr = cgutils.pointer_add(builder, ptr, self.stride) builder.store(ptr, self.pointer)
def get_next_int32(context, builder, state_ptr): """ Get the next int32 generated by the PRNG at *state_ptr*. """ idxptr = get_index_ptr(builder, state_ptr) idx = builder.load(idxptr) need_reshuffle = builder.icmp_unsigned('>=', idx, N_const) with cgutils.if_unlikely(builder, need_reshuffle): fnty = ir.FunctionType(ir.VoidType(), (rnd_state_ptr_t,)) fn = builder.function.module.get_or_insert_function(fnty, "numba_rnd_shuffle") builder.call(fn, (state_ptr,)) builder.store(const_int(0), idxptr) idx = builder.load(idxptr) array_ptr = get_array_ptr(builder, state_ptr) y = builder.load(cgutils.gep(builder, array_ptr, 0, idx)) idx = builder.add(idx, const_int(1)) builder.store(idx, idxptr) # Tempering y = builder.xor(y, builder.lshr(y, const_int(11))) y = builder.xor(y, builder.and_(builder.shl(y, const_int(7)), const_int(0x9d2c5680))) y = builder.xor(y, builder.and_(builder.shl(y, const_int(15)), const_int(0xefc60000))) y = builder.xor(y, builder.lshr(y, const_int(18))) return y
def iternext_specific(self, context, builder, result): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) bbend = cgutils.append_basic_block(builder, 'end') exhausted = cgutils.as_bool_bit(builder, builder.load(self.exhausted)) with cgutils.if_unlikely(builder, exhausted): result.set_valid(False) builder.branch(bbend) indices = [ builder.load(cgutils.gep(builder, self.indices, dim)) for dim in range(ndim) ] result.yield_(cgutils.pack_array(builder, indices)) result.set_valid(True) shape = cgutils.unpack_tuple(builder, self.shape, ndim) _increment_indices(context, builder, ndim, shape, self.indices, self.exhausted) builder.branch(bbend) builder.position_at_end(bbend)
def _increment_indices(context, builder, ndim, shape, indices, end_flag=None): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) bbend = cgutils.append_basic_block(builder, 'end_increment') if end_flag is not None: builder.store(cgutils.false_byte, end_flag) for dim in reversed(range(ndim)): idxptr = cgutils.gep(builder, indices, dim) idx = builder.add(builder.load(idxptr), one) count = shape[dim] in_bounds = builder.icmp(lc.ICMP_SLT, idx, count) with cgutils.if_likely(builder, in_bounds): builder.store(idx, idxptr) builder.branch(bbend) builder.store(zero, idxptr) if end_flag is not None: builder.store(cgutils.true_byte, end_flag) builder.branch(bbend) builder.position_at_end(bbend)
def iternext_specific(self, context, builder, arrty, arr, result): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) ndim = arrty.ndim nitems = arr.nitems index = builder.load(self.index) is_valid = builder.icmp(lc.ICMP_SLT, index, nitems) result.set_valid(is_valid) with cgutils.if_likely(builder, is_valid): ptr = builder.load(self.pointer) value = context.unpack_value(builder, arrty.dtype, ptr) if kind == 'flat': result.yield_(value) else: # ndenumerate(): fetch and increment indices indices = self.indices idxvals = [builder.load(cgutils.gep(builder, indices, dim)) for dim in range(ndim)] idxtuple = cgutils.pack_array(builder, idxvals) result.yield_( cgutils.make_anonymous_struct(builder, [idxtuple, value])) _increment_indices_array(context, builder, arrty, arr, indices) index = builder.add(index, one) builder.store(index, self.index) ptr = cgutils.pointer_add(builder, ptr, self.stride) builder.store(ptr, self.pointer)
def reduce_datetime_for_unit(builder, dt_val, src_unit, dest_unit): dest_unit_code = npdatetime.DATETIME_UNITS[dest_unit] src_unit_code = npdatetime.DATETIME_UNITS[src_unit] if dest_unit_code < 2 or src_unit_code >= 2: return dt_val, src_unit # Need to compute the day ordinal for *dt_val* if src_unit_code == 0: # Years to days year_val = dt_val days_val = year_to_days(builder, year_val) else: # Months to days leap_array = cgutils.global_constant(builder, "leap_year_months_acc", leap_year_months_acc) normal_array = cgutils.global_constant(builder, "normal_year_months_acc", normal_year_months_acc) days = cgutils.alloca_once(builder, TIMEDELTA64) # First compute year number and month number year, month = cgutils.divmod_by_constant(builder, dt_val, 12) # Then deduce the number of days with builder.if_else(is_leap_year(builder, year)) as (then, otherwise): with then: addend = builder.load( cgutils.gep(builder, leap_array, 0, month, inbounds=True)) builder.store(addend, days) with otherwise: addend = builder.load( cgutils.gep(builder, normal_array, 0, month, inbounds=True)) builder.store(addend, days) days_val = year_to_days(builder, year) days_val = builder.add(days_val, builder.load(days)) if dest_unit_code == 2: # Need to scale back to weeks weeks, _ = cgutils.divmod_by_constant(builder, days_val, 7) return weeks, 'W' else: return days_val, 'D'
def get_entry(self, idx): """ Get entry number *idx*. """ entry_ptr = cgutils.gep(self._builder, self._entries, idx) entry = self._context.make_data_helper(self._builder, types.SetEntry(self._ty), ref=entry_ptr) return entry
def reduce_datetime_for_unit(builder, dt_val, src_unit, dest_unit): dest_unit_code = npdatetime.DATETIME_UNITS[dest_unit] src_unit_code = npdatetime.DATETIME_UNITS[src_unit] if dest_unit_code < 2 or src_unit_code >= 2: return dt_val, src_unit # Need to compute the day ordinal for *dt_val* if src_unit_code == 0: # Years to days year_val = dt_val days_val = year_to_days(builder, year_val) else: # Months to days leap_array = cgutils.global_constant(builder, "leap_year_months_acc", leap_year_months_acc) normal_array = cgutils.global_constant(builder, "normal_year_months_acc", normal_year_months_acc) days = cgutils.alloca_once(builder, TIMEDELTA64) # First compute year number and month number year, month = cgutils.divmod_by_constant(builder, dt_val, 12) # Then deduce the number of days with cgutils.ifelse(builder, is_leap_year(builder, year)) as (then, otherwise): with then: addend = builder.load(cgutils.gep(builder, leap_array, 0, month)) builder.store(addend, days) with otherwise: addend = builder.load(cgutils.gep(builder, normal_array, 0, month)) builder.store(addend, days) days_val = year_to_days(builder, year) days_val = builder.add(days_val, builder.load(days)) if dest_unit_code == 2: # Need to scale back to weeks weeks, _ = cgutils.divmod_by_constant(builder, days_val, 7) return weeks, 'W' else: return days_val, 'D'
def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) data = arr.data ndim = arrty.ndim shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant( types.intp, arrty.ndim)) pointers = cgutils.alloca_once(builder, data.type, size=context.get_constant( types.intp, arrty.ndim)) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) empty = cgutils.alloca_once_value(builder, cgutils.false_byte) # Initialize each dimension with the next index and pointer # values. For the last (inner) dimension, this is 0 and the # start pointer, for the other dimensions, this is 1 and the # pointer to the next subarray after start. for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) ptrptr = cgutils.gep(builder, pointers, dim) if dim == ndim - 1: builder.store(zero, idxptr) builder.store(data, ptrptr) else: p = cgutils.pointer_add(builder, data, strides[dim]) builder.store(p, ptrptr) builder.store(one, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic (see issue #846). dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, empty) self.indices = indices self.pointers = pointers self.empty = empty
def load_from_data_pointer(self, builder, ptr): values = [] for i, model in enumerate(self._models): elem_ptr = cgutils.gep(builder, ptr, 0, i) val = model.load_from_data_pointer(builder, elem_ptr) values.append(val) struct = ir.Constant(self.get_value_type(), ir.Undefined) for i, val in enumerate(values): struct = self.set(builder, struct, val, i) return struct
def _define_nrt_meminfo_data(module): """ Implement NRT_MemInfo_data_fast in the module. This allows LLVM to inline lookup of the data pointer. """ fn = module.get_or_insert_function(meminfo_data_ty, name="NRT_MemInfo_data_fast") builder = ir.IRBuilder(fn.append_basic_block()) [ptr] = fn.args struct_ptr = builder.bitcast(ptr, _meminfo_struct_type.as_pointer()) data_ptr = builder.load(cgutils.gep(builder, struct_ptr, 0, 3)) builder.ret(data_ptr)
def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) data = arr.data ndim = arrty.ndim shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant(types.intp, arrty.ndim)) pointers = cgutils.alloca_once(builder, data.type, size=context.get_constant(types.intp, arrty.ndim)) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) empty = cgutils.alloca_once_value(builder, cgutils.false_byte) # Initialize each dimension with the next index and pointer # values. For the last (inner) dimension, this is 0 and the # start pointer, for the other dimensions, this is 1 and the # pointer to the next subarray after start. for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) ptrptr = cgutils.gep(builder, pointers, dim) if dim == ndim - 1: builder.store(zero, idxptr) builder.store(data, ptrptr) else: p = cgutils.pointer_add(builder, data, strides[dim]) builder.store(p, ptrptr) builder.store(one, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic (see issue #846). dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, empty) self.indices = indices self.pointers = pointers self.empty = empty
def build_set(context, builder, set_type, items): """ Build a set of the given type, containing the given items. """ nitems = len(items) inst = SetInstance.allocate(context, builder, set_type, nitems) # Populate set. Inlining the insertion code for each item would be very # costly, instead we create a LLVM array and iterate over it. array = cgutils.pack_array(builder, items) array_ptr = cgutils.alloca_once_value(builder, array) count = context.get_constant(types.intp, nitems) with cgutils.for_range(builder, count) as loop: item = builder.load(cgutils.gep(builder, array_ptr, 0, loop.index)) inst.add(item) return impl_ret_new_ref(context, builder, set_type, inst.value)
def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) self.index = cgutils.alloca_once_value(builder, zero) self.pointer = cgutils.alloca_once_value(builder, arr.data) # We can't trust strides[-1] to always contain the right # step value, see # http://docs.scipy.org/doc/numpy-dev/release.html#npy-relaxed-strides-checking self.stride = arr.itemsize if kind == 'ndenumerate': # Zero-initialize the indices array. indices = cgutils.alloca_once( builder, zero.type, size=context.get_constant(types.intp, arrty.ndim)) for dim in range(arrty.ndim): idxptr = cgutils.gep(builder, indices, dim) builder.store(zero, idxptr) self.indices = indices
def random_arr(context, builder, sig, args, typing_key=typing_key): from . import arrayobj arrty = sig.return_type dtype = arrty.dtype scalar_sig = signature(dtype, *sig.args[:-1]) scalar_args = args[:-1] # Allocate array... shapes = arrayobj._parse_shape(context, builder, sig.args[-1], args[-1]) arr = arrayobj._empty_nd_impl(context, builder, arrty, shapes) # ... and populate it in natural order scalar_impl = context.get_function(typing_key, scalar_sig) with cgutils.for_range(builder, arr.nitems) as loop: val = scalar_impl(builder, scalar_args) ptr = cgutils.gep(builder, arr.data, loop.index) arrayobj.store_item(context, builder, arrty, val, ptr) return impl_ret_new_ref(context, builder, sig.return_type, arr._getvalue())
def init_specific(self, context, builder, shapes): zero = context.get_constant(types.intp, 0) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant(types.intp, ndim)) exhausted = cgutils.alloca_once_value(builder, cgutils.false_byte) for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) builder.store(zero, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic. dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, exhausted) self.indices = indices self.exhausted = exhausted self.shape = cgutils.pack_array(builder, shapes)
def init_specific(self, context, builder, arrty, arr): zero = context.get_constant(types.intp, 0) self.index = cgutils.alloca_once_value(builder, zero) self.pointer = cgutils.alloca_once_value(builder, arr.data) # We can't trust strides[-1] to always contain the right # step value, see # http://docs.scipy.org/doc/numpy-dev/release.html#npy-relaxed-strides-checking self.stride = arr.itemsize if kind == 'ndenumerate': # Zero-initialize the indices array. indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant( types.intp, arrty.ndim)) for dim in range(arrty.ndim): idxptr = cgutils.gep(builder, indices, dim) builder.store(zero, idxptr) self.indices = indices
def iternext_specific(self, context, builder, result): zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) bbend = cgutils.append_basic_block(builder, 'end') exhausted = cgutils.as_bool_bit(builder, builder.load(self.exhausted)) with cgutils.if_unlikely(builder, exhausted): result.set_valid(False) builder.branch(bbend) indices = [builder.load(cgutils.gep(builder, self.indices, dim)) for dim in range(ndim)] result.yield_(cgutils.pack_array(builder, indices)) result.set_valid(True) shape = cgutils.unpack_tuple(builder, self.shape, ndim) _increment_indices(context, builder, ndim, shape, self.indices, self.exhausted) builder.branch(bbend) builder.position_at_end(bbend)
def init_specific(self, context, builder, shapes): zero = context.get_constant(types.intp, 0) indices = cgutils.alloca_once(builder, zero.type, size=context.get_constant( types.intp, ndim)) exhausted = cgutils.alloca_once_value(builder, cgutils.false_byte) for dim in range(ndim): idxptr = cgutils.gep(builder, indices, dim) builder.store(zero, idxptr) # 0-sized dimensions really indicate an empty array, # but we have to catch that condition early to avoid # a bug inside the iteration logic. dim_size = shapes[dim] dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero) with cgutils.if_unlikely(builder, dim_is_empty): builder.store(cgutils.true_byte, exhausted) self.indices = indices self.exhausted = exhausted self.shape = cgutils.pack_array(builder, shapes)
def _gep(self, idx): return cgutils.gep(self._builder, self.data, idx)
def get_index_ptr(builder, state_ptr): return cgutils.gep(builder, state_ptr, 0, 0)
def get_array_ptr(builder, state_ptr): return cgutils.gep(builder, state_ptr, 0, 1)
def as_data(self, builder, value): values = [builder.load(cgutils.gep(builder, value, i)) for i in range(self._fe_type.count)] return cgutils.pack_array(builder, values)
def get_gauss_ptr(builder, state_ptr): return cgutils.gep(builder, state_ptr, 0, 3)
def iternext_specific(self, context, builder, arrty, arr, result): ndim = arrty.ndim data = arr.data shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) indices = self.indices pointers = self.pointers zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) minus_one = context.get_constant(types.intp, -1) result.set_valid(True) bbcont = cgutils.append_basic_block(builder, 'continued') bbend = cgutils.append_basic_block(builder, 'end') # Catch already computed iterator exhaustion is_empty = cgutils.as_bool_bit(builder, builder.load(self.empty)) with cgutils.if_unlikely(builder, is_empty): result.set_valid(False) builder.branch(bbend) # Current pointer inside last dimension last_ptr = cgutils.alloca_once(builder, data.type) # Walk from inner dimension to outer for dim in reversed(range(ndim)): idxptr = cgutils.gep(builder, indices, dim) idx = builder.load(idxptr) count = shapes[dim] stride = strides[dim] in_bounds = builder.icmp(lc.ICMP_SLT, idx, count) with cgutils.if_likely(builder, in_bounds): # Index is valid => we point to the right slot ptrptr = cgutils.gep(builder, pointers, dim) ptr = builder.load(ptrptr) builder.store(ptr, last_ptr) # Compute next index and pointer for this dimension next_ptr = cgutils.pointer_add(builder, ptr, stride) builder.store(next_ptr, ptrptr) next_idx = builder.add(idx, one) builder.store(next_idx, idxptr) # Reset inner dimensions for inner_dim in range(dim + 1, ndim): idxptr = cgutils.gep(builder, indices, inner_dim) ptrptr = cgutils.gep(builder, pointers, inner_dim) # Compute next index and pointer for this dimension inner_ptr = cgutils.pointer_add( builder, ptr, strides[inner_dim]) builder.store(inner_ptr, ptrptr) builder.store(one, idxptr) builder.branch(bbcont) # End of array => skip to end result.set_valid(False) builder.branch(bbend) builder.position_at_end(bbcont) # After processing of indices and pointers: fetch value. ptr = builder.load(last_ptr) value = context.unpack_value(builder, arrty.dtype, ptr) result.yield_(value) builder.branch(bbend) builder.position_at_end(bbend)
def iternext_specific(self, context, builder, arrty, arr, result): ndim = arrty.ndim data = arr.data shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) indices = self.indices pointers = self.pointers zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) minus_one = context.get_constant(types.intp, -1) result.set_valid(True) bbcont = cgutils.append_basic_block(builder, 'continued') bbend = cgutils.append_basic_block(builder, 'end') # Catch already computed iterator exhaustion is_empty = cgutils.as_bool_bit(builder, builder.load(self.empty)) with cgutils.if_unlikely(builder, is_empty): result.set_valid(False) builder.branch(bbend) # Current pointer inside last dimension last_ptr = cgutils.alloca_once(builder, data.type) # Walk from inner dimension to outer for dim in reversed(range(ndim)): idxptr = cgutils.gep(builder, indices, dim) idx = builder.load(idxptr) count = shapes[dim] stride = strides[dim] in_bounds = builder.icmp(lc.ICMP_SLT, idx, count) with cgutils.if_likely(builder, in_bounds): # Index is valid => we point to the right slot ptrptr = cgutils.gep(builder, pointers, dim) ptr = builder.load(ptrptr) builder.store(ptr, last_ptr) # Compute next index and pointer for this dimension next_ptr = cgutils.pointer_add(builder, ptr, stride) builder.store(next_ptr, ptrptr) next_idx = builder.add(idx, one) builder.store(next_idx, idxptr) # Reset inner dimensions for inner_dim in range(dim + 1, ndim): idxptr = cgutils.gep(builder, indices, inner_dim) ptrptr = cgutils.gep(builder, pointers, inner_dim) # Compute next index and pointer for this dimension inner_ptr = cgutils.pointer_add(builder, ptr, strides[inner_dim]) builder.store(inner_ptr, ptrptr) builder.store(one, idxptr) builder.branch(bbcont) # End of array => skip to end result.set_valid(False) builder.branch(bbend) builder.position_at_end(bbcont) # After processing of indices and pointers: fetch value. ptr = builder.load(last_ptr) value = context.unpack_value(builder, arrty.dtype, ptr) result.yield_(value) builder.branch(bbend) builder.position_at_end(bbend)
def iternext_specific(self, context, builder, arrty, arr, result): ndim = arrty.ndim data = arr.data shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) indices = self.indices pointers = self.pointers zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) bbend = cgutils.append_basic_block(builder, 'end') # Catch already computed iterator exhaustion is_exhausted = cgutils.as_bool_bit( builder, builder.load(self.exhausted)) with cgutils.if_unlikely(builder, is_exhausted): result.set_valid(False) builder.branch(bbend) result.set_valid(True) # Current pointer inside last dimension last_ptr = cgutils.gep(builder, pointers, ndim - 1) ptr = builder.load(last_ptr) value = context.unpack_value(builder, arrty.dtype, ptr) if kind == 'flat': result.yield_(value) else: # ndenumerate() => yield (indices, value) idxvals = [builder.load(cgutils.gep(builder, indices, dim)) for dim in range(ndim)] idxtuple = cgutils.pack_array(builder, idxvals) result.yield_( cgutils.make_anonymous_struct(builder, [idxtuple, value])) # Update indices and pointers by walking from inner # dimension to outer. for dim in reversed(range(ndim)): idxptr = cgutils.gep(builder, indices, dim) idx = builder.add(builder.load(idxptr), one) count = shapes[dim] stride = strides[dim] in_bounds = builder.icmp(lc.ICMP_SLT, idx, count) with cgutils.if_likely(builder, in_bounds): # Index is valid => pointer can simply be incremented. builder.store(idx, idxptr) ptrptr = cgutils.gep(builder, pointers, dim) ptr = builder.load(ptrptr) ptr = cgutils.pointer_add(builder, ptr, stride) builder.store(ptr, ptrptr) # Reset pointers in inner dimensions for inner_dim in range(dim + 1, ndim): ptrptr = cgutils.gep(builder, pointers, inner_dim) builder.store(ptr, ptrptr) builder.branch(bbend) # Reset index and continue with next dimension builder.store(zero, idxptr) # End of array builder.store(cgutils.true_byte, self.exhausted) builder.branch(bbend) builder.position_at_end(bbend)
def iternext_specific(self, context, builder, arrty, arr, result): ndim = arrty.ndim data = arr.data shapes = cgutils.unpack_tuple(builder, arr.shape, ndim) strides = cgutils.unpack_tuple(builder, arr.strides, ndim) indices = self.indices pointers = self.pointers zero = context.get_constant(types.intp, 0) one = context.get_constant(types.intp, 1) bbend = cgutils.append_basic_block(builder, 'end') # Catch already computed iterator exhaustion is_exhausted = cgutils.as_bool_bit( builder, builder.load(self.exhausted)) with cgutils.if_unlikely(builder, is_exhausted): result.set_valid(False) builder.branch(bbend) result.set_valid(True) # Current pointer inside last dimension last_ptr = cgutils.gep(builder, pointers, ndim - 1) ptr = builder.load(last_ptr) value = context.unpack_value(builder, arrty.dtype, ptr) if kind == 'flat': result.yield_(value) else: # ndenumerate() => yield (indices, value) idxvals = [ builder.load(cgutils.gep(builder, indices, dim)) for dim in range(ndim) ] idxtuple = cgutils.pack_array(builder, idxvals) result.yield_( cgutils.make_anonymous_struct(builder, [idxtuple, value])) # Update indices and pointers by walking from inner # dimension to outer. for dim in reversed(range(ndim)): idxptr = cgutils.gep(builder, indices, dim) idx = builder.add(builder.load(idxptr), one) count = shapes[dim] stride = strides[dim] in_bounds = builder.icmp(lc.ICMP_SLT, idx, count) with cgutils.if_likely(builder, in_bounds): # Index is valid => pointer can simply be incremented. builder.store(idx, idxptr) ptrptr = cgutils.gep(builder, pointers, dim) ptr = builder.load(ptrptr) ptr = cgutils.pointer_add(builder, ptr, stride) builder.store(ptr, ptrptr) # Reset pointers in inner dimensions for inner_dim in range(dim + 1, ndim): ptrptr = cgutils.gep(builder, pointers, inner_dim) builder.store(ptr, ptrptr) builder.branch(bbend) # Reset index and continue with next dimension builder.store(zero, idxptr) # End of array builder.store(cgutils.true_byte, self.exhausted) builder.branch(bbend) builder.position_at_end(bbend)