Loading...
Searching...
No Matches
Zp_field.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
16
17#ifndef MATRIX_FIELD_ZP_H_
18#define MATRIX_FIELD_ZP_H_
19
20#include <utility>
21#include <array>
22#include <climits>
23
24namespace Gudhi {
25namespace persistence_fields {
26
37template <unsigned int characteristic,
38 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 = Unsigned_integer_type;
45 template <class T>
46 using isInteger = std::enable_if_t<std::is_integral_v<T> >;
47
51 Zp_field_element() : element_(0) { static_assert(_is_prime(), "Characteristic has to be a prime number."); }
52
59 template <typename Integer_type, class = isInteger<Integer_type> >
60 Zp_field_element(Integer_type element) : element_(_get_value(element))
61 {
62 static_assert(_is_prime(), "Characteristic has to be a prime number.");
63 }
64
70 Zp_field_element(const Zp_field_element& toCopy) = default;
71
77 Zp_field_element(Zp_field_element&& toMove) noexcept : element_(std::exchange(toMove.element_, 0)) {}
78
79 ~Zp_field_element() = default;
80
84 friend void operator+=(Zp_field_element& f1, const Zp_field_element& f2)
85 {
86 f1.element_ = Zp_field_element::_add(f1.element_, f2.element_);
87 }
88
93 {
94 f1 += f2;
95 return f1;
96 }
97
101 template <typename Integer_type, class = isInteger<Integer_type> >
102 friend void operator+=(Zp_field_element& f, const Integer_type& v)
103 {
104 f.element_ = Zp_field_element::_add(f.element_, _get_value(v));
105 }
106
112 template <typename Integer_type, class = isInteger<Integer_type> >
113 friend Zp_field_element operator+(Zp_field_element f, const Integer_type& v)
114 {
115 f += v;
116 return f;
117 }
118
124 template <typename Integer_type, class = isInteger<Integer_type> >
125 friend Integer_type operator+(const Integer_type& v, Zp_field_element f)
126 {
127 f += v;
128 return f.element_;
129 }
130
134 friend void operator-=(Zp_field_element& f1, const Zp_field_element& f2)
135 {
136 f1.element_ = Zp_field_element::_subtract(f1.element_, f2.element_);
137 }
138
143 {
144 f1 -= f2;
145 return f1;
146 }
147
151 template <typename Integer_type, class = isInteger<Integer_type> >
152 friend void operator-=(Zp_field_element& f, const Integer_type& v)
153 {
154 f.element_ = Zp_field_element::_subtract(f.element_, _get_value(v));
155 }
156
162 template <typename Integer_type, class = isInteger<Integer_type> >
163 friend Zp_field_element operator-(Zp_field_element f, const Integer_type& v)
164 {
165 f -= v;
166 return f;
167 }
168
174 template <typename Integer_type, class = isInteger<Integer_type> >
175 friend Integer_type operator-(const Integer_type& v, const Zp_field_element& f)
176 {
177 return Zp_field_element::_subtract(_get_value(v), f.element_);
178 }
179
183 friend void operator*=(Zp_field_element& f1, const Zp_field_element& f2)
184 {
185 f1.element_ = Zp_field_element::_multiply(f1.element_, f2.element_);
186 }
187
192 {
193 f1 *= f2;
194 return f1;
195 }
196
200 template <typename Integer_type, class = isInteger<Integer_type> >
201 friend void operator*=(Zp_field_element& f, const Integer_type& v)
202 {
203 f.element_ = Zp_field_element::_multiply(f.element_, _get_value(v));
204 }
205
211 template <typename Integer_type, class = isInteger<Integer_type> >
212 friend Zp_field_element operator*(Zp_field_element f, const Integer_type& v)
213 {
214 f *= v;
215 return f;
216 }
217
223 template <typename Integer_type, class = isInteger<Integer_type> >
224 friend Integer_type operator*(const Integer_type& v, Zp_field_element f)
225 {
226 f *= v;
227 return f.element_;
228 }
229
233 friend bool operator==(const Zp_field_element& f1, const Zp_field_element& f2) { return f1.element_ == f2.element_; }
234
240 template <typename Integer_type, class = isInteger<Integer_type> >
241 friend bool operator==(const Integer_type& v, const Zp_field_element& f)
242 {
243 return Zp_field_element::_get_value(v) == f.element_;
244 }
245
251 template <typename Integer_type, class = isInteger<Integer_type> >
252 friend bool operator==(const Zp_field_element& f, const Integer_type& v)
253 {
254 return Zp_field_element::_get_value(v) == f.element_;
255 }
256
260 friend bool operator!=(const Zp_field_element& f1, const Zp_field_element& f2) { return !(f1 == f2); }
261
267 template <typename Integer_type, class = isInteger<Integer_type> >
268 friend bool operator!=(const Integer_type& v, const Zp_field_element& f)
269 {
270 return !(v == f);
271 }
272
278 template <typename Integer_type, class = isInteger<Integer_type> >
279 friend bool operator!=(const Zp_field_element& f, const Integer_type& v)
280 {
281 return !(v == f);
282 }
283
288 {
289 std::swap(element_, other.element_);
290 return *this;
291 }
292
297 {
298 if (this == &other) return *this;
299
300 element_ = std::exchange(other.element_, 0);
301 return *this;
302 }
303
309 template <typename Integer_type, class = isInteger<Integer_type> >
310 Zp_field_element& operator=(const Integer_type& value)
311 {
312 element_ = _get_value(value);
313 return *this;
314 }
315
319 friend void swap(Zp_field_element& f1, Zp_field_element& f2) noexcept { std::swap(f1.element_, f2.element_); }
320
324 operator unsigned int() const { return element_; }
325
332 {
333 if (element_ != 0 && inverse_[element_] == 0) { // initialize everything at instantiation instead?
334 inverse_[element_] = _get_inverse(element_);
335 }
336
337 return Zp_field_element<characteristic>(inverse_[element_]);
338 }
339
346 std::pair<Zp_field_element, unsigned int> get_partial_inverse(unsigned int productOfCharacteristics) const
347 {
348 return {get_inverse(), productOfCharacteristics};
349 }
350
357
364
371 static Zp_field_element get_partial_multiplicative_identity([[maybe_unused]] unsigned int productOfCharacteristics)
372 {
374 }
375
381 static constexpr unsigned int get_characteristic() { return characteristic; }
382
388 Element get_value() const { return element_; }
389
390 // static constexpr bool handles_only_z2() { return false; }
391
392 private:
393 Element element_;
394 static inline std::array<unsigned int, characteristic> inverse_;
395
396 static Element _add(Element element, Element v)
397 {
398 if (UINT_MAX - element < v) {
399 // automatic unsigned integer overflow behaviour will make it work
400 element += v;
401 element -= characteristic;
402 return element;
403 }
404
405 element += v;
406 if (element >= characteristic) element -= characteristic;
407
408 return element;
409 }
410
411 static Element _subtract(Element element, Element v)
412 {
413 if (element < v) {
414 element += characteristic;
415 }
416 element -= v;
417
418 return element;
419 }
420
421 static Element _multiply(Element element, Element v)
422 {
423 Element a = element;
424 element = 0;
425 Element temp_b;
426
427 while (a != 0) {
428 if (a & 1) {
429 if (v >= characteristic - element) element -= characteristic;
430 element += v;
431 }
432 a >>= 1;
433
434 temp_b = v;
435 if (v >= characteristic - v) temp_b -= characteristic;
436 v += temp_b;
437 }
438
439 return element;
440 }
441
442 static int _get_inverse(Element element)
443 {
444 // to solve: Ax + My = 1
445 int M = characteristic;
446 int A = element;
447 int y = 0, x = 1;
448 // extended euclidean division
449 while (A > 1) {
450 int quotient = A / M;
451 int temp = M;
452
453 M = A % M, A = temp;
454 temp = y;
455
456 y = x - quotient * y;
457 x = temp;
458 }
459
460 if (x < 0) x += characteristic;
461
462 return x;
463 }
464
465 template <typename Integer_type, class = isInteger<Integer_type> >
466 static constexpr Element _get_value(Integer_type e)
467 {
468 if constexpr (std::is_signed_v<Integer_type>) {
469 if (e < -static_cast<Integer_type>(characteristic)) e = e % characteristic;
470 if (e < 0) return e += characteristic;
471 return e < static_cast<Integer_type>(characteristic) ? e : e % characteristic;
472 } else {
473 return e < characteristic ? e : e % characteristic;
474 }
475 }
476
477 static constexpr bool _is_prime()
478 {
479 if (characteristic <= 1) return false;
480 if (characteristic <= 3) return true;
481 if (characteristic % 2 == 0 || characteristic % 3 == 0) return false;
482
483 for (long i = 5; i * i <= characteristic; i = i + 6)
484 if (characteristic % i == 0 || characteristic % (i + 2) == 0) return false;
485
486 return true;
487 }
488};
489
490} // namespace persistence_fields
491} // namespace Gudhi
492
493#endif // MATRIX_FIELD_ZP_H_
Class representing an element of the field for any prime number .
Definition Zp_field.h:41
Zp_field_element(Integer_type element)
Constructor setting the element to the given value.
Definition Zp_field.h:60
Zp_field_element & operator=(Zp_field_element other)
Assign operator.
Definition Zp_field.h:287
friend Zp_field_element operator-(Zp_field_element f1, const Zp_field_element &f2)
operator-
Definition Zp_field.h:142
Zp_field_element & operator=(const Integer_type &value)
Assign operator.
Definition Zp_field.h:310
friend Zp_field_element operator-(Zp_field_element f, const Integer_type &v)
operator-
Definition Zp_field.h:163
friend Integer_type operator*(const Integer_type &v, Zp_field_element f)
operator*
Definition Zp_field.h:224
static Zp_field_element get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition Zp_field.h:363
Zp_field_element get_inverse() const
Returns the inverse of the element in the field.
Definition Zp_field.h:331
Unsigned_integer_type Element
Definition Zp_field.h:43
friend Integer_type operator+(const Integer_type &v, Zp_field_element f)
operator+
Definition Zp_field.h:125
friend bool operator!=(const Integer_type &v, const Zp_field_element &f)
operator!=
Definition Zp_field.h:268
friend void operator+=(Zp_field_element &f, const Integer_type &v)
operator+=
Definition Zp_field.h:102
friend Zp_field_element operator*(Zp_field_element f, const Integer_type &v)
operator*
Definition Zp_field.h:212
friend void operator-=(Zp_field_element &f1, const Zp_field_element &f2)
operator-=
Definition Zp_field.h:134
friend bool operator==(const Zp_field_element &f1, const Zp_field_element &f2)
operator==
Definition Zp_field.h:233
Element get_value() const
Returns the value of the element.
Definition Zp_field.h:388
friend void operator*=(Zp_field_element &f, const Integer_type &v)
operator*=
Definition Zp_field.h:201
Zp_field_element & operator=(Zp_field_element &&other) noexcept
Move assign operator.
Definition Zp_field.h:296
friend void operator*=(Zp_field_element &f1, const Zp_field_element &f2)
operator*=
Definition Zp_field.h:183
friend Integer_type operator-(const Integer_type &v, const Zp_field_element &f)
operator-
Definition Zp_field.h:175
Zp_field_element(Zp_field_element &&toMove) noexcept
Move constructor.
Definition Zp_field.h:77
std::pair< Zp_field_element, unsigned int > get_partial_inverse(unsigned int productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the argument.
Definition Zp_field.h:346
static Zp_field_element get_partial_multiplicative_identity(unsigned int productOfCharacteristics)
For interface purposes with multi-fields. Returns the multiplicative identity of the field.
Definition Zp_field.h:371
friend Zp_field_element operator*(Zp_field_element f1, const Zp_field_element &f2)
operator*
Definition Zp_field.h:191
friend Zp_field_element operator+(Zp_field_element f, const Integer_type &v)
operator+
Definition Zp_field.h:113
friend void operator-=(Zp_field_element &f, const Integer_type &v)
operator-=
Definition Zp_field.h:152
friend bool operator==(const Zp_field_element &f, const Integer_type &v)
operator==
Definition Zp_field.h:252
Zp_field_element()
Default constructor. Sets the element to 0.
Definition Zp_field.h:51
friend bool operator!=(const Zp_field_element &f, const Integer_type &v)
operator!=
Definition Zp_field.h:279
static Zp_field_element get_additive_identity()
Returns the additive identity of the field.
Definition Zp_field.h:356
static constexpr unsigned int get_characteristic()
Returns the current characteristic.
Definition Zp_field.h:381
friend void swap(Zp_field_element &f1, Zp_field_element &f2) noexcept
Swap operator.
Definition Zp_field.h:319
friend bool operator==(const Integer_type &v, const Zp_field_element &f)
operator==
Definition Zp_field.h:241
Zp_field_element(const Zp_field_element &toCopy)=default
Copy constructor.
friend Zp_field_element operator+(Zp_field_element f1, const Zp_field_element &f2)
operator+
Definition Zp_field.h:92
friend bool operator!=(const Zp_field_element &f1, const Zp_field_element &f2)
operator!=
Definition Zp_field.h:260
Element Characteristic
Definition Zp_field.h:44
friend void operator+=(Zp_field_element &f1, const Zp_field_element &f2)
operator+=
Definition Zp_field.h:84
Field namespace.
Definition Intro_field_elements_and_operators.h:16
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14