2016-10-27 21:16:58 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
namespace nall {
|
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
template<uint Bits> struct BarrettReduction {
|
|
|
|
using type = typename ArithmeticNatural<1 * Bits>::type;
|
|
|
|
using pair = typename ArithmeticNatural<2 * Bits>::type;
|
2016-10-27 21:16:58 +00:00
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
explicit BarrettReduction(type modulo) : modulo(modulo), factor(pair(1) + -pair(modulo) / modulo) {}
|
|
|
|
|
|
|
|
//return => value % modulo
|
|
|
|
inline auto operator()(pair value) const -> type {
|
|
|
|
pair hi, lo;
|
|
|
|
mul(value, factor, hi, lo);
|
|
|
|
pair remainder = value - hi * modulo;
|
2016-10-27 21:16:58 +00:00
|
|
|
return remainder < modulo ? remainder : remainder - modulo;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-10-04 10:11:23 +00:00
|
|
|
const pair modulo;
|
|
|
|
const pair factor;
|
2016-10-27 21:16:58 +00:00
|
|
|
};
|
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
template<typename T, uint Bits> auto operator%(T value, const BarrettReduction<Bits>& modulo) {
|
|
|
|
return modulo(value);
|
|
|
|
}
|
|
|
|
|
2016-10-27 21:16:58 +00:00
|
|
|
}
|