#ifndef HALIDE_MODULUS_REMAINDER_H #define HALIDE_MODULUS_REMAINDER_H /** \file * Routines for statically determining what expressions are divisible by. */ #include "Scope.h" namespace Halide { namespace Internal { /** The result of modulus_remainder analysis */ struct ModulusRemainder { ModulusRemainder() : modulus(0), remainder(0) {} ModulusRemainder(int m, int r) : modulus(m), remainder(r) {} int modulus, remainder; }; /** For things like alignment analysis, often it's helpful to know * if an integer expression is some multiple of a constant plus * some other constant. For example, it is straight-forward to * deduce that ((10*x + 2)*(6*y - 3) - 1) is congruent to five * modulo six. * * We get the most information when the modulus is large. E.g. if * something is congruent to 208 modulo 384, then we also know it's * congruent to 0 mod 8, and we can possibly use it as an index for an * aligned load. If all else fails, we can just say that an integer is * congruent to zero modulo one. */ ModulusRemainder modulus_remainder(Expr e); /** If we have alignment information about external variables, we can * let the analysis know about that using this version of * modulus_remainder: */ ModulusRemainder modulus_remainder(Expr e, const Scope &scope); /** Reduce an expression modulo some integer. Returns true and assigns * to remainder if an answer could be found. */ ///@{ bool reduce_expr_modulo(Expr e, int modulus, int *remainder); bool reduce_expr_modulo(Expr e, int modulus, int *remainder, const Scope &scope); ///@} void modulus_remainder_test(); /** The greatest common divisor of two integers */ int64_t gcd(int64_t, int64_t); /** The least common multiple of two integers */ int64_t lcm(int64_t, int64_t); } // namespace Internal } // namespace Halide #endif