diff --git a/kerncraft/kernel.py b/kerncraft/kernel.py index d3f0c44..c48fc49 100755 --- a/kerncraft/kernel.py +++ b/kerncraft/kernel.py @@ -37,6 +37,7 @@ from . import incore_model from .pycparser_utils import clean_code, replace_id +from kerncraft.symbolic.utils import int_ceil @contextmanager def set_recursionlimit(new_limit): @@ -389,7 +390,7 @@ def iteration_length(self, dimension=None): for var_name, start, end, incr in loops: # This unspools the iterations: - length = end-start + length = int_ceil((end-start), incr) total_length = total_length*length return self.subs_consts(total_length) @@ -483,7 +484,7 @@ def global_iterator_to_indices(self, git=None): loop_var = symbol_pos_int(var_name) # This unspools the iterations: - length = end-start # FIXME is incr handled correct here? + length = int_ceil((end-start), incr) counter = start+(((global_iterator*last_incr) // total_length)*incr) % length total_length = total_length*length last_incr = incr @@ -511,7 +512,7 @@ def global_iterator(self): total_length = sympy.Integer(1) for var_name, start, end, incr in reversed(self._loop_stack): loop_var = symbol_pos_int(var_name) - length = end - start # FIXME is incr handled correct here? + length = int_ceil((end-start), incr) global_iterator += (loop_var - start) * total_length total_length *= length return global_iterator diff --git a/kerncraft/symbolic/__init__.py b/kerncraft/symbolic/__init__.py new file mode 100644 index 0000000..b63a01f --- /dev/null +++ b/kerncraft/symbolic/__init__.py @@ -0,0 +1 @@ +from kerncraft.symbolic.utils import int_ceil, int_floor diff --git a/kerncraft/symbolic/utils.py b/kerncraft/symbolic/utils.py new file mode 100644 index 0000000..5099398 --- /dev/null +++ b/kerncraft/symbolic/utils.py @@ -0,0 +1,19 @@ +import sympy + +class int_floor(sympy.Function): + @classmethod + def eval(cls, x, y): + if x.is_Number and y.is_Number: + return x // y + + def _eval_is_integer(self): + return True + +class int_ceil(sympy.Function): + @classmethod + def eval(cls, x, y): + if x.is_Number and y.is_Number: + return sympy.ceiling(x / y) + + def _eval_is_integer(self): + return True