Loading...
Searching...
No Matches
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
16
17#ifndef MATRIX_FIELD_ZP_VAR_H_
18#define MATRIX_FIELD_ZP_VAR_H_
19
20#include <utility>
21#include <vector>
22#include <climits>
23#include <stdexcept>
24
25namespace Gudhi {
26namespace persistence_fields {
27
40template <typename Unsigned_integer_type = unsigned int,
41 class = std::enable_if_t<std::is_unsigned_v<Unsigned_integer_type> > >
43{
44 public:
45 using Element = Unsigned_integer_type;
47 template <class T>
48 using isInteger = std::enable_if_t<std::is_integral_v<T> >;
49
53 Shared_Zp_field_element() : element_(0) {}
54
61 template <typename Integer_type, class = isInteger<Integer_type> >
62 Shared_Zp_field_element(Integer_type element) : element_(_get_value(element))
63 {}
64
71
77 Shared_Zp_field_element(Shared_Zp_field_element&& toMove) noexcept : element_(std::exchange(toMove.element_, 0)) {}
78
79 ~Shared_Zp_field_element() = default;
80
87 static void initialize(Characteristic characteristic)
88 {
89 if (characteristic <= 1)
90 throw std::invalid_argument("Characteristic must be strictly positive and a prime number.");
91
92 inverse_.resize(characteristic);
93 inverse_[0] = 0;
94 for (Element i = 1; i < characteristic; ++i) {
95 Element inv = 1;
96 Element mult = inv * i;
97 while ((mult % characteristic) != 1) {
98 ++inv;
99 if (mult == characteristic) throw std::invalid_argument("Characteristic must be a prime number.");
100 mult = inv * i;
101 }
102 inverse_[i] = inv;
103 }
104
105 characteristic_ = characteristic;
106 }
107
113 Element get_value() const { return element_; }
114
119 {
120 f1.element_ = Shared_Zp_field_element::_add(f1.element_, f2.element_);
121 }
122
127 {
128 f1 += f2;
129 return f1;
130 }
131
137 template <typename Integer_type, class = isInteger<Integer_type> >
138 friend void operator+=(Shared_Zp_field_element& f, const Integer_type& v)
139 {
140 f.element_ = Shared_Zp_field_element::_add(f.element_, _get_value(v));
141 }
142
148 template <typename Integer_type, class = isInteger<Integer_type> >
150 {
151 f += v;
152 return f;
153 }
154
160 template <typename Integer_type, class = isInteger<Integer_type> >
161 friend Integer_type operator+(const Integer_type& v, Shared_Zp_field_element f)
162 {
163 f += v;
164 return f.element_;
165 }
166
171 {
172 f1.element_ = Shared_Zp_field_element::_subtract(f1.element_, f2.element_);
173 }
174
179 {
180 f1 -= f2;
181 return f1;
182 }
183
189 template <typename Integer_type, class = isInteger<Integer_type> >
190 friend void operator-=(Shared_Zp_field_element& f, const Integer_type& v)
191 {
192 f.element_ = Shared_Zp_field_element::_subtract(f.element_, _get_value(v));
193 }
194
200 template <typename Integer_type, class = isInteger<Integer_type> >
202 {
203 f -= v;
204 return f;
205 }
206
212 template <typename Integer_type, class = isInteger<Integer_type> >
213 friend Integer_type operator-(const Integer_type& v, const Shared_Zp_field_element& f)
214 {
215 return Shared_Zp_field_element::_subtract(_get_value(v), f.element_);
216 }
217
222 {
223 f1.element_ = Shared_Zp_field_element::_multiply(f1.element_, f2.element_);
224 }
225
230 {
231 f1 *= f2;
232 return f1;
233 }
234
240 template <typename Integer_type, class = isInteger<Integer_type> >
241 friend void operator*=(Shared_Zp_field_element& f, const Integer_type& v)
242 {
243 f.element_ = Shared_Zp_field_element::_multiply(f.element_, _get_value(v));
244 }
245
251 template <typename Integer_type, class = isInteger<Integer_type> >
253 {
254 f *= v;
255 return f;
256 }
257
263 template <typename Integer_type, class = isInteger<Integer_type> >
264 friend Integer_type operator*(const Integer_type& v, Shared_Zp_field_element f)
265 {
266 f *= v;
267 return f.element_;
268 }
269
274 {
275 return f1.element_ == f2.element_;
276 }
277
283 template <typename Integer_type, class = isInteger<Integer_type> >
284 friend bool operator==(const Integer_type& v, const Shared_Zp_field_element& f)
285 {
286 return Shared_Zp_field_element::_get_value(v) == f.element_;
287 }
288
294 template <typename Integer_type, class = isInteger<Integer_type> >
295 friend bool operator==(const Shared_Zp_field_element& f, const Integer_type& v)
296 {
297 return Shared_Zp_field_element::_get_value(v) == f.element_;
298 }
299
303 friend bool operator!=(const Shared_Zp_field_element& f1, const Shared_Zp_field_element& f2) { return !(f1 == f2); }
304
310 template <typename Integer_type, class = isInteger<Integer_type> >
311 friend bool operator!=(const Integer_type& v, const Shared_Zp_field_element& f)
312 {
313 return !(v == f);
314 }
315
321 template <typename Integer_type, class = isInteger<Integer_type> >
322 friend bool operator!=(const Shared_Zp_field_element& f, const Integer_type& v)
323 {
324 return !(v == f);
325 }
326
331 {
332 std::swap(element_, other.element_);
333 return *this;
334 }
335
340 {
341 if (this == &other) return *this;
342
343 element_ = std::exchange(other.element_, 0);
344 return *this;
345 }
346
352 template <typename Integer_type, class = isInteger<Integer_type> >
353 Shared_Zp_field_element& operator=(const Integer_type& value)
354 {
355 element_ = Shared_Zp_field_element::_get_value(value);
356 return *this;
357 }
358
363 {
364 std::swap(f1.element_, f2.element_);
365 }
366
370 operator unsigned int() const { return element_; }
371
377 Shared_Zp_field_element get_inverse() const { return Shared_Zp_field_element(inverse_[element_]); }
378
385 std::pair<Shared_Zp_field_element, Characteristic> get_partial_inverse(Characteristic productOfCharacteristics) const
386 {
387 return {get_inverse(), productOfCharacteristics};
388 }
389
396
403
411 [[maybe_unused]] Characteristic productOfCharacteristics)
412 {
413 return Shared_Zp_field_element(1);
414 }
415
421 static Characteristic get_characteristic() { return characteristic_; }
422
423 // static constexpr bool handles_only_z2() { return false; }
424
425 private:
426 Element element_;
427 static inline Characteristic characteristic_;
428 static inline std::vector<Element> inverse_;
429
430 static Element _add(Element element, Element v)
431 {
432 if (UINT_MAX - element < v) {
433 // automatic unsigned integer overflow behaviour will make it work
434 element += v;
435 element -= characteristic_;
436 return element;
437 }
438
439 element += v;
440 if (element >= characteristic_) element -= characteristic_;
441
442 return element;
443 }
444
445 static Element _subtract(Element element, Element v)
446 {
447 if (element < v) {
448 element += characteristic_;
449 }
450 element -= v;
451
452 return element;
453 }
454
455 static Element _multiply(Element element, Element v)
456 {
457 Element a = element;
458 element = 0;
459 Element temp_b;
460
461 while (a != 0) {
462 if (a & 1) {
463 if (v >= characteristic_ - element) element -= characteristic_;
464 element += v;
465 }
466 a >>= 1;
467
468 temp_b = v;
469 if (v >= characteristic_ - v) temp_b -= characteristic_;
470 v += temp_b;
471 }
472
473 return element;
474 }
475
476 template <typename Integer_type, class = isInteger<Integer_type> >
477 static constexpr Element _get_value(Integer_type e)
478 {
479 if constexpr (std::is_signed_v<Integer_type>) {
480 if (e < -static_cast<Integer_type>(characteristic_)) e = e % characteristic_;
481 if (e < 0) return e += characteristic_;
482 return e < static_cast<Integer_type>(characteristic_) ? e : e % characteristic_;
483 } else {
484 return e < characteristic_ ? e : e % characteristic_;
485 }
486 }
487};
488
489} // namespace persistence_fields
490} // namespace Gudhi
491
492#endif // MATRIX_FIELD_ZP_VAR_H_
Class representing an element of the field for any prime number . If each instantiation of the class...
Definition Zp_field_shared.h:43
Shared_Zp_field_element & operator=(Shared_Zp_field_element &&other) noexcept
Move assign operator.
Definition Zp_field_shared.h:339
static void initialize(Characteristic characteristic)
Initialize the field to the given characteristic. Should be called first before constructing the fiel...
Definition Zp_field_shared.h:87
friend bool operator==(const Shared_Zp_field_element &f, const Integer_type &v)
operator==
Definition Zp_field_shared.h:295
Shared_Zp_field_element get_inverse() const
Returns the inverse of the element in the field.
Definition Zp_field_shared.h:377
friend bool operator==(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator==
Definition Zp_field_shared.h:273
Shared_Zp_field_element()
Default constructor. Sets the element to 0.
Definition Zp_field_shared.h:53
Shared_Zp_field_element & operator=(const Integer_type &value)
Assign operator.
Definition Zp_field_shared.h:353
friend bool operator==(const Integer_type &v, const Shared_Zp_field_element &f)
operator==
Definition Zp_field_shared.h:284
Shared_Zp_field_element & operator=(Shared_Zp_field_element other)
Assign operator.
Definition Zp_field_shared.h:330
friend Integer_type operator+(const Integer_type &v, Shared_Zp_field_element f)
operator+
Definition Zp_field_shared.h:161
Element Characteristic
Definition Zp_field_shared.h:46
friend void operator-=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator-=
Definition Zp_field_shared.h:170
friend Integer_type operator*(const Integer_type &v, Shared_Zp_field_element f)
operator*
Definition Zp_field_shared.h:264
friend Shared_Zp_field_element operator+(Shared_Zp_field_element f, const Integer_type &v)
operator+
Definition Zp_field_shared.h:149
friend bool operator!=(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator!=
Definition Zp_field_shared.h:303
friend void operator*=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator*=
Definition Zp_field_shared.h:221
static Shared_Zp_field_element get_partial_multiplicative_identity(Characteristic productOfCharacteristics)
For interface purposes with multi-fields. Returns the multiplicative identity of the field.
Definition Zp_field_shared.h:410
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f, const Integer_type &v)
operator*
Definition Zp_field_shared.h:252
static Shared_Zp_field_element get_additive_identity()
Returns the additive identity of the field.
Definition Zp_field_shared.h:395
friend void operator-=(Shared_Zp_field_element &f, const Integer_type &v)
operator-=
Definition Zp_field_shared.h:190
Unsigned_integer_type Element
Definition Zp_field_shared.h:45
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
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:126
static Shared_Zp_field_element get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition Zp_field_shared.h:402
friend void operator*=(Shared_Zp_field_element &f, const Integer_type &v)
operator*=
Definition Zp_field_shared.h:241
friend void swap(Shared_Zp_field_element &f1, Shared_Zp_field_element &f2) noexcept
Swap operator.
Definition Zp_field_shared.h:362
static Characteristic get_characteristic()
Returns the current characteristic.
Definition Zp_field_shared.h:421
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f, const Integer_type &v)
operator-
Definition Zp_field_shared.h:201
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator*
Definition Zp_field_shared.h:229
Element get_value() const
Returns the value of the element.
Definition Zp_field_shared.h:113
Shared_Zp_field_element(Integer_type element)
Constructor setting the element to the given value.
Definition Zp_field_shared.h:62
friend bool operator!=(const Integer_type &v, const Shared_Zp_field_element &f)
operator!=
Definition Zp_field_shared.h:311
std::pair< Shared_Zp_field_element, Characteristic > get_partial_inverse(Characteristic productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the argument.
Definition Zp_field_shared.h:385
friend Integer_type operator-(const Integer_type &v, const Shared_Zp_field_element &f)
operator-
Definition Zp_field_shared.h:213
Shared_Zp_field_element(Shared_Zp_field_element &&toMove) noexcept
Move constructor.
Definition Zp_field_shared.h:77
friend void operator+=(Shared_Zp_field_element &f, const Integer_type &v)
operator+=
Definition Zp_field_shared.h:138
friend bool operator!=(const Shared_Zp_field_element &f, const Integer_type &v)
operator!=
Definition Zp_field_shared.h:322
friend void operator+=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator+=
Definition Zp_field_shared.h:118
Shared_Zp_field_element(const Shared_Zp_field_element &toCopy)=default
Copy constructor.
Field namespace.
Definition Intro_field_elements_and_operators.h:16
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14