1 // -*- C++ -*-
2 //==============================================================================================
3 //
4 // This file is part of LiDIA --- a library for computational number theory
5 //
6 // Copyright (c) 1994--2002 the LiDIA Group. All rights reserved.
7 //
8 // See http://www.informatik.tu-darmstadt.de/TI/LiDIA/
9 //
10 //----------------------------------------------------------------------------------------------
11 //
12 //
13 // File : gec_complex_multiplication.cc
14 // Author : Harald Baier (HB)
15 // Changes : See CVS log
16 //
17 //==============================================================================================
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 # include "LiDIA/gec_complex_multiplication.h"
23 #ifdef VERBOSE
24 # include <cassert>
25 #endif
26
27
28 #ifdef LIDIA_NAMESPACE
29 namespace LiDIA {
30 #endif
31
32
33 //
34 // Initialize static variables
35 //
36
37 // default discriminant (fundamental of class number 200), if no delta
38 // is set by the user
39 const bigint gec_complex_multiplication::default_delta = -21311;
40 const bigint gec_complex_multiplication::default_delta_4 = -21311;
41 const bigint gec_complex_multiplication::default_delta_1 = -125579;
42 const bigint gec_complex_multiplication::default_delta_2 = -53444;
43 // as default_delta is odd, the corresponding case is set to 1
44 const short gec_complex_multiplication::default_delta_case = 1;
45 // the default number of subintervals is 2^40
46 const long gec_complex_multiplication::bitlength_no_of_intervals = 40;
47 // the precision for computation of Weber polynomials is alpha * L (see PhD)
48 const bigfloat gec_complex_multiplication::alpha = 0.015;
49 // the default lower bound of the class number is 200:
50 // in case of Fixed Field Approach or OEF, this is the default value
51 // for the lower bound of the class number
52 const long gec_complex_multiplication::default_lower_bound_class_number = 200;
53 // the default upper bound of the class number is 1000:
54 // in case of Fixed Field Approach or OEF, this is the default value
55 // for the upper bound of the class number
56 const long gec_complex_multiplication::default_upper_bound_class_number = 1000;
57
58 // some constant static variables for the OEF case
59 const lidia_size_t gec_complex_multiplication::default_word_length = 32;
60 const lidia_size_t gec_complex_multiplication::default_degree_oef = 5;
61
62
63 //
64 // Constructor / Destructor
65 //
66 gec_complex_multiplication::
gec_complex_multiplication()67 gec_complex_multiplication() :
68 gec()
69 {
70 CM_FLAG = true;
71
72 class_polynomial.assign_zero();
73 complex_precision = 0;
74 degree = 1;
75 generation_mode = 0;
76
77 lower_bound_class_number = upper_bound_class_number = 0;
78 word_length = 0;
79
80 is_initialized = false;
81 is_polynomial_set = false;
82 efficient_curve_parameters = false;
83 }
84
85 gec_complex_multiplication::
gec_complex_multiplication(const bigint & Delta)86 gec_complex_multiplication( const bigint & Delta ) :
87 gec()
88 {
89 CM_FLAG = true;
90
91 delta.assign( Delta );
92 class_polynomial.assign_zero();
93 complex_precision = 0;
94 degree = 1;
95 generation_mode = 0;
96
97 lower_bound_class_number = upper_bound_class_number = 0;
98 word_length = 0;
99
100 is_initialized = false;
101 is_polynomial_set = false;
102 efficient_curve_parameters = false;
103 }
104
105
106 gec_complex_multiplication::
gec_complex_multiplication(lidia_size_t d)107 gec_complex_multiplication( lidia_size_t d ) :
108 gec()
109 {
110 CM_FLAG = true;
111
112 class_polynomial.assign_zero();
113 complex_precision = 0;
114 degree = d;
115 generation_mode = 0;
116
117 lower_bound_class_number = upper_bound_class_number = 0;
118 word_length = 0;
119
120 is_initialized = false;
121 is_polynomial_set = false;
122 efficient_curve_parameters = false;
123
124 lower_bound_class_number = default_lower_bound_class_number;
125 }
126
127 gec_complex_multiplication::
gec_complex_multiplication(std::ostream & out)128 gec_complex_multiplication( std::ostream & out ) : gec( out )
129 {
130 CM_FLAG = true;
131
132 class_polynomial.assign_zero();
133 complex_precision = 0;
134 degree = 1;
135 generation_mode = 0;
136
137 lower_bound_class_number = upper_bound_class_number = 0;
138 word_length = 0;
139
140 is_initialized = false;
141 is_polynomial_set = false;
142 efficient_curve_parameters = false;
143 }
144
145
146 gec_complex_multiplication::
~gec_complex_multiplication()147 ~gec_complex_multiplication()
148 {
149 }
150
151 //
152 // Accessors
153 //
154 unsigned int
get_generation_mode() const155 gec_complex_multiplication::get_generation_mode() const
156 {
157 return( generation_mode );
158 }
159
160 const bigint &
get_delta() const161 gec_complex_multiplication::get_delta() const
162 {
163 return( delta );
164 }
165
166 long
get_complex_precision() const167 gec_complex_multiplication::get_complex_precision() const
168 {
169 return( complex_precision );
170 }
171
172 polynomial < bigint >
get_class_polynomial() const173 gec_complex_multiplication::get_class_polynomial() const
174 {
175 return( class_polynomial );
176 }
177
178 //
179 // Mutators
180 //
181
182 // Mutator for generation_mode: see file set_generation_mode.cc
183
184 // Mutator for discriminant of End(E)
185 void
set_delta(const bigint & d)186 gec_complex_multiplication::set_delta( const bigint & d )
187 {
188 if( d.is_ge_zero() )
189 lidia_error_handler("gec_complex_multiplication", "set_delta( const bigint & delta): delta is non negative");
190
191 abs_delta.assign( d );
192 abs_delta.negate();
193
194 if( ( abs_delta.bit(0) == 0 && abs_delta.bit(1) == 0 ) )
195 {
196 delta_case = 0;
197 delta = d;
198 }
199 else if( ( abs_delta.bit(0) == 1 && abs_delta.bit(1) == 1 ) )
200 {
201 delta_case = 1;
202 delta = d;
203 }
204 else
205 lidia_error_handler("gec_complex_multiplication", "set_delta( const bigint & delta): delta is not = 0,1 mod 4");
206 }
207
208 // Mutator for complex_precision: see file set_complex_precision.cc
209
210
211 // Mutator for lower_bound_class_number
212 void
set_lower_bound_class_number(const long lower_bound)213 gec_complex_multiplication::set_lower_bound_class_number(
214 const long lower_bound )
215 {
216 if( lower_bound < default_lower_bound_class_number ||
217 lower_bound > default_upper_bound_class_number )
218 lidia_error_handler("gec_complex_multiplication", "set_lower_bound_class_number( const long h_): h_ is not in the correct interval. Check the default values.");
219 else if( upper_bound_class_number != 0 &&
220 upper_bound_class_number <= lower_bound )
221 lidia_error_handler("gec_complex_multiplication", "set_lower_bound_class_number( const long h_): h_ has to be smaller than upper_bound_class_number.");
222
223 lower_bound_class_number = lower_bound;
224 }
225
226 // Mutator for upper_bound_class_number
227 void
set_upper_bound_class_number(const long upper_bound)228 gec_complex_multiplication::set_upper_bound_class_number(
229 const long upper_bound )
230 {
231 if( upper_bound < default_lower_bound_class_number ||
232 upper_bound > default_upper_bound_class_number )
233 lidia_error_handler("gec_complex_multiplication", "set_upper_bound_class_number( const long h_): h_ is not in the correct interval. Check the default values.");
234 else if( lower_bound_class_number >= upper_bound )
235 lidia_error_handler("gec_complex_multiplication", "set_upper_bound_class_number( const long h_): h_ has to be larger than lower_bound_class_number.");
236
237 upper_bound_class_number = upper_bound;
238 }
239
240
241 // Mutator for class_polynomial: The user responsible for the right choice.
242 void
set_class_polynomial(const polynomial<bigint> & class_pol)243 gec_complex_multiplication::set_class_polynomial(
244 const polynomial < bigint > & class_pol )
245 {
246 class_polynomial.assign( class_pol );
247 is_polynomial_set = true;
248 }
249
250 // Mutator for class_polynomial: The user responsible for the right choice.
251 // In addition, the function requires the coefficients to be stored
252 // in the file <file_directory>/h_/delta_ starting with the
253 // coefficient of X^h_ = 1 in descending order.
254 void
set_class_polynomial(const bigint & delta_,const lidia_size_t h_,char * file_directory)255 gec_complex_multiplication::set_class_polynomial(
256 const bigint & delta_, const lidia_size_t h_, char * file_directory )
257 {
258 delta.assign( delta_ );
259 class_polynomial.set_degree( h_ );
260
261 char input_file[ 200 ], delta_as_string[ 100 ];
262 strcpy( input_file, file_directory );
263 strcat( input_file, "/" );
264 bigint_to_string( delta_, delta_as_string );
265 strcat( input_file, delta_as_string );
266
267 std::ifstream in( input_file );
268
269 for( lidia_size_t kk = h_; kk >= 0; kk-- )
270 in >> class_polynomial[ kk ];
271
272 is_polynomial_set = true;
273 }
274
275 //
276 // Assignment by other instance of this class
277 //
278 void
assign(const gec_complex_multiplication & I)279 gec_complex_multiplication::assign( const gec_complex_multiplication & I )
280 {
281 if( this != &I )
282 {
283 is_initialized = I.is_initialized;
284
285 if( is_initialized )
286 {
287 q = I.q;
288 F_q = I.F_q;
289 r = I.r;
290 k = I.k;
291 G = I.G;
292
293 lower_bound_bitlength_r = I.lower_bound_bitlength_r;
294 upper_bound_k = I.upper_bound_k;
295
296 a2 = I.a2;
297 a4 = I.a4;
298 a6 = I.a6;
299
300 according_to_BSI = I.according_to_BSI;
301 delta_field = I.delta_field;
302 lower_bound_h_field = I.lower_bound_h_field;
303 }
304 }
305 }
306
307
308 #ifdef LIDIA_NAMESPACE
309 } // end of namespace LiDIA
310 # undef IN_NAMESPACE_LIDIA
311 #endif
312