2
This file is part of TON Blockchain Library.
4
TON Blockchain Library is free software: you can redistribute it and/or modify
5
it under the terms of the GNU Lesser General Public License as published by
6
the Free Software Foundation, either version 2 of the License, or
7
(at your option) any later version.
9
TON Blockchain Library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
17
Copyright 2017-2020 Telegram Systems LLP
28
void ResidueRing::init() {
29
Zero = new Residue(0, td::Ref<ResidueRing>(this));
30
One = new Residue(1, td::Ref<ResidueRing>(this));
33
ResidueRing::~ResidueRing() {
37
Zero = One = Img_i = 0;
40
const Residue operator+(const Residue& x, const Residue& y) {
42
Residue z(x.ring_ref());
43
bn_assert(BN_mod_add(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
47
const Residue operator-(const Residue& x, const Residue& y) {
49
Residue z(x.ring_ref());
50
bn_assert(BN_mod_sub(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
54
const Residue operator*(const Residue& x, const Residue& y) {
56
Residue z(x.ring_ref());
57
bn_assert(BN_mod_mul(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
61
const Residue operator-(const Residue& x) {
67
Residue& Residue::operator+=(const Residue& y) {
69
bn_assert(BN_mod_add(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
73
Residue& Residue::operator-=(const Residue& y) {
75
bn_assert(BN_mod_sub(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
79
Residue& Residue::operator*=(const Residue& y) {
81
bn_assert(BN_mod_mul(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
85
bool operator==(const Residue& x, const Residue& y) {
87
return x.extract() == y.extract();
90
bool operator!=(const Residue& x, const Residue& y) {
92
return x.extract() != y.extract();
95
Residue sqr(const Residue& x) {
96
Residue z(x.ring_ref());
97
bn_assert(BN_mod_sqr(z.val.bn_ptr(), x.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
101
Residue power(const Residue& x, const Bignum& y) {
102
Residue z(x.ring_ref());
103
bn_assert(BN_mod_exp(z.val.bn_ptr(), x.val.bn_ptr(), y.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
107
Residue inverse(const Residue& x) {
108
assert(x.ring_ref()->is_prime());
109
return power(x, x.ring_ref()->get_modulus() - 2);
112
const Residue& ResidueRing::img_i() const {
115
assert(modulus % 4 == 1);
117
Bignum n = (modulus - 1) / 4;
119
Residue t = power(frac(g), n);
120
if (t != one() && t != frac(-1)) {
121
Img_i = new Residue(t);
130
Residue sqrt(const Residue& x) {
131
assert(x.ring_of().is_prime());
132
const ResidueRing& R = x.ring_of();
133
const Bignum& p = R.get_modulus();
134
if (x.is_zero() || !p.odd()) {
137
if (p[1]) { // p=3 (mod 4)
138
return power(x, (p + 1) >> 2);
141
Residue t = power(x, (p + 3) >> 3);
142
return (sqr(t) == x) ? t : R.img_i() * t;
149
Residue ResidueRing::frac(long num, long denom) const {
155
if (!(num % denom)) {
156
return Residue(num / denom, self_ref());
158
return Residue(num, self_ref()) * inverse(Residue(denom, self_ref()));
162
std::string Residue::to_str() const {
163
return "Mod(" + val.to_str() + "," + modulus().to_str() + ")";
166
std::ostream& operator<<(std::ostream& os, const Residue& x) {
167
return os << x.to_str();
170
std::istream& operator>>(std::istream& is, Residue& x) {
173
x = dec_string(word);