#ifndef modulus_h_
#define modulus_h_
#include <iostream>
/*
Represents a number (or similarly behaving class) within the range [0,max_value)
A member of the T type must be:
1. convertable from int,
2. comparable to ints (via '<')
3. comparable to itself (via '=='), and
4. addable/subtractable from ints (or Ts - as they can be converted via 1.)
Parameters that fit that description include
* int, unsigned, long, char
* double, float
* enum
* or, even a Modulus instance itself
*/
template<typename T, int _max_value>
class Modulus {
public:
/*
Typedefs/access to template parameters
*/
typedef T value_type;
static const int max_value = _max_value;
/*
Conversion operators
*/
Modulus(T val=0): val(val) {rectify();}
Modulus &operator =(T rhs) {val=rhs; rectify(); return *this;}
operator T () const {return val;}
T value() const {return (T)*this;}
virtual void rectify() {
while ( val < 0 ) val = val + max_value;
//val = val % max_value; doesn't work for float/double,
//so we do it the long way
while(max_value < val) val = val - max_value;
if(val == max_value ) val=0;
}
/*
Increment/Decrement
*/
Modulus& operator ++() { val = val+1; rectify(); return *this; }
Modulus operator ++(int) {T old=val; val = val+1; rectify(); return Modulus(old);}
Modulus& operator --() { val = val-1; rectify(); return *this; }
Modulus operator --(int) {T old=val; val = val-1; rectify(); return Modulus(old);}
/*
Input
(output is handled by automatic conversion to value_type)
*/
template <typename T_2, int max_2>
friend std::istream& operator >> (std::istream& in, Modulus<T,max_value> &j);
/*
OP= Operators
#define OPERATOR(OP) \
Modulus& operator OP(T x) { \
val OP x; \
rectify(); \
return *this; \
}
OPERATOR(+=)
OPERATOR(-=)
OPERATOR(*=)
OPERATOR(/=)
OPERATOR(%=)
OPERATOR(&=)
OPERATOR(|=)
OPERATOR(^=)
OPERATOR(<<=)
OPERATOR(>>=)
#undef OPERATOR
*/
private:
T val;
};
template <typename T, int max_value>
std::istream& operator >> (std::istream& in, Modulus<T,max_value> &j){
in >> j.val;
j.rectify();
return in;
}
template<typename T_from, typename T_to>
T_to convert(T_from from) {
typedef typename T_to::value_type T_to_type;
typename T_from::value_type max_from = T_from::max_value;
T_to_type max_to = T_to::max_value;
T_to out = T_to_type( (from * max_to) / max_from);
return out;
}
#endif