-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathqidloop.cc
More file actions
135 lines (120 loc) · 5.08 KB
/
qidloop.cc
File metadata and controls
135 lines (120 loc) · 5.08 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// FILE QIDLOOP.CC
#include "qidloop.h"
Qidealooper::Qidealooper(long nmin, long nmax, int both_conjugates, int sorted)
: n(nmin), maxn(nmax), both(both_conjugates), sort(sorted)
{
vector<Qideal> Ilist = (sort? Qideal_lists::ideals_with_norm(n, both): ideals_with_norm(n, both));
// cout<<" Qidealooper inserting "<<Ilist.size()<<" ideals of norm "<<n<<" into queue: "<<Ilist<<endl;
I_norm_n.insert(I_norm_n.end(), Ilist.begin(), Ilist.end());
advance();
}
Qideal Qidealooper::next() // must only call when not not_finished
{
Qideal I = I_norm_n.front();
I_norm_n.pop_front();
advance();
return I;
}
void Qidealooper::advance()
{
if (! I_norm_n.empty()) return;
while (I_norm_n.empty() && n<maxn)
{
n+=1;
vector<Qideal> Ilist = (sort? Qideal_lists::ideals_with_norm(n, both): ideals_with_norm(n, both));
// cout<<" Qidealooper inserting "<<Ilist.size()<<" ideals of norm "<<n<<" into queue: "<<Ilist<<endl;
I_norm_n.insert(I_norm_n.end(), Ilist.begin(), Ilist.end());
}
// now either n>maxn and I_norm_n is empty, or n<=maxn and it is
// not. In the first case, not_finished() will be false
}
vector<Qideal> Quad::class_group; // list of ideals representing ideal classes (no structure)
vector<Qideal> Quad::class_group_2_torsion; // list of ideals representing 2-torsion in class group
vector<Qideal> Quad::class_group_2_torsion_gens; // list of ideals generating 2-torsion in class group
vector<Qideal> Quad::class_group_2_cotorsion; // list of ideals representing class group mod squares
vector<Qideal> Quad::class_group_2_cotorsion_gens; // list of ideals generating class group mod squares
void Quad::fill_class_group()
{
// NB class_number may already be set correctly (if <=5 currently); if not, it will have been set to 0
class_group.clear();
class_group_2_torsion.clear();
class_group_2_cotorsion.clear();
class_group_2_torsion_gens.clear();
class_group_2_cotorsion_gens.clear();
class_group.push_back(Qideal());
class_group_2_torsion.push_back(Qideal());
class_group_2_cotorsion.push_back(Qideal());
if(class_number==1)
{
class_group_2_rank = 0;
return;
}
long MB = floor(2*sqrt(I2long(absdisc))/PI); // Minkowski bound
Qidealooper loop(1, MB, 1, 1);
while( loop.not_finished() )
{
Qideal I = loop.next();
if (I.is_principal())
continue;
if (find_ideal_class(I, class_group) == -1)
{
// cout << I << " is in a new ideal class (#" << class_group.size() << ")" << endl;
class_group.push_back(I);
Qideal I2 = I*I;
// cout << " -- the square is " << I2 << endl;
if (I2.is_principal())
{
// cout << " -- this class is 2-torsion" <<endl;
// I is 2-torsion
if (find_ideal_class(I, class_group_2_torsion)==-1)
{
// add a new 2-torsion generator
class_group_2_torsion_gens.push_back(I);
// compute the new coset: copy the subgroup:
auto coset = class_group_2_torsion;
// multiply its elements by I:
std::for_each(coset.begin(), coset.end(), [I] ( Qideal& J ) { J*=I;});
// append the new coset to the subgroup:
class_group_2_torsion.insert(class_group_2_torsion.end(), coset.begin(), coset.end());
}
}
else
{ // I has order>2, and we keep its conjugate (in the inverse class) too
// cout << " -- this class has order > 2" <<endl;
class_group.push_back(I.conj());
}
}
if (class_group.size()==(unsigned)class_number)
break;
}
if (class_number==0) // then it wasn't preset
{
class_number = class_group.size();
}
// cout << "Class number = " << class_number << " with representatives " << class_group << endl;
// replace the 2-torsion class representatives with the equivalent
// ideals in the main class_group list
std::for_each(class_group_2_torsion.begin(), class_group_2_torsion.end(),
[] (Qideal& J) { J = class_group[find_ideal_class(J, class_group)];});
class_group_2_rank = class_group_2_torsion_gens.size();
// find ideals generating and representing Cl/Cl^2
for ( auto& I : class_group)
{
if (!I.has_square_class()) // then I is not a square
{
if (find_ideal_class_mod_squares(I, class_group_2_cotorsion)==-1)
{
// add a new 2-cotorsion generator
class_group_2_cotorsion_gens.push_back(I);
// compute the new coset; first copy old subgroup:
auto coset = class_group_2_cotorsion;
// multiply each element by I:
std::for_each(coset.begin(), coset.end(), [I] ( Qideal& J )
{ J = class_group[find_ideal_class(I*J, class_group)];});
// append the new coset to the subgroup:
class_group_2_cotorsion.insert(class_group_2_cotorsion.end(), coset.begin(), coset.end());
}
}
}
}
// END OF FILE QIDLOOP.CC