Zp_field_operators.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) 2024 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
17 #ifndef MATRIX_FIELD_ZP_OPERATOR_H_
18 #define MATRIX_FIELD_ZP_OPERATOR_H_
19 
20 #include <stdexcept>
21 #include <utility>
22 #include <vector>
23 #include <limits.h>
24 
25 namespace Gudhi {
27 namespace persistence_fields {
28 
38 template <typename Unsigned_integer_type = unsigned int,
39  class = std::enable_if_t<std::is_unsigned_v<Unsigned_integer_type> > >
41 {
42  public:
43  using element_type = Unsigned_integer_type;
45  template <class T>
46  using isSignedInteger = std::enable_if_t<std::is_signed_v<T> >;
47 
54  Zp_field_operators(characteristic_type characteristic = 0) : characteristic_(0) {
55  if (characteristic != 0) set_characteristic(characteristic);
56  }
63  : characteristic_(toCopy.characteristic_), inverse_(toCopy.inverse_) {}
70  : characteristic_(std::exchange(toMove.characteristic_, 0)), inverse_(std::move(toMove.inverse_)) {}
71 
77  void set_characteristic(characteristic_type characteristic) {
78  if (characteristic <= 1)
79  throw std::invalid_argument("Characteristic must be strictly positive and a prime number.");
80 
81  inverse_.resize(characteristic);
82  inverse_[0] = 0;
83  for (unsigned int i = 1; i < characteristic; ++i) {
84  unsigned int inv = 1;
85  unsigned int mult = inv * i;
86  while ((mult % characteristic) != 1) {
87  ++inv;
88  if (mult == characteristic) throw std::invalid_argument("Characteristic must be a prime number.");
89  mult = inv * i;
90  }
91  inverse_[i] = inv;
92  }
93 
94  characteristic_ = characteristic;
95  }
101  const characteristic_type& get_characteristic() const { return characteristic_; }
102 
110  element_type get_value(element_type e) const { return e < characteristic_ ? e : e % characteristic_; }
119  template <typename Signed_integer_type, class = isSignedInteger<Signed_integer_type> >
120  element_type get_value(Signed_integer_type e) const {
121  if (e < -static_cast<Signed_integer_type>(characteristic_)) e = e % characteristic_;
122  if (e < 0) return e += characteristic_;
123  return e < static_cast<Signed_integer_type>(characteristic_) ? e : e % characteristic_;
124  }
125 
134  return _add(get_value(e1), get_value(e2), characteristic_);
135  }
136 
144  void add_inplace(element_type& e1, element_type e2) const {
145  e1 = _add(get_value(e1), get_value(e2), characteristic_);
146  }
147 
156  return _substract(get_value(e1), get_value(e2), characteristic_);
157  }
158 
167  e1 = _substract(get_value(e1), get_value(e2), characteristic_);
168  }
177  e2 = _substract(get_value(e1), get_value(e2), characteristic_);
178  }
179 
188  return _multiply(get_value(e1), get_value(e2), characteristic_);
189  }
190 
199  e1 = _multiply(get_value(e1), get_value(e2), characteristic_);
200  }
201 
213 
225  e = get_value(e * m + a);
226  }
238  a = get_value(e * m + a);
239  }
240 
253 
265  e = get_value((e + a) * m);
266  }
278  m = get_value((e + a) * m);
279  }
280 
289  bool are_equal(element_type e1, element_type e2) const { return get_value(e1) == get_value(e2); }
290 
297  element_type get_inverse(element_type e) const { return inverse_[get_value(e)]; }
305  std::pair<element_type, characteristic_type> get_partial_inverse(element_type e,
306  characteristic_type productOfCharacteristics) const {
307  return {get_inverse(e), productOfCharacteristics};
308  }
309 
315  static constexpr element_type get_additive_identity() { return 0; }
321  static constexpr element_type get_multiplicative_identity() { return 1; }
329  [[maybe_unused]] characteristic_type productOfCharacteristics) {
330  return 1;
331  }
332 
333  // static constexpr bool handles_only_z2() { return false; }
334 
339  std::swap(characteristic_, other.characteristic_);
340  inverse_.swap(other.inverse_);
341  return *this;
342  }
347  std::swap(f1.characteristic_, f2.characteristic_);
348  f1.inverse_.swap(f2.inverse_);
349  }
350 
351  private:
352  characteristic_type characteristic_;
353  std::vector<element_type> inverse_;
355  static element_type _add(element_type e1, element_type e2, characteristic_type characteristic) {
356  if (UINT_MAX - e1 < e2) {
357  // automatic unsigned integer overflow behaviour will make it work
358  e1 += e2;
359  e1 -= characteristic;
360  return e1;
361  }
362 
363  e1 += e2;
364  if (e1 >= characteristic) e1 -= characteristic;
365 
366  return e1;
367  }
368  static element_type _substract(element_type e1, element_type e2, characteristic_type characteristic) {
369  if (e1 < e2) {
370  e1 += characteristic;
371  }
372  e1 -= e2;
373 
374  return e1;
375  }
376  static element_type _multiply(element_type e1, element_type e2, characteristic_type characteristic) {
377  unsigned int a = e1;
378  e1 = 0;
379  unsigned int temp_b;
380 
381  while (a != 0) {
382  if (a & 1) {
383  if (e2 >= characteristic - e1) e1 -= characteristic;
384  e1 += e2;
385  }
386  a >>= 1;
387 
388  temp_b = e2;
389  if (e2 >= characteristic - e2) temp_b -= characteristic;
390  e2 += temp_b;
391  }
392 
393  return e1;
394  }
395 };
396 
397 } // namespace persistence_fields
398 } // namespace Gudhi
399 
400 #endif // MATRIX_FIELD_ZP_OPERATOR_H_
Class defining operators for the field for any prime number .
Definition: Zp_field_operators.h:41
static constexpr element_type get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition: Zp_field_operators.h:321
void substract_inplace_back(element_type e1, element_type &e2) const
Stores in the second element the substraction in the field of the first element by the second element...
Definition: Zp_field_operators.h:176
Zp_field_operators(characteristic_type characteristic=0)
Default constructor. If a non-zero characteristic is given, initializes the field with it....
Definition: Zp_field_operators.h:54
Zp_field_operators(const Zp_field_operators &toCopy)
Copy constructor.
Definition: Zp_field_operators.h:62
Zp_field_operators(Zp_field_operators &&toMove) noexcept
Move constructor.
Definition: Zp_field_operators.h:69
element_type multiply(element_type e1, element_type e2) const
Returns the multiplication of two elements in the field.
Definition: Zp_field_operators.h:187
Unsigned_integer_type element_type
Definition: Zp_field_operators.h:43
element_type multiply_and_add(element_type e, element_type m, element_type a) const
Multiplies the first element with the second one and adds the third one. Returns the result in the fi...
Definition: Zp_field_operators.h:212
void multiply_inplace(element_type &e1, element_type e2) const
Stores in the first element the multiplication of two given elements in the field,...
Definition: Zp_field_operators.h:198
element_type add(element_type e1, element_type e2) const
Returns the sum of two elements in the field.
Definition: Zp_field_operators.h:133
static constexpr element_type get_additive_identity()
Returns the additive identity of the field.
Definition: Zp_field_operators.h:315
void set_characteristic(characteristic_type characteristic)
Sets the characteristic of the field.
Definition: Zp_field_operators.h:77
void multiply_and_add_inplace_front(element_type &e, element_type m, element_type a) const
Multiplies the first element with the second one and adds the third one, that is (e * m + a) % charac...
Definition: Zp_field_operators.h:224
static constexpr element_type 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_operators.h:328
void substract_inplace_front(element_type &e1, element_type e2) const
Stores in the first element the substraction in the field of the first element by the second element,...
Definition: Zp_field_operators.h:166
element_type add_and_multiply(element_type e, element_type a, element_type m) const
Adds the first element to the second one and multiplies the third one with it. Returns the result in ...
Definition: Zp_field_operators.h:252
void add_and_multiply_inplace_front(element_type &e, element_type a, element_type m) const
Adds the first element to the second one and multiplies the third one with it, that is ((e + a) * m) ...
Definition: Zp_field_operators.h:264
element_type get_inverse(element_type e) const
Returns the inverse of the given element in the field.
Definition: Zp_field_operators.h:297
element_type substract(element_type e1, element_type e2) const
Returns the substraction in the field of the first element by the second element.
Definition: Zp_field_operators.h:155
void add_and_multiply_inplace_back(element_type e, element_type a, element_type &m) const
Adds the first element to the second one and multiplies the third one with it, that is ((e + a) * m) ...
Definition: Zp_field_operators.h:277
void multiply_and_add_inplace_back(element_type e, element_type m, element_type &a) const
Multiplies the first element with the second one and adds the third one, that is (e * m + a) % charac...
Definition: Zp_field_operators.h:237
const characteristic_type & get_characteristic() const
Returns the current characteristic.
Definition: Zp_field_operators.h:101
element_type get_value(element_type e) const
Returns the value of an integer in the field. That is the positive value of the integer modulo the cu...
Definition: Zp_field_operators.h:110
friend void swap(Zp_field_operators &f1, Zp_field_operators &f2)
Swap operator.
Definition: Zp_field_operators.h:346
element_type characteristic_type
Definition: Zp_field_operators.h:44
bool are_equal(element_type e1, element_type e2) const
Returns true if the two given elements are equal in the field, false otherwise.
Definition: Zp_field_operators.h:289
void add_inplace(element_type &e1, element_type e2) const
Stores in the first element the sum of two given elements in the field, that is (e1 + e2) % character...
Definition: Zp_field_operators.h:144
Zp_field_operators & operator=(Zp_field_operators other)
Assign operator.
Definition: Zp_field_operators.h:338
element_type get_value(Signed_integer_type e) const
Returns the value of an integer in the field. That is the positive value of the integer modulo the cu...
Definition: Zp_field_operators.h:120
std::pair< element_type, characteristic_type > get_partial_inverse(element_type e, characteristic_type productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the second argument.
Definition: Zp_field_operators.h:305
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14