def _print_IndexedElement(self, expr): if isinstance(expr.base, IndexedVariable): base = expr.base.internal_variable else: base = expr.base inds = list(expr.indices) inds = inds[::-1] base_shape = base.shape allow_negative_indexes = (isinstance(expr.base, IndexedVariable) and \ base.allows_negative_indexes) for i, ind in enumerate(inds): if isinstance(ind, PyccelUnarySub) and isinstance( ind.args[0], LiteralInteger): inds[i] = PyccelMinus(base_shape[i], ind.args[0]) else: #indices of indexedElement of len==1 shouldn't be a Tuple if isinstance(ind, Tuple) and len(ind) == 1: inds[i].args = ind[0] if allow_negative_indexes and \ not isinstance(ind, LiteralInteger) and not isinstance(ind, Slice): inds[i] = PyccelMod(ind, base_shape[i]) #set dtype to the C struct types dtype = self._print(expr.dtype) dtype = self.find_in_ndarray_type_registry(dtype, expr.precision) base_name = self._print(base.name) if base.is_ndarray: if expr.rank > 0: #managing the Slice input for i, ind in enumerate(inds): if isinstance(ind, Slice): #setting the slice start and end to their correct value if none is provided start = ind.start #handling the negative indexes for a slice object if isinstance(start, PyccelUnarySub) and \ isinstance(start.args[0], LiteralInteger): start = PyccelMinus(base_shape[i], start.args[0]) end = ind.end if isinstance(end, PyccelUnarySub) and \ isinstance(end.args[0], LiteralInteger): end = PyccelMinus(base_shape[i], end.args[0]) if ind.start is None: start = 0 if ind.end is None: end = base.shape[i] inds[i] = Slice(start, end) else: #setting the Slice start and end to their correct value when try to get a view with scalar index inds[i] = Slice(ind, ind + 1) inds = [self._print(i) for i in inds] return "array_slicing(%s, %s)" % (base_name, ", ".join(inds)) inds = [self._print(i) for i in inds] else: raise NotImplementedError(expr) return "%s.%s[get_index(%s, %s)]" % (base_name, dtype, base_name, ", ".join(inds))
def _visit_Slice(self, stmt): upper = self._visit(stmt.upper) if stmt.upper is not None else None lower = self._visit(stmt.lower) if stmt.lower is not None else None step = self._visit(stmt.step) if stmt.step is not None else None return Slice(lower, upper, step)
def get_results_shape(func): """returns a dictionary that contains for each result, its shape. When using the decorator @shapes, the shape value may be computed""" # ... arguments = list(func.arguments) arguments_inout = list(func.arguments_inout) results = list(func.results) inouts = [x for x, flag in zip(arguments, arguments_inout) if flag] # ... # ... d_args = {} for a in arguments: d_args[a.name] = a # ... # print('results = ', results) # print('inouts = ', inouts) d_shapes = {} if 'shapes' in func.decorators.keys(): d = func.decorators['shapes'] for valued in d: # ... r = [r for r in results + inouts if r.name == valued.name] if not r: raise ValueError('Could not find {}'.format(r)) assert (len(r) == 1) r = r[0] # ... # ... rhs = valued.value if isinstance(rhs, String): rhs = rhs.arg.replace("'", '') else: raise NotImplementedError('') # ... # ... rhs = sympify(rhs, locals=d_args) # ... # TODO improve # this must always be a list of slices d_shapes[r.name] = [Slice(None, rhs)] # TODO treate the case when shapes is not given => add some checks # else: # raise NotImplementedError('') return d_shapes
def _visit_Slice(self, stmt): upper = self._visit(stmt.upper) lower = self._visit(stmt.lower) if stmt.step is not None: raise NotImplementedError("Steps in slices are not implemented") if not isinstance(upper, Nil) and not isinstance(lower, Nil): return Slice(lower, upper) elif not isinstance(lower, Nil): return Slice(lower, None) elif not isinstance(upper, Nil): return Slice(None, upper) else: return Slice(None, None)
def _visit_Map(self, stmt): func = stmt.func args = stmt.target # ... if isinstance(func, BasicMap): raise TypeError("'map' object is not callable") # ... # ... get the codomain type type_codomain = self.main_type type_domain = self.d_domain_types[type_codomain] # ... # ... construct the generator target = [self._visit(i) for i in args] if len(target) == 1: target = target[0] assert (isinstance(target, Variable)) generator = VariableGenerator(target) else: generator = ZipGenerator(*target) # ... # ... construct the results results = self._visit(type_codomain) # compute depth of the type list # TODO do we still need this? depth_out = len(list(type_codomain.atoms(TypeList))) # ... # ... index = generator.index iterator = generator.iterator # ... # ... list of all statements stmts = [] # ... # ... we set the generator after we treat map/tmap self.set_generator(results, generator) # ... # ... apply the function to arguments rhs = Call(func, iterator) # ... # print('PAR ICI') # print(func) # print(func.name) ## import sys; sys.exit(0) # ... create lhs lhs = generator.iterator # TODO check this if isinstance(lhs, Tuple) and len(lhs) == 1: lhs = lhs[0] # ... # ... create lhs for storing the result if isinstance(results, Variable): results = [results] else: msg = '{} not available'.format(type(results)) raise NotImplementedError(msg) if not isinstance(index, Tuple): index = [index] else: index = list([i for i in index]) lhs = [] for r in results: m = r.rank - depth_out ind = index + [Slice(None, None)] * m if len(ind) == 1: ind = ind[0] lhs.append(IndexedBase(r.name)[ind]) lhs = Tuple(*lhs) if len(lhs) == 1: lhs = lhs[0] # ... # ... create core statement stmts += [Assign(lhs, rhs)] # ... # TODO USE THIS # expr = self.get_expr_from_type() # return the associated for loops return GeneratorBlock(generator, stmts, accelerator=self.accelerator, nowait=self.nowait, schedule=self.schedule, chunk=self.chunk)
def _visit_Reduce(self, stmt, op=None): target = stmt.target # ... get the codomain type type_codomain = self.main_type type_domain = self.d_domain_types[type_codomain] # ... # ... construct the results results = self._visit(type_codomain) # compute depth of the type list # TODO do we still need this? depth_out = 0 # ... # ... construct the generator block = self._visit(target) assert (isinstance(block, GeneratorBlock)) generator = block.generator if isinstance(generator, Variable): generator = VariableGenerator(generator) assert (isinstance(generator, BasicGenerator)) # ... # ... index = generator.index iterator = generator.iterator # ... # ... list of all statements stmts = [] # ... # ... we set the generator after we treat map/tmap self.set_generator(results, generator) # ... # ... create lhs lhs = generator.iterator # TODO check this if isinstance(lhs, Tuple) and len(lhs) == 1: lhs = lhs[0] # ... # ... create lhs for storing the result if isinstance(results, Variable): results = [results] else: msg = '{} not available'.format(type(results)) raise NotImplementedError(msg) if not isinstance(index, Tuple): index = [index] else: index = list([i for i in index]) lhs = [] for r in results: m = r.rank - depth_out ind = [Slice(None, None)] * m if ind: if len(ind) == 1: ind = ind[0] lhs.append(IndexedBase(r.name)[ind]) else: lhs.append(Symbol(r.name)) lhs = Tuple(*lhs) if len(lhs) == 1: lhs = lhs[0] # ... # ... add reduction reduction = Reduction(op, results) # ... # TODO USE THIS # expr = self.get_expr_from_type() # return the associated for loops return ReductionGeneratorBlock(block, reduction, lhs, accelerator=self.accelerator)
def _visit_ProductMap(self, stmt): func = stmt.func args = stmt.target # ... if isinstance(func, BasicMap): raise TypeError("'map' object is not callable") # ... # ... get the codomain type type_codomain = self.main_type type_domain = self.d_domain_types[type_codomain] # ... # ... construct the generator target = [self._visit(i) for i in args] generator = ProductGenerator(*target) # ... # ... construct the results results = self._visit(type_codomain) # compute depth of the type list # TODO do we still need this? depth_out = len(list(type_codomain.atoms(TypeList))) # ... # ... index = generator.index iterator = generator.iterator # ... # ... list of all statements stmts = [] # ... # ... use a multi index in the case of zip length = generator.length multi_index = generator.multi_index generator.set_as_list() # TODO check formula value = index[0] for ix, nx in zip(index[1:], length[::-1][:-1]): value = nx * value + ix stmts += [Assign(multi_index, value)] # update index to use multi index index = multi_index # ... # ... we set the generator after we treat map/tmap self.set_generator(results, generator) # ... # ... apply the function to arguments rhs = Call(func, iterator) # ... # ... create lhs lhs = generator.iterator # TODO check this if isinstance(lhs, Tuple) and len(lhs) == 1: lhs = lhs[0] # ... # ... create lhs for storing the result if isinstance(results, Variable): results = [results] else: msg = '{} not available'.format(type(results)) raise NotImplementedError(msg) if not isinstance(index, Tuple): index = [index] else: index = list([i for i in index]) lhs = [] for r in results: m = r.rank - depth_out ind = index + [Slice(None, None)] * m if len(ind) == 1: ind = ind[0] lhs.append(IndexedBase(r.name)[ind]) lhs = Tuple(*lhs) if len(lhs) == 1: lhs = lhs[0] # ... # ... create core statement stmts += [Assign(lhs, rhs)] # ... # TODO USE THIS # expr = self.get_expr_from_type() # return the associated for loops return GeneratorBlock(generator, stmts, accelerator=self.accelerator, nowait=self.nowait, schedule=self.schedule, chunk=self.chunk)