Rings for MAT 685
Mathematical ring implementation to demonstrate templates and inheritance
mod.hpp
1 #ifndef __MOD_
2 #define __MOD_
3 
4 #include <stdexcept>
5 using std::domain_error;
6 
7 #include <iostream>
8 using std::ostream;
9 
10 #include "../gcd/gcd_template.hpp"
11 
12 #include "rings.hpp"
13 
14 namespace Rings {
15 
24 template<typename T, T m>
25 class Mod : virtual public Commutative_Ring_Element {
26 protected:
27 
29  T value;
31  bool invertible;
32 
34  void adjust_value() {
35  value %= m;
36  if (value < 0)
37  value += m;
38  }
43  virtual void check_inverse() { invertible = 1 == gcd<T>(value, m); }
49  void check_modulus() {
50  if (m == 0) throw domain_error("Attempted to create a modulus of 0");
51  }
52 
53 public:
54 
56  Mod<T,m>();
58  Mod<T, m>(T v);
60  Mod<T, m>(const Mod<T, m> & other);
61 
63  virtual bool is_one() const override;
65  virtual bool is_zero() const override;
67  virtual bool has_inverse() const override;
68 
70  virtual Mod<T, m> & operator + (const Ring_Element & other) const override;
72  virtual Mod<T, m> & operator - (const Ring_Element & other) const override;
74  virtual Mod<T, m> & operator * (const Ring_Element & other) const override;
76  virtual Mod<T, m> & operator * (const T & other) const;
77 
79  const Mod<T,m> & operator = (const Ring_Element &);
80 
81  virtual bool operator == (const Ring_Element &) const override;
82  virtual bool operator != (const Ring_Element &) const override;
83 
85  T get_value() const;
86 
87 };
88 
89 template<typename T, T m>
90 Mod<T,m>::Mod() : value(0) { check_modulus(); check_inverse(); }
91 
92 template<typename T, T m>
93 Mod<T,m>::Mod(T v) : value(v) { adjust_value(); check_inverse(); }
94 
95 template<typename T, T m>
96 Mod<T,m>::Mod(const Mod<T, m> & other)
97  : value(other.value), invertible(other.invertible)
98 { }
99 
100 template<typename T, T m>
101 bool Mod<T,m>::is_one() const { return value == 1; }
102 
103 template<typename T, T m>
104 bool Mod<T,m>::is_zero() const { return value == 0; }
105 
106 template<typename T, T m>
107 bool Mod<T,m>::has_inverse() const { return invertible; }
108 
109 template<typename T, T m>
111 {
112  static Mod<T, m> result;
113  auto o = dynamic_cast<const Mod<T, m> &>(other);
114  result.value = value + o.value;
115  result.adjust_value();
116  return result;
117 }
118 
119 template<typename T, T m>
121 {
122  static Mod<T, m> result;
123  auto o = dynamic_cast<const Mod<T, m> &>(other);
124  result.value = value - o.value;
125  result.adjust_value();
126  return result;
127 }
128 
129 template<typename T, T m>
131 {
132  static Mod<T, m> result;
133  auto o = dynamic_cast<const Mod<T, m> &>(other);
134  result.value = value * o.value;
135  result.adjust_value();
136  return result;
137 }
138 
139 template<typename T, T m>
140 Mod<T, m> & Mod<T,m>::operator * (const T & other) const {
141  static Mod<T, m> result;
142  result.value = value * other;
143  result.adjust_value();
144  return result;
145 }
146 
147 template<typename T, T m>
149  if (*this != other) {
150  const Mod<T,m> & o = dynamic_cast<const Mod<T,m> & >(other);
151  value = o.value;
152  invertible = o.invertible;
153  }
154  return *this;
155 }
156 
157 template<typename T, T m>
158 bool Mod<T,m>::operator == (const Ring_Element & other) const {
159  const Mod<T,m> & o = dynamic_cast<const Mod<T,m> & >(other);
160  return value == o.value;
161 }
162 
163 template<typename T, T m>
164 bool Mod<T,m>::operator != (const Ring_Element & other) const {
165  const Mod<T,m> & o = dynamic_cast<const Mod<T,m> & >(other);
166  return value != o.value;
167 }
168 
169 template<typename T, T m>
170 T Mod<T,m>::get_value() const { return value; }
171 
176 template <typename T, T m>
177 ostream & operator << (ostream & os, const Mod<T, m> & x) {
178  os << x.get_value();
179  return os;
180 }
181 
186 template<typename T, T m>
188 
189 }
190 
191 #endif
virtual Mod< T, m > & operator-(const Ring_Element &other) const override
implements modular subtraction
Definition: mod.hpp:120
elements of this type should have commutative multiplication
Definition: rings.hpp:39
virtual bool is_zero() const override
True iff assigned value is congruent to 0
Definition: mod.hpp:104
virtual Mod< T, m > & operator+(const Ring_Element &other) const override
implements modular addition
Definition: mod.hpp:110
virtual bool is_one() const override
True iff assigned value is congruent to 1
Definition: mod.hpp:101
Definition: integer.hpp:6
T get_value() const
returns value of this modulus
Definition: mod.hpp:170
virtual bool has_inverse() const override
True iff assigned value is relatively prime to modulus
Definition: mod.hpp:107
virtual void check_inverse()
decides whether this is invertible and sets flag accordingly; True iff (where is value) ...
Definition: mod.hpp:43
bool invertible
whether the element is invertible
Definition: mod.hpp:31
const Mod< T, m > & operator=(const Ring_Element &)
assignment operator may be needed
Definition: mod.hpp:148
a class for elements with the capabilities of ring arithmetic
Definition: rings.hpp:9
virtual bool operator!=(const Ring_Element &) const override
comparison: other element has different value
Definition: mod.hpp:164
constexpr Mod< T, m > prevent_zero_modulus
used to prevent the use of a zero modulus
Definition: mod.hpp:187
virtual Mod< T, m > & operator*(const Ring_Element &other) const override
implements modular multiplication
Definition: mod.hpp:130
templated modular arithmetic, making no assumption about the modulus
Definition: mod.hpp:25
virtual bool operator==(const Ring_Element &) const override
comparison: other element has same value
Definition: mod.hpp:158
void adjust_value()
ensures value is at least 0 but less than modulus
Definition: mod.hpp:34
Mod()
initializes to 0
Definition: mod.hpp:90
void check_modulus()
checks modulus to ensure we aren&#39;t trying to do the impossible
Definition: mod.hpp:49
T value
value of the element
Definition: mod.hpp:29