-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathelement.h
100 lines (73 loc) · 2 KB
/
element.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef H_ELEMENT
#define H_ELEMENT
#include "repr.h"
// Compute unit a layer above representation
template <class E>
class Element
{
public:
template <class C>
static E one(C const &context);
template <class C>
static E zero(C const &context);
virtual E one() const = 0;
virtual E zero() const = 0;
virtual E &self() = 0;
virtual E const &self() const = 0;
virtual void serialize(u8 mod_byte_len, std::vector<u8> &data) const = 0;
// Computes the multiplicative inverse of this element, if nonzero.
virtual Option<E> inverse() const = 0;
virtual void square() = 0;
virtual void mul2() = 0;
virtual void mul(E const &e) = 0;
virtual void sub(E const &e) = 0;
virtual void add(E const &e) = 0;
virtual void negate() = 0;
virtual bool is_zero() const = 0;
virtual bool operator==(E const &other) const = 0;
virtual bool operator!=(E const &other) const = 0;
// ********************* DEFAULT IMPLEMENTED ***************** //
template <usize N>
E pow(Repr<N> const &e) const
{
auto res = this->one();
auto found_one = false;
for (auto it = RevBitIterator(e); it.before();)
{
auto i = *it;
if (found_one)
{
res.square();
}
else
{
found_one = i;
}
if (i)
{
res.mul(self());
}
}
return res;
}
template <usize N>
bool is_non_nth_root_with(u64 n, Repr<N> power) const
{
if (is_zero())
{
return false;
}
constexpr Repr<N> one = {1};
power = cbn::subtract_ignore_carry(power, one);
Repr<N> divisor = {n};
if (!cbn::is_zero(power % divisor))
{
return false;
}
power = power / divisor;
auto l = this->pow(power);
auto e_one = this->one();
return l != e_one;
}
};
#endif