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