Zp_field_shared.h
Go to the documentation of this file.
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author(s): Hannah Schreiber
4  *
5  * Copyright (C) 2022 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
17 #ifndef MATRIX_FIELD_ZP_VAR_H_
18 #define MATRIX_FIELD_ZP_VAR_H_
19 
20 #include <utility>
21 #include <vector>
22 #include <limits.h>
23 #include <stdexcept>
24 
25 namespace Gudhi {
26 namespace persistence_fields {
27 
40 template <typename Unsigned_integer_type = unsigned int,
41  class = std::enable_if_t<std::is_unsigned_v<Unsigned_integer_type> > >
43  public:
44  using element_type = Unsigned_integer_type;
46  template <class T>
47  using isInteger = std::enable_if_t<std::is_integral_v<T> >;
48 
52  Shared_Zp_field_element() : element_(0) {}
59  template <typename Integer_type, class = isInteger<Integer_type> >
60  Shared_Zp_field_element(Integer_type element) : element_(_get_value(element)) {}
66  Shared_Zp_field_element(const Shared_Zp_field_element& toCopy) : element_(toCopy.element_) {}
72  Shared_Zp_field_element(Shared_Zp_field_element&& toMove) noexcept : element_(std::exchange(toMove.element_, 0)) {}
73 
80  static void initialize(characteristic_type characteristic) {
81  if (characteristic <= 1)
82  throw std::invalid_argument("Characteristic must be strictly positive and a prime number.");
83 
84  inverse_.resize(characteristic);
85  inverse_[0] = 0;
86  for (element_type i = 1; i < characteristic; ++i) {
87  element_type inv = 1;
88  element_type mult = inv * i;
89  while ((mult % characteristic) != 1) {
90  ++inv;
91  if (mult == characteristic) throw std::invalid_argument("Characteristic must be a prime number.");
92  mult = inv * i;
93  }
94  inverse_[i] = inv;
95  }
96 
97  characteristic_ = characteristic;
98  }
99 
105  element_type get_value() const { return element_; }
106 
111  f1.element_ = Shared_Zp_field_element::_add(f1.element_, f2.element_);
112  }
117  f1 += f2;
118  return f1;
119  }
125  template <typename Integer_type, class = isInteger<Integer_type> >
126  friend void operator+=(Shared_Zp_field_element& f, const Integer_type& v) {
127  f.element_ = Shared_Zp_field_element::_add(f.element_, _get_value(v));
128  }
134  template <typename Integer_type, class = isInteger<Integer_type> >
135  friend Shared_Zp_field_element operator+(Shared_Zp_field_element f, const Integer_type& v) {
136  f += v;
137  return f;
138  }
144  template <typename Integer_type, class = isInteger<Integer_type> >
145  friend Integer_type operator+(const Integer_type& v, Shared_Zp_field_element f) {
146  f += v;
147  return f.element_;
148  }
149 
154  f1.element_ = Shared_Zp_field_element::_substract(f1.element_, f2.element_);
155  }
160  f1 -= f2;
161  return f1;
162  }
168  template <typename Integer_type, class = isInteger<Integer_type> >
169  friend void operator-=(Shared_Zp_field_element& f, const Integer_type& v) {
170  f.element_ = Shared_Zp_field_element::_substract(f.element_, _get_value(v));
171  }
177  template <typename Integer_type, class = isInteger<Integer_type> >
178  friend Shared_Zp_field_element operator-(Shared_Zp_field_element f, const Integer_type& v) {
179  f -= v;
180  return f;
181  }
187  template <typename Integer_type, class = isInteger<Integer_type> >
188  friend Integer_type operator-(const Integer_type& v, const Shared_Zp_field_element& f) {
189  return Shared_Zp_field_element::_substract(_get_value(v), f.element_);
190  }
191 
196  f1.element_ = Shared_Zp_field_element::_multiply(f1.element_, f2.element_);
197  }
202  f1 *= f2;
203  return f1;
204  }
210  template <typename Integer_type, class = isInteger<Integer_type> >
211  friend void operator*=(Shared_Zp_field_element& f, const Integer_type& v) {
212  f.element_ = Shared_Zp_field_element::_multiply(f.element_, _get_value(v));
213  }
219  template <typename Integer_type, class = isInteger<Integer_type> >
220  friend Shared_Zp_field_element operator*(Shared_Zp_field_element f, const Integer_type& v) {
221  f *= v;
222  return f;
223  }
229  template <typename Integer_type, class = isInteger<Integer_type> >
230  friend Integer_type operator*(const Integer_type& v, Shared_Zp_field_element f) {
231  f *= v;
232  return f.element_;
233  }
234 
238  friend bool operator==(const Shared_Zp_field_element& f1, const Shared_Zp_field_element& f2) {
239  return f1.element_ == f2.element_;
240  }
246  template <typename Integer_type, class = isInteger<Integer_type> >
247  friend bool operator==(const Integer_type& v, const Shared_Zp_field_element& f) {
248  return Shared_Zp_field_element::_get_value(v) == f.element_;
249  }
255  template <typename Integer_type, class = isInteger<Integer_type> >
256  friend bool operator==(const Shared_Zp_field_element& f, const Integer_type& v) {
257  return Shared_Zp_field_element::_get_value(v) == f.element_;
258  }
262  friend bool operator!=(const Shared_Zp_field_element& f1, const Shared_Zp_field_element& f2) { return !(f1 == f2); }
268  template <typename Integer_type, class = isInteger<Integer_type> >
269  friend bool operator!=(const Integer_type& v, const Shared_Zp_field_element& f) {
270  return !(v == f);
271  }
277  template <typename Integer_type, class = isInteger<Integer_type> >
278  friend bool operator!=(const Shared_Zp_field_element& f, const Integer_type& v) {
279  return !(v == f);
280  }
281 
286  std::swap(element_, other.element_);
287  return *this;
288  }
294  template <typename Integer_type, class = isInteger<Integer_type> >
295  Shared_Zp_field_element& operator=(const Integer_type& value) {
296  element_ = Shared_Zp_field_element::_get_value(value);
297  return *this;
298  }
302  friend void swap(Shared_Zp_field_element& f1, Shared_Zp_field_element& f2) { std::swap(f1.element_, f2.element_); }
303 
307  operator unsigned int() const { return element_; }
308 
314  Shared_Zp_field_element get_inverse() const { return Shared_Zp_field_element(inverse_[element_]); }
321  std::pair<Shared_Zp_field_element, characteristic_type> get_partial_inverse(
322  characteristic_type productOfCharacteristics) const {
323  return {get_inverse(), productOfCharacteristics};
324  }
325 
345  [[maybe_unused]] characteristic_type productOfCharacteristics) {
346  return Shared_Zp_field_element(1);
347  }
353  static characteristic_type get_characteristic() { return characteristic_; }
354 
355  // static constexpr bool handles_only_z2() { return false; }
356 
357  private:
358  element_type element_;
359  static inline characteristic_type characteristic_;
360  static inline std::vector<element_type> inverse_;
362  static element_type _add(element_type element, element_type v) {
363  if (UINT_MAX - element < v) {
364  // automatic unsigned integer overflow behaviour will make it work
365  element += v;
366  element -= characteristic_;
367  return element;
368  }
369 
370  element += v;
371  if (element >= characteristic_) element -= characteristic_;
372 
373  return element;
374  }
375  static element_type _substract(element_type element, element_type v) {
376  if (element < v) {
377  element += characteristic_;
378  }
379  element -= v;
380 
381  return element;
382  }
383  static element_type _multiply(element_type element, element_type v) {
384  element_type a = element;
385  element = 0;
386  element_type temp_b;
387 
388  while (a != 0) {
389  if (a & 1) {
390  if (v >= characteristic_ - element) element -= characteristic_;
391  element += v;
392  }
393  a >>= 1;
394 
395  temp_b = v;
396  if (v >= characteristic_ - v) temp_b -= characteristic_;
397  v += temp_b;
398  }
399 
400  return element;
401  }
402 
403  template <typename Integer_type, class = isInteger<Integer_type> >
404  static constexpr element_type _get_value(Integer_type e) {
405  if constexpr (std::is_signed_v<Integer_type>){
406  if (e < -static_cast<Integer_type>(characteristic_)) e = e % characteristic_;
407  if (e < 0) return e += characteristic_;
408  return e < static_cast<Integer_type>(characteristic_) ? e : e % characteristic_;
409  } else {
410  return e < characteristic_ ? e : e % characteristic_;
411  }
412  }
413 };
414 
415 } // namespace persistence_fields
416 } // namespace Gudhi
417 
418 #endif // MATRIX_FIELD_ZP_VAR_H_
Class representing an element of the field for any prime number . If each instanciation of the class...
Definition: Zp_field_shared.h:42
static characteristic_type get_characteristic()
Returns the current characteristic.
Definition: Zp_field_shared.h:353
friend bool operator==(const Shared_Zp_field_element &f, const Integer_type &v)
operator==
Definition: Zp_field_shared.h:256
Shared_Zp_field_element get_inverse() const
Returns the inverse of the element in the field.
Definition: Zp_field_shared.h:314
friend bool operator==(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator==
Definition: Zp_field_shared.h:238
Shared_Zp_field_element()
Default constructor. Sets the element to 0.
Definition: Zp_field_shared.h:52
friend bool operator==(const Integer_type &v, const Shared_Zp_field_element &f)
operator==
Definition: Zp_field_shared.h:247
std::pair< Shared_Zp_field_element, characteristic_type > get_partial_inverse(characteristic_type productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the argument.
Definition: Zp_field_shared.h:321
friend Integer_type operator+(const Integer_type &v, Shared_Zp_field_element f)
operator+
Definition: Zp_field_shared.h:145
friend void operator-=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator-=
Definition: Zp_field_shared.h:153
friend Integer_type operator*(const Integer_type &v, Shared_Zp_field_element f)
operator*
Definition: Zp_field_shared.h:230
static void initialize(characteristic_type characteristic)
Initialize the field to the given characteristic. Should be called first before constructing the fiel...
Definition: Zp_field_shared.h:80
friend Shared_Zp_field_element operator+(Shared_Zp_field_element f, const Integer_type &v)
operator+
Definition: Zp_field_shared.h:135
friend bool operator!=(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator!=
Definition: Zp_field_shared.h:262
Shared_Zp_field_element & operator=(Shared_Zp_field_element other)
Assign operator.
Definition: Zp_field_shared.h:285
friend void operator*=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator*=
Definition: Zp_field_shared.h:195
Shared_Zp_field_element(const Shared_Zp_field_element &toCopy)
Copy constructor.
Definition: Zp_field_shared.h:66
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f, const Integer_type &v)
operator*
Definition: Zp_field_shared.h:220
static Shared_Zp_field_element get_additive_identity()
Returns the additive identity of the field.
Definition: Zp_field_shared.h:331
friend void operator-=(Shared_Zp_field_element &f, const Integer_type &v)
operator-=
Definition: Zp_field_shared.h:169
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator-
Definition: Zp_field_shared.h:159
friend Shared_Zp_field_element operator+(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator+
Definition: Zp_field_shared.h:116
static Shared_Zp_field_element get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition: Zp_field_shared.h:337
Unsigned_integer_type element_type
Definition: Zp_field_shared.h:44
friend void operator*=(Shared_Zp_field_element &f, const Integer_type &v)
operator*=
Definition: Zp_field_shared.h:211
element_type characteristic_type
Definition: Zp_field_shared.h:45
friend void swap(Shared_Zp_field_element &f1, Shared_Zp_field_element &f2)
Swap operator.
Definition: Zp_field_shared.h:302
static Shared_Zp_field_element get_partial_multiplicative_identity([[maybe_unused]] characteristic_type productOfCharacteristics)
For interface purposes with multi-fields. Returns the multiplicative identity of the field.
Definition: Zp_field_shared.h:344
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f, const Integer_type &v)
operator-
Definition: Zp_field_shared.h:178
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator*
Definition: Zp_field_shared.h:201
element_type get_value() const
Returns the value of the element.
Definition: Zp_field_shared.h:105
Shared_Zp_field_element(Integer_type element)
Constructor setting the element to the given value.
Definition: Zp_field_shared.h:60
friend bool operator!=(const Integer_type &v, const Shared_Zp_field_element &f)
operator!=
Definition: Zp_field_shared.h:269
friend Integer_type operator-(const Integer_type &v, const Shared_Zp_field_element &f)
operator-
Definition: Zp_field_shared.h:188
Shared_Zp_field_element & operator=(const Integer_type &value)
Assign operator.
Definition: Zp_field_shared.h:295
Shared_Zp_field_element(Shared_Zp_field_element &&toMove) noexcept
Move constructor.
Definition: Zp_field_shared.h:72
friend void operator+=(Shared_Zp_field_element &f, const Integer_type &v)
operator+=
Definition: Zp_field_shared.h:126
friend bool operator!=(const Shared_Zp_field_element &f, const Integer_type &v)
operator!=
Definition: Zp_field_shared.h:278
friend void operator+=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator+=
Definition: Zp_field_shared.h:110
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14