1 //==============================================================================================
2 //
3 //	This file is part of LiDIA --- a library for computational number theory
4 //
5 //	Copyright (c) 1994--2001 the LiDIA Group.  All rights reserved.
6 //
7 //	See http://www.informatik.tu-darmstadt.de/TI/LiDIA/
8 //
9 //----------------------------------------------------------------------------------------------
10 //
11 //	$Id$
12 //
13 //	Author	: Victor Shoup (VS), Thomas Pfahler (TPf)
14 //	Changes	: See CVS log
15 //
16 //==============================================================================================
17 
18 
19 #ifdef HAVE_CONFIG_H
20 # include	"config.h"
21 #endif
22 #include	"LiDIA/Fp_polynomial.h"
23 #include	"LiDIA/finite_fields/Fp_polynomial_util.h"
24 #include	"LiDIA/Fp_poly_modulus.h"
25 #include	"LiDIA/lidia_signal.h"
26 #include	"LiDIA/lidia_file.h"
27 #include	"LiDIA/single_factor.h"
28 #include	"LiDIA/factorization.h"
29 
30 #include	<fstream>
31 #include	<cstdio>
32 #include	<unistd.h>
33 
34 
35 
36 #ifdef LIDIA_NAMESPACE
37 namespace LiDIA {
38 #endif
39 
40 
41 
42 int DDF_GCD_BLOCKING_FACTOR = 4;
43 
44 #define BABY 0
45 #define GIANT 1
46 
47 
48 //
49 // Temporary files will be located in the current directory or in /tmp
50 // and will have the following names:
51 // 	ddf1234b.001		(baby steps)
52 //	ddf1234b.002
53 //	...
54 //	ddf1234g.001		(giant steps)
55 //	ddf1234g.002
56 //	...
57 // where 1234 is the pid of the current process (modulo 10^5).
58 //
59 
60 
61 //
62 // Task:        tries to create the file "ddf....b.001", where "...." is
63 //		replaced by the pid of the current process (mod 10^5),
64 //		 a) in the current directory
65 //		 b) if that fails, in the directory /tmp
66 //		an error will occur, if the directories are not writeable or
67 //		 if a file with the same name already exists in both dirs.
68 //		finally, stem="[successful dir]/ddf[pid]"
69 //
70 // Conditions:	enough space for stem must be allocated
71 //
72 
73 static
check_stem(char * stem)74 void check_stem(char* stem)
75 {
76 	memory_handler(tmp, "Fp_polynomial",
77 		       "create_stem(void)::Error in memory allocation");
78 
79 	int num = static_cast<int>(getpid()) % 10000; // 4 digits are enough
80 	bool ok = false;
81 
82 	sprintf(stem, "./ddf%db.001", num); // try current directory...
83 
84 	// <MM>
85 	// Replaced by use of lidia_file,
86 	// s.is_open() is not portable
87 	//
88 	//s.open(stem, std::ios::out|std::ios::noreplace); // test if pid is already used
89 	//if (s.is_open()) {	// PT
90 	//	sprintf(stem, "./ddf%d", num);
91 	//	ok = true; // file was successfully created
92 	//}
93 	//s.close();
94 
95 	if (!lidia_file::file_exists(stem)) {
96 		sprintf(stem, "./ddf%d", num);
97 		ok = true; // filename was successfully created
98 	}
99 	// </MM>
100 
101 
102 	if (!ok) {
103 		// try "/tmp"-directory...
104 		sprintf(stem, "/tmp/ddf%db.001", num);
105 
106 		//<MM>
107 		//
108 		//s.open(stem, std::ios::out|std::ios::noreplace);
109 		//if (s.is_open()) {	// PT
110 		//	sprintf(stem, "/tmp/ddf%d", num);
111 		//	ok = true;
112 		//}
113 		//s.close();
114 
115 		if (!lidia_file::file_exists(stem)) {
116 			sprintf(stem, "./ddf%d", num);
117 			ok = true; // filename was successfully created
118 		}
119 		//</MM>
120 	}
121 
122 	if (!ok)
123 		lidia_error_handler("Fp_polynomial", "create_stem(...)::cannot write "
124 				    "temporary files into current nor into /tmp-directory");
125 }
126 
127 
128 
129 //
130 // Task:	returns the string "[stem][ext].[d]", where d is filled up
131 //		with zeros if necessary to get a 3-digit number
132 //
133 // Conditions:	the whole string must have less than 32 characters
134 //
135 
136 static
create_file_name(const char * stem,int ext,lidia_size_t d)137 char * create_file_name(const char *stem, int ext, lidia_size_t d)
138 {
139 	debug_handler("Fp_polynomial", "create_file_name (char*, char*, lidia_size_t)");
140 
141 	static char sbuf[32];
142 
143 	strcpy(sbuf, stem);
144 	switch(ext) {
145 	case(BABY):  strcat(sbuf, "b.");
146 		break;
147 	case(GIANT): strcat(sbuf, "g.");
148 		break;
149 	default: lidia_error_handler("Fp_polynomial", "create_file_name(...)"
150 				     "::wrong ext");
151 	}
152 
153 	char dbuf[4];
154 	dbuf[3] = '\0';
155 	lidia_size_t i, dd;
156 	dd = d;
157 
158 	for (i = 2; i >= 0; i--) {
159 		dbuf[i] = static_cast<char>((dd % 10) + '0');
160 		dd = dd / 10;
161 	}
162 
163 	strcat(sbuf, dbuf);
164 	return sbuf;
165 }
166 
167 
168 
169 //
170 // Task:	delete all temporary files
171 //
172 
173 static
file_cleanup(lidia_size_t k,lidia_size_t l,const char * new_ddf_stem)174 void file_cleanup(lidia_size_t k, lidia_size_t l, const char *new_ddf_stem)
175 {
176 	debug_handler("Fp_polynomial", "file_cleanup(lidia_size_t, lidia_size_t, char*)");
177 	lidia_size_t i;
178 
179 	for (i = 1; i <= k; i++)
180 		std::remove(create_file_name(new_ddf_stem, BABY, i));
181 
182 	for (i = 1; i <= l; i++)
183 		std::remove(create_file_name(new_ddf_stem, GIANT, i));
184 }
185 
186 
187 
188 
189 //
190 // Task :	remove all temporary files in case of an interruption
191 //
192 
LIDIA_SIGNAL_FUNCTION(tidy_up)193 LIDIA_SIGNAL_FUNCTION(tidy_up)
194 {
195 	int num = static_cast<int>(getpid()) % 10000;
196 	char stem[32];
197 
198 	// delete all temporary files (if any) in directory "./"
199 	sprintf(stem, "./ddf%d", num);
200 	int i = 1;
201 	while (! std::remove(create_file_name(stem, BABY, i)))
202 		i++;
203 	i = 1;
204 	while (! std::remove(create_file_name(stem, GIANT, i)))
205 		i++;
206 
207 	// delete all temporary files (if any) in directory "/tmp/"
208 	sprintf(stem, "/tmp/ddf%d", num);
209 	i = 1;
210 	while (! std::remove(create_file_name(stem, BABY, i)))
211 		i++;
212 	i = 1;
213 	while (! std::remove(create_file_name(stem, GIANT, i)))
214 		i++;
215 
216 	lidia_error_handler("Fp_polynomial", "ddf : the program has been "
217 			    "interrupted");
218 }
219 
220 
221 
222 //
223 // Task:	reads giant step #gs into g
224 //
225 
226 static
fetch_giant_step(Fp_polynomial & g,lidia_size_t gs,const Fp_poly_modulus & F,const char * new_ddf_stem)227 void fetch_giant_step(Fp_polynomial & g, lidia_size_t gs,
228 		      const Fp_poly_modulus & F, const char *new_ddf_stem)
229 {
230 	debug_handler("Fp_polynomial", "fetch_giant_step(Fp_polynomial&, lidia_size_t, Fp_poly_modulus&, char*)");
231 
232 	std::ifstream s;
233 
234 	s.open(create_file_name(new_ddf_stem, GIANT, gs), std::ios::in);
235 	if (!s) {
236 		lidia_error_handler_c("Fp_polynomial",
237 				      "fetch_giant_step(...)::open read error",
238 				      std::cout << "open read error: " << create_file_name(new_ddf_stem,
239 											   GIANT, gs) << "\n";);
240 		return; // LC
241 	}
242 
243 	s >> g;
244 	s.close();
245 	remainder(g, g, F);
246 }
247 
248 
249 
250 //
251 // Task:	reads baby steps #1 to #k into v
252 //
253 
254 static
fetch_baby_steps(base_vector<Fp_polynomial> & v,lidia_size_t k,const char * new_ddf_stem,const bigint & p)255 void fetch_baby_steps(base_vector< Fp_polynomial > &v, lidia_size_t k,
256 		      const char *new_ddf_stem, const bigint & p)
257 {
258 	debug_handler("Fp_polynomial", "fetch_baby_steps(base_vector< Fp_polynomial > &, lidia_size_t, char*, bigint&)");
259 
260 	std::ifstream s;
261 
262 	if (v.capacity() < k)
263 		v.set_capacity(k);
264 	v.set_size(k);
265 
266 
267 	lidia_size_t i;
268 	for (i = 1; i <= k - 1; i++) {
269 		s.open(create_file_name(new_ddf_stem, BABY, i), std::ios::in);
270 		if (!s) {
271 			lidia_error_handler_c("Fp_polynomial",
272 					      "fetch_baby_steps(...):::open read error",
273 					      std::cout << "open read error: "
274 					      << create_file_name(new_ddf_stem, BABY, i) << "\n";);
275 			return; // LC
276 		}
277 
278 		s >> v[i];
279 		s.close();
280 	}
281 
282 	v[0].set_modulus(p);
283 	v[0].assign_x();
284 }
285 
286 
287 
288 //
289 // Task:	writes baby steps to disk
290 //
291 
292 static
generate_baby_steps(Fp_polynomial & h1,const Fp_polynomial & f,const Fp_polynomial & h,lidia_size_t k,const char * new_ddf_stem)293 void generate_baby_steps(Fp_polynomial & h1, const Fp_polynomial & f,
294 			 const Fp_polynomial & h, lidia_size_t k, const char *new_ddf_stem)
295 {
296 	debug_handler("Fp_polynomial", "generate_baby_steps(Fp_polynomial&, Fp_polynomial&, Fp_polynomial&, lidia_size_t, char*)");
297 
298 	f.comp_modulus(h, "generate_baby_steps");
299 
300 	my_timer t;
301 	std::ofstream s;
302 	bool verbose = single_factor< Fp_polynomial >::verbose();
303 
304 	if (verbose) t.start("generating baby steps...");
305 
306 	Fp_poly_modulus F(f);
307 
308 	poly_argument H;
309 	H.build(h, F, 2 * square_root(f.degree()));
310 
311 
312 	h1.assign(h);
313 
314 	lidia_size_t i;
315 
316 	for (i = 1; i <= k - 1; i++) {
317 		s.open(create_file_name(new_ddf_stem, BABY, i), std::ios::out);
318 		if (!s) {
319 			lidia_error_handler_c("Fp_polynomial",
320 					      "generate_baby_steps(...)::open write error",
321 					      std::cout << "open write error: "
322 					      << create_file_name(new_ddf_stem, BABY, i) << "\n";);
323 			return; // LC
324 		}
325 
326 		s << h1 << "\n";
327 		s.close();
328 
329 		H.compose(h1, h1, F);
330 		if (verbose) std::cerr << "+";
331 	}
332 
333 	if (verbose) t.stop();
334 }
335 
336 
337 //
338 // Task:	writes giant steps to disk
339 //
340 
341 static
generate_giant_steps(const Fp_polynomial & f,const Fp_polynomial & h,lidia_size_t l,const char * new_ddf_stem)342 void generate_giant_steps(const Fp_polynomial & f, const Fp_polynomial & h,
343 			  lidia_size_t l, const char *new_ddf_stem)
344 {
345 	debug_handler("Fp_polynomial", "generate_giant_steps(Fp_polynomial&, Fp_polynomial&, lidia_size_t, char*)");
346 
347 	f.comp_modulus(h, "generate_giant_steps");
348 
349 	my_timer t;
350 	std::ofstream s;
351 	bool verbose = single_factor< Fp_polynomial >::verbose();
352 
353 	if (verbose) t.start("generating giant steps...");
354 
355 	Fp_poly_modulus F(f);
356 
357 	poly_argument H;
358 	H.build(h, F, 2 * square_root(f.degree()));
359 
360 	Fp_polynomial h1;
361 
362 	h1.assign(h);
363 
364 	lidia_size_t i;
365 
366 	for (i = 1; i <= l; i++) {
367 		s.open(create_file_name(new_ddf_stem, GIANT, i), std::ios::out);
368 		if (!s) {
369 			lidia_error_handler_c("Fp_polynomial",
370 					      "generate_giant_steps(...)::open write error",
371 					      std::cout << "open write error: "
372 					      << create_file_name(new_ddf_stem, GIANT, i) << "\n";);
373 			return; // LC
374 		}
375 
376 		s << h1 << "\n";
377 		s.close();
378 
379 		if (i != l)
380 			H.compose(h1, h1, F);
381 
382 		if (verbose) std::cerr << "+";
383 	}
384 
385 	if (verbose) t.stop();
386 }
387 
388 
389 
390 //
391 // Task:	appends g, a product of irreducible polynomials of degree m,
392 //		to u
393 //		(the exponents of u are the degrees of the irreducible
394 //		polynomials !)
395 //
396 
397 static
new_add_factor(factorization<Fp_polynomial> & u,const Fp_polynomial & g,lidia_size_t m)398 void new_add_factor(factorization< Fp_polynomial > &u,
399 		    const Fp_polynomial & g, lidia_size_t m)
400 {
401 	debug_handler("Fp_polynomial", "new_add_factor(factorization< Fp_polynomial > &, Fp_polynomial&, lidia_size_t)");
402 
403 	u.append(g, m);
404 
405 	if (single_factor< Fp_polynomial >::verbose())
406 		std::cerr << "split " << m << " " << g.degree() << std::endl;
407 }
408 
409 
410 
411 //
412 // Task:	splits f by computing gcd(f, buf[i])
413 //
414 // Algorithm:	instead of computing gcd(f,buf[i]) for all i, we compute
415 //		g = product of all buf[i]. If gcd(f,g) = 1, we do not have to
416 //		compute any further gcd and can return immediately
417 //
418 
419 static
new_process_table(factorization<Fp_polynomial> & u,Fp_polynomial & f,const Fp_poly_modulus & F,base_vector<Fp_polynomial> & buf,lidia_size_t size,lidia_size_t StartInterval,lidia_size_t IntervalLength)420 void new_process_table(factorization< Fp_polynomial > &u, Fp_polynomial & f,
421 		       const Fp_poly_modulus & F, base_vector< Fp_polynomial > &buf,
422 		       lidia_size_t size, lidia_size_t StartInterval,
423 		       lidia_size_t IntervalLength)
424 {
425 	debug_handler("Fp_polynomial", "new_process_table(factorization< Fp_polynomial > &, Fp_polynomial&, Fp_poly_modulus&, base_vector< Fp_polynomial > &, lidia_size_t, lidia_size_t, lidia_size_t)");
426 
427 	if (size == 0)
428 		return;
429 
430 	Fp_polynomial & g = buf[size - 1];
431 
432 	lidia_size_t i;
433 
434 	for (i = 0; i < size - 1; i++)
435 		multiply(g, g, buf[i], F);
436 
437 	gcd(g, f, g);
438 	if (g.degree() == 0)
439 		return;
440 
441 	divide(f, f, g);
442 
443 	lidia_size_t d = (StartInterval - 1) * IntervalLength + 1;
444 	i = 0;
445 	lidia_size_t interval = StartInterval;
446 
447 	//next, we 'refine' our gcd computations
448 	while (i < size - 1 && 2 * d <= g.degree()) {
449 		gcd(buf[i], buf[i], g);
450 		if (buf[i].degree() > 0) {
451 			new_add_factor(u, buf[i], interval);
452 			divide(g, g, buf[i]);
453 		}
454 		i++;
455 		interval++;
456 		d += IntervalLength;
457 	}
458 
459 	if (g.degree() > 0) {
460 		if (i == size - 1)
461 			new_add_factor(u, g, interval);
462 		else
463 			new_add_factor(u, g, (g.degree()+IntervalLength-1)/IntervalLength);
464 	}
465 }
466 
467 
468 
469 static
giant_refine(factorization<Fp_polynomial> & u,const Fp_polynomial & ff,lidia_size_t k,const char * new_ddf_stem)470 void giant_refine(factorization< Fp_polynomial > &u, const Fp_polynomial & ff,
471 		  lidia_size_t k, const char *new_ddf_stem)
472 {
473 	debug_handler("Fp_polynomial", "giant_refine(factorization< Fp_polynomial > &, Fp_polynomial&, lidia_size_t, char*)");
474 
475 	my_timer t;
476 	bool verbose = single_factor< Fp_polynomial >::verbose();
477 
478 	if (verbose) {
479 		std::cerr << "giant refine...\n";
480 		t.start("giant refine time: ");
481 	}
482 
483 	u.kill();
484 
485 	base_vector< Fp_polynomial > BabyStep;
486 
487 	fetch_baby_steps(BabyStep, k, new_ddf_stem, ff.modulus());
488 
489 	base_vector< Fp_polynomial >
490 		buf(static_cast<lidia_size_t>(DDF_GCD_BLOCKING_FACTOR),
491 		    static_cast<lidia_size_t>(DDF_GCD_BLOCKING_FACTOR));
492 
493 	Fp_polynomial f;
494 	f.assign(ff);
495 
496 	Fp_poly_modulus F;
497 	F.build(f);
498 
499 	Fp_polynomial g;
500 	Fp_polynomial h;
501 
502 	lidia_size_t size = 0;
503 	lidia_size_t first_gs = 0; //initialized only because of compiler warnings
504 
505 	lidia_size_t d = 1;
506 
507 	while (2 * d <= f.degree()) {
508 
509 		lidia_size_t old_n = f.degree();
510 
511 		lidia_size_t gs = (d + k - 1) / k;
512 		lidia_size_t bs = gs * k - d;
513 
514 		if (bs == k - 1) {
515 			size++;
516 			if (size == 1)
517 				first_gs = gs;
518 			fetch_giant_step(g, gs, F, new_ddf_stem);
519 			subtract(buf[size - 1], g, BabyStep[bs]);
520 		}
521 		else {
522 			subtract(h, g, BabyStep[bs]);
523 			multiply(buf[size - 1], buf[size - 1], h, F); //Fp_poly_modulus
524 
525 		}
526 
527 		if (verbose && bs == 0)
528 			std::cerr << "+";
529 
530 		if (size == DDF_GCD_BLOCKING_FACTOR && bs == 0) {
531 			new_process_table(u, f, F, buf, size, first_gs, k);
532 			if (verbose) std::cerr << "*";
533 			size = 0;
534 		}
535 
536 		d++;
537 
538 		if (2 * d <= f.degree() && f.degree() < old_n) {
539 			F.build(f);
540 
541 			lidia_size_t i;
542 			for (i = 1; i <= k - 1; i++)
543 				remainder(BabyStep[i], BabyStep[i], F);
544 		}
545 	}
546 
547 	if (size > 0) {
548 		new_process_table(u, f, F, buf, size, first_gs, k);
549 		if (verbose) std::cerr << "*";
550 	}
551 
552 	if (f.degree() > 0)
553 		new_add_factor(u, f, -1);
554 
555 	if (verbose) t.stop();
556 }
557 
558 
559 
560 static
interval_refine(factorization<Fp_polynomial> & factors,const Fp_polynomial & ff,lidia_size_t k,lidia_size_t gs,const base_vector<Fp_polynomial> & BabyStep,const char * new_ddf_stem)561 void interval_refine(factorization< Fp_polynomial > &factors,
562 		     const Fp_polynomial &ff, lidia_size_t k, lidia_size_t gs,
563 		     const base_vector< Fp_polynomial > &BabyStep, const char *new_ddf_stem)
564 {
565 	debug_handler("Fp_polynomial", "interval_refine(factorization< Fp_polynomial > &, Fp_polynomial&, lidia_size_t, lidia_size_t, base_vector< Fp_polynomial > &, char*)");
566 
567 	if (BabyStep.size() != 0)
568 		ff.comp_modulus(BabyStep[0], "interval_refine");
569 
570 	base_vector< Fp_polynomial >
571 		buf(static_cast<lidia_size_t>(DDF_GCD_BLOCKING_FACTOR),
572 		    static_cast<lidia_size_t>(DDF_GCD_BLOCKING_FACTOR));
573 
574 	Fp_polynomial f(ff);
575 
576 	Fp_poly_modulus F;
577 	F.build(f);
578 
579 	Fp_polynomial g;
580 
581 	fetch_giant_step(g, gs, F, new_ddf_stem);
582 
583 	lidia_size_t size = 0;
584 
585 	lidia_size_t first_d = 0; //initialized only because of compiler warnings
586 
587 	lidia_size_t d = (gs - 1) * k + 1;
588 	lidia_size_t bs = k - 1;
589 
590 	while (2 * d <= f.degree()) {
591 		lidia_size_t old_n = f.degree();
592 
593 		if (size == 0)
594 			first_d = d;
595 		remainder(buf[size], BabyStep[bs], F);
596 		subtract(buf[size], buf[size], g);
597 		size++;
598 
599 		if (size == DDF_GCD_BLOCKING_FACTOR) {
600 			new_process_table(factors, f, F, buf, size, first_d, 1);
601 			size = 0;
602 		}
603 
604 		d++;
605 		bs--;
606 
607 		if (bs < 0) {
608 			//exit
609 			d = f.degree() + 1;
610 		}
611 
612 		if (2 * d <= f.degree() && f.degree() < old_n) {
613 			F.build(f);
614 			remainder(g, g, F);
615 		}
616 	}
617 
618 	new_process_table(factors, f, F, buf, size, first_d, 1);
619 
620 	if (f.degree() > 0)
621 		new_add_factor(factors, f, f.degree());
622 }
623 
624 
625 
626 static
baby_refine(factorization<Fp_polynomial> & factors,const factorization<Fp_polynomial> & u,lidia_size_t k,const char * new_ddf_stem)627 void baby_refine(factorization< Fp_polynomial > &factors,
628 		 const factorization< Fp_polynomial > &u,
629 		 lidia_size_t k, const char *new_ddf_stem)
630 {
631 	debug_handler("Fp_polynomial", "baby_refine(factorization< Fp_polynomial > &, factorization< Fp_polynomial > &, lidia_size_t, char*)");
632 
633 	my_timer t;
634 	bool verbose = single_factor< Fp_polynomial >::verbose();
635 
636 	if (verbose) {
637 		std::cerr << "baby refine...\n";
638 		t.start("baby refine time: ");
639 	}
640 
641 	factors.kill();
642 
643 	base_vector< Fp_polynomial > BabyStep;
644 
645 	lidia_size_t i;
646 
647 	for (i = 0; i < u.no_of_composite_components(); i++) {
648 		const Fp_polynomial & g = u.composite_base(i).base();
649 		lidia_size_t gs = u.composite_exponent(i);
650 
651 		if (gs == -1 || 2 * ((gs - 1) * k + 1) > g.degree())
652 			new_add_factor(factors, g, g.degree());
653 		else {
654 			if (BabyStep.size() == 0)
655 				fetch_baby_steps(BabyStep, k, new_ddf_stem,
656 						 u.composite_base(0).base().modulus());
657 			interval_refine(factors, g, k, gs, BabyStep, new_ddf_stem);
658 		}
659 	}
660 
661 	if (verbose) t.stop();
662 }
663 
664 
665 
666 //*************************************************************************
667 //
668 //			the main routine
669 //
670 //*************************************************************************
671 
672 //
673 // Literature:	V. Shoup
674 //		A New Polynomial Factorization Algorithm and its Implementation
675 //		Universitaet des Saarlandes, 1994
676 //		Shoup, J. Symbolic Comp. 20:363-397, 1995
677 //
678 // Task:        Performs the distinct degree factorization of f = F.modulus()
679 //		(i.e. splits f in products of irreducibles of the same
680 //		degree)
681 //		when finished, the exponents of 'factors' are the degrees of
682 //		the irreducible factors of 'f' !!!
683 //
684 // Conditions:  f is square-free, monic, deg(f) > 0 and f(0) != 0 (?).
685 //              h = x^p mod f
686 //
687 // Algorithm:   DDF (Shoup)
688 //		some intermediate results are written to disk, they are
689 //		deleted at the end of the routine
690 //		baby step/giant step approach
691 //
692 
693 void
ddf(factorization<Fp_polynomial> & factors,const Fp_polynomial & f,const Fp_polynomial & h)694 ddf(factorization< Fp_polynomial > &factors,
695     const Fp_polynomial & f, const Fp_polynomial & h)
696 {
697 	debug_handler("Fp_polynomial", "ddf(factorization< Fp_polynomial > &, Fp_polynomial&, Fp_polynomial&)");
698 
699 	f.comp_modulus(h, "ddf");
700 
701 	if (f.degree() <= 0) {
702 		lidia_error_handler("Fp_polynomial",
703 				    "ddf(...)::polynomial has degree <= 0");
704 		return; // LC
705 	}
706 
707 	if (f.degree() == 1) {
708 		single_factor< Fp_polynomial > tmp(f);
709 		factors.assign(tmp);
710 		return;
711 	}
712 
713 	char *new_ddf_stem = new char[32];
714 	memory_handler(new_ddf_stem, "Fp_polynomial",
715 		       "ddf::Error in memory allocation");
716 	check_stem(new_ddf_stem);
717 
718 	lidia_signal sig1 (SIGTERM, tidy_up);
719 	lidia_signal sig2 (SIGINT, tidy_up);
720 	//PT lidia_signal sig3 (SIGHUP, tidy_up);
721 
722 	lidia_size_t B = f.degree() / 2;
723 	lidia_size_t k = square_root(B);
724 	lidia_size_t l = (B + k - 1) / k;
725 
726 	Fp_polynomial h1;
727 	generate_baby_steps(h1, f, h, k, new_ddf_stem);
728 	generate_giant_steps(f, h1, l, new_ddf_stem);
729 
730 	factorization< Fp_polynomial > u;
731 	giant_refine(u, f, k, new_ddf_stem);
732 	baby_refine(factors, u, k, new_ddf_stem);
733 
734 	file_cleanup(k, l, new_ddf_stem);
735 	delete[] new_ddf_stem;
736 }
737 
738 
739 
740 //*************************************************************************
741 //
742 //			    "interface"
743 //
744 //*************************************************************************
745 
ddf(const Fp_polynomial & f)746 factorization< Fp_polynomial > ddf(const Fp_polynomial& f)
747 {
748 	debug_handler("Fp_polynomial", "ddf(Fp_polynomial&)");
749 
750 	factorization< Fp_polynomial > factors;
751 	Fp_poly_modulus F(f);
752 	Fp_polynomial b;
753 	power_x(b, f.modulus(), F);
754 	ddf(factors, f, b);
755 	return factors;
756 }
757 
758 
759 
ddf() const760 factorization< Fp_polynomial > single_factor< Fp_polynomial >::ddf() const
761 {
762 	debug_handler("single_factor< Fp_polynomial >", "ddf()");
763 	return LiDIA::ddf(rep);
764 }
765 
766 
767 
768 #ifdef LIDIA_NAMESPACE
769 }	// end of namespace LiDIA
770 #endif
771