Rings for MAT 685
Mathematical ring implementation to demonstrate templates and inheritance
modp.hpp
1 #ifndef __MODP_HPP_
2 #define __MODP_HPP_
3 
4 #include <stdexcept>
5 using std::domain_error;
6 
7 #include <vector>
8 using std::vector;
9 
10 #include "mod.hpp"
11 
12 namespace Rings {
13 
23 template<typename T, T p>
24 class Modp : virtual public Field_Element, virtual public Mod<T, p> {
25 
26 protected:
27 
28  using Mod<T,p>::value;
30 
32  static vector<T> inverses;
33 
35  virtual void check_inverse() noexcept override { }
37  void check_inverses();
38 
39 public:
40 
42 
44  Modp<T,p>();
46  Modp<T,p>(T);
50  Modp<T,p>(const Mod<T,p> & other);
52  Modp<T,p>(const Modp<T,p> & other);
53 
54  virtual Modp<T,p> & operator * (const T & other) const override;
55  virtual Modp<T,p> & operator / (const Field_Element & other) const override;
56  virtual Modp<T,p> & inverse() const override;
57 
58  virtual bool has_inverse() const override;
59 
60 };
61 
62 template <typename T, T p>
64  if (inverses.size() == 0) {
65  inverses.resize(p);
66  inverses[1] = 1;
67  inverses[p - 1] = p - 1;
68  for (T i = 2; i < p - 1; ++i) {
69  T a, b;
70  T d = gcd<T>(i, p, a, b);
71  if (d != 1)
72  throw domain_error("Attempted a non-prime modulus for Modp");
73  if (a < 0) a += p;
74  inverses[i] = a;
75  }
76  }
77 }
78 
79 template <typename T, T p>
80 Modp<T,p>::Modp() : Mod<T,p>() { invertible = true; check_inverses(); }
81 
82 template <typename T, T p>
83 Modp<T,p>::Modp(T v) : Mod<T,p>(v) {
84  invertible = true;
86 }
87 
88 template <typename T, T p>
89 Modp<T,p>::Modp(const Modp<T,p> & other) : Mod<T,p>(other) {
90  invertible = true;
92 }
93 
94 template <typename T, T p>
95 Modp<T,p>::Modp(const Mod<T,p> & other) : Mod<T,p>(other) {
96  invertible = true;
98 }
99 
100 template <typename T, T p>
101 Modp<T,p> & Modp<T,p>::operator * (const T & other) const {
102  static Modp<T,p> result(value * other);
103  return result;
104 }
105 
106 template <typename T, T p>
108  const
109 {
110  static Modp<T,p> result;
111  result.value
112  = value * inverses[dynamic_cast<const Modp<T,p> &>(other).value];
113  result.adjust_value();
114  return result;
115 }
116 
117 template <typename T, T p>
119  static Modp<T,p> result;
120  result.value = inverses[value];
121  return result;
122 }
123 
124 template <typename T, T p>
125 bool Modp<T,p>::has_inverse() const { return not is_zero(); }
126 
127 template<typename T, T p> vector<T> Modp<T,p>::inverses;
128 
133 template<typename T, T p>
135 
136 }
137 
138 #endif
virtual Modp< T, p > & operator*(const T &other) const override
multiplication of value with element of base type
Definition: modp.hpp:101
a field is an integral domain whose nonzero elements have inverses
Definition: rings.hpp:63
virtual bool is_zero() const override
True iff assigned value is congruent to 0
Definition: mod.hpp:104
Definition: integer.hpp:6
virtual Modp< T, p > & inverse() const override
multiplicative inverse
Definition: modp.hpp:118
Modp()
initializes to zero
Definition: modp.hpp:80
bool invertible
whether the element is invertible
Definition: mod.hpp:31
virtual void check_inverse() noexcept override
redefines Mod’s check_inverse() to do nothing
Definition: modp.hpp:35
constexpr Modp< T, p > initialize_inverses
used to force an initialization of inverses at compilation
Definition: modp.hpp:134
virtual bool has_inverse() const override
fields are integral domains where nonzero elements have inverses
Definition: rings.hpp:68
virtual bool has_inverse() const override
fields are integral domains where nonzero elements have inverses
Definition: modp.hpp:125
templated modular arithmetic, modulo a prime
Definition: modp.hpp:24
virtual Modp< T, p > & operator/(const Field_Element &other) const override
division: other element should be of same type, use a cast
Definition: modp.hpp:107
static vector< T > inverses
lists inverses for all nonzero elements
Definition: modp.hpp:32
templated modular arithmetic, making no assumption about the modulus
Definition: mod.hpp:25
void adjust_value()
ensures value is at least 0 but less than modulus
Definition: mod.hpp:34
void check_inverses()
checks whether inverse are set up, and if not sets them up
Definition: modp.hpp:63
T value
value of the element
Definition: mod.hpp:29