Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/bernmm/bern_modp_util.cpp
4057 views
1
/*
2
bern_modp_util.cpp: number-theoretic utility functions
3
4
Copyright (C) 2008, 2009, David Harvey
5
6
This file is part of the bernmm package (version 1.1).
7
8
bernmm is released under a BSD-style license. See the README file in
9
the source distribution for details.
10
*/
11
12
13
#include <NTL/ZZ.h>
14
#include "bern_modp_util.h"
15
16
17
NTL_CLIENT;
18
19
20
namespace bernmm {
21
22
23
long PowerMod(long a, long ee, long n, double ninv)
24
{
25
long x, y;
26
27
unsigned long e;
28
29
if (ee < 0)
30
e = - ((unsigned long) ee);
31
else
32
e = ee;
33
34
x = 1;
35
y = a;
36
while (e) {
37
if (e & 1) x = MulMod(x, y, n, ninv);
38
y = MulMod(y, y, n, ninv);
39
e = e >> 1;
40
}
41
42
if (ee < 0) x = InvMod(x, n);
43
44
return x;
45
}
46
47
48
49
void Factorisation::helper(long k, long m)
50
{
51
if (m == 1)
52
return;
53
54
for (long i = k + 1; i * i <= m; i++)
55
{
56
if (m % i == 0)
57
{
58
// found a factor
59
factors.push_back(i);
60
// remove that factor entirely
61
for (m /= i; m % i == 0; m /= i);
62
// recurse
63
helper(i, m);
64
return;
65
}
66
}
67
68
// no more factors
69
factors.push_back(m);
70
}
71
72
73
Factorisation::Factorisation(long n)
74
{
75
this->n = n;
76
helper(1, n);
77
}
78
79
80
PrimeTable::PrimeTable(long bound)
81
{
82
long size = (bound - 1) / ULONG_BITS + 1; // = ceil(bound / ULONG_BITS)
83
data.resize(size);
84
85
for (long i = 2; i * i < bound; i++)
86
if (is_prime(i))
87
for (long j = 2*i; j < bound; j += i)
88
set(j);
89
}
90
91
92
long order(long x, long p, double pinv, const Factorisation& F)
93
{
94
// in the loop below, m is always some multiple of the order of x
95
long m = p - 1;
96
97
// try to remove factors from m until we can't remove any more
98
for (int i = 0; i < F.factors.size(); i++)
99
{
100
long q = F.factors[i];
101
102
while (m % q == 0)
103
{
104
long mm = m / q;
105
if (PowerMod(x, mm, p, pinv) != 1)
106
break;
107
m = mm;
108
}
109
}
110
111
return m;
112
}
113
114
115
116
long primitive_root(long p, double pinv, const Factorisation& F)
117
{
118
if (p == 2)
119
return 1;
120
121
long g = 2;
122
for (; g < p; g++)
123
if (order(g, p, pinv, F) == p - 1)
124
return g;
125
126
// no generator exists!?
127
abort();
128
}
129
130
131
132
}; // end namespace
133
134
135
// end of file ================================================================
136
137