#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.
*/
EXPORT 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: */
EXPORT ModulusRemainder modulus_remainder(Expr e, const Scope<ModulusRemainder> &scope);
/** Reduce an expression modulo some integer. Returns true and assigns
* to remainder if an answer could be found. */
///@{
EXPORT bool reduce_expr_modulo(Expr e, int modulus, int *remainder);
EXPORT bool reduce_expr_modulo(Expr e, int modulus, int *remainder, const Scope<ModulusRemainder> &scope);
///@}
EXPORT void modulus_remainder_test();
/** The greatest common divisor of two integers */
EXPORT int gcd(int, int);
/** The least common multiple of two integers */
EXPORT int lcm(int, int);
}
}
#endif