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
25namespace Gudhi {
27namespace persistence_fields {
28
38template <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 isSignedInteger = std::enable_if_t<std::is_signed_v<T> >;
47
54 Zp_field_operators(Characteristic 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 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& get_characteristic() const { return characteristic_; }
102
110 Element get_value(Element e) const { return e < characteristic_ ? e : e % characteristic_; }
119 template <typename Signed_integer_type, class = isSignedInteger<Signed_integer_type> >
120 Element 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
133 Element add(Element e1, Element e2) const {
134 return _add(get_value(e1), get_value(e2), characteristic_);
135 }
136
144 void add_inplace(Element& e1, Element e2) const {
145 e1 = _add(get_value(e1), get_value(e2), characteristic_);
146 }
147
156 return _subtract(get_value(e1), get_value(e2), characteristic_);
157 }
158
167 e1 = _subtract(get_value(e1), get_value(e2), characteristic_);
168 }
177 e2 = _subtract(get_value(e1), get_value(e2), characteristic_);
178 }
179
188 return _multiply(get_value(e1), get_value(e2), characteristic_);
189 }
190
198 void multiply_inplace(Element& e1, Element e2) const {
199 e1 = _multiply(get_value(e1), get_value(e2), characteristic_);
200 }
201
212 Element multiply_and_add(Element e, Element m, Element a) const { return get_value(e * m + a); }
213
225 e = get_value(e * m + a);
226 }
238 a = get_value(e * m + a);
239 }
240
252 Element add_and_multiply(Element e, Element a, Element m) const { return get_value((e + a) * m); }
253
265 e = get_value((e + a) * m);
266 }
278 m = get_value((e + a) * m);
279 }
280
289 bool are_equal(Element e1, Element e2) const { return get_value(e1) == get_value(e2); }
290
297 Element get_inverse(Element e) const { return inverse_[get_value(e)]; }
305 std::pair<Element, Characteristic> get_partial_inverse(Element e,
306 Characteristic productOfCharacteristics) const {
307 return {get_inverse(e), productOfCharacteristics};
308 }
309
315 static constexpr Element get_additive_identity() { return 0; }
321 static constexpr Element get_multiplicative_identity() { return 1; }
329 [[maybe_unused]] Characteristic 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 characteristic_;
353 std::vector<Element> inverse_;
355 static Element _add(Element e1, Element e2, Characteristic 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 _subtract(Element e1, Element e2, Characteristic characteristic) {
369 if (e1 < e2) {
370 e1 += characteristic;
371 }
372 e1 -= e2;
373
374 return e1;
375 }
376 static Element _multiply(Element e1, Element e2, Characteristic 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
void multiply_and_add_inplace_back(Element e, Element m, Element &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 & get_characteristic() const
Returns the current characteristic.
Definition: Zp_field_operators.h:101
Zp_field_operators(const Zp_field_operators &toCopy)
Copy constructor.
Definition: Zp_field_operators.h:62
Element get_inverse(Element e) const
Returns the inverse of the given element in the field.
Definition: Zp_field_operators.h:297
Element multiply_and_add(Element e, Element m, Element 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
Zp_field_operators(Zp_field_operators &&toMove) noexcept
Move constructor.
Definition: Zp_field_operators.h:69
Element get_value(Element 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
Element add(Element e1, Element e2) const
Returns the sum of two elements in the field.
Definition: Zp_field_operators.h:133
void set_characteristic(Characteristic characteristic)
Sets the characteristic of the field.
Definition: Zp_field_operators.h:77
Element Characteristic
Definition: Zp_field_operators.h:44
std::pair< Element, Characteristic > get_partial_inverse(Element e, Characteristic productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the second argument.
Definition: Zp_field_operators.h:305
void add_and_multiply_inplace_back(Element e, Element a, Element &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
Zp_field_operators(Characteristic characteristic=0)
Default constructor. If a non-zero characteristic is given, initializes the field with it....
Definition: Zp_field_operators.h:54
Unsigned_integer_type Element
Definition: Zp_field_operators.h:43
static constexpr Element get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition: Zp_field_operators.h:321
bool are_equal(Element e1, Element e2) const
Returns true if the two given elements are equal in the field, false otherwise.
Definition: Zp_field_operators.h:289
void add_and_multiply_inplace_front(Element &e, Element a, Element 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
static constexpr Element get_additive_identity()
Returns the additive identity of the field.
Definition: Zp_field_operators.h:315
void subtract_inplace_back(Element e1, Element &e2) const
Stores in the second element the subtraction in the field of the first element by the second element,...
Definition: Zp_field_operators.h:176
Element 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
Zp_field_operators & operator=(Zp_field_operators other)
Assign operator.
Definition: Zp_field_operators.h:338
friend void swap(Zp_field_operators &f1, Zp_field_operators &f2)
Swap operator.
Definition: Zp_field_operators.h:346
static constexpr Element get_partial_multiplicative_identity(Characteristic productOfCharacteristics)
For interface purposes with multi-fields. Returns the multiplicative identity of the field.
Definition: Zp_field_operators.h:328
Element multiply(Element e1, Element e2) const
Returns the multiplication of two elements in the field.
Definition: Zp_field_operators.h:187
Element subtract(Element e1, Element e2) const
Returns the subtraction in the field of the first element by the second element.
Definition: Zp_field_operators.h:155
void multiply_and_add_inplace_front(Element &e, Element m, Element 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
void multiply_inplace(Element &e1, Element e2) const
Stores in the first element the multiplication of two given elements in the field,...
Definition: Zp_field_operators.h:198
void subtract_inplace_front(Element &e1, Element e2) const
Stores in the first element the subtraction in the field of the first element by the second element,...
Definition: Zp_field_operators.h:166
Element add_and_multiply(Element e, Element a, Element 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_inplace(Element &e1, Element 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
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14