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