-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathPOLFACT.HTM
769 lines (768 loc) · 57.5 KB
/
POLFACT.HTM
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
<!doctype html>
<html lang="en" prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#">
<head>
<meta charset="utf-8">
<meta name="Author" content="Dario Alejandro Alpern">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Web application that factors and finds exact roots of integer polynomials and factors polynomials modulo a power of a prime number. Written by Dario Alpern.">
<meta name="theme-color" content="#db5945">
<meta name="twitter:card" content="summary_large_image">
<meta property="og:title" content="Polynomial factorization and roots calculator">
<meta property="og:type" content="article">
<meta property="og:site_name" content="Alpertron">
<meta property="og:url" content="https://www.alpertron.com.ar/POLFACT.HTM">
<meta property="og:image" content="https://www.alpertron.com.ar/polfact.png">
<meta property="og:image:width" content="1073">
<meta property="og:image:height" content="542">
<meta property="og:image:alt" content="Screenshot">
<meta property="og:locale" content="en_US">
<meta property="og:locale:alternate" content="es_ES">
<meta property="og:description" content="Works with integer and modulo p^n polynomials.">
<meta property="article:published_time" content="2025-01-01">
<meta property="fb:app_id" content="1495228927625175">
<link rel="alternate" hreflang="es" href="https://www.alpertron.com.ar/FACTPOL.HTM">
<link rel="alternate" hreflang="en" href="https://www.alpertron.com.ar/POLFACT.HTM">
<link rel="manifest" href="polfact.webmanifest">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="polfact-icon-180px.png">
<link rel="canonical" href="https://www.alpertron.com.ar/POLFACT.HTM">
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Q7PH40GPHC"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-Q7PH40GPHC');
</script>
<title>Polynomial factorization and roots calculator</title>
<style>
@media screen {
nav {background-color:#000080; width:100%; margin:0px; text-align:center}
nav ul {padding:0; margin:0 auto; list-style:none; display:inline-block}
nav li {float:left; position:relative; display:block; margin-top:0px; margin-bottom:0px; margin-left:5px; margin-right:5px; background-color:#000080; color:#FFFFFF; cursor: pointer; text-align:left}
nav li[aria-expanded="true"] {background-color:#004000; color:#FFFFFF}
nav li ul {display:none; position:absolute}
nav li[aria-expanded="true"] ul.alignleft {display:block; height:auto}
nav li[aria-expanded="true"] ul.alignright {display:block; height:auto; right:0px; background-color:#004000}
nav li ul li {clear:both; white-space: nowrap; border:0px; background-color:#004000; width:100%; padding-top:1em; padding-bottom:0.5em}
nav a:link{color:#FFFFFF; text-decoration:none}
nav a:visited{color:#FFFFFF; text-decoration:none}
nav a:hover{background-color:#004000; color:#FFFFFF; text-decoration:none}
nav a:active{background-color:#004000; color:#FFFFFF; text-decoration:none}
nav li ul li a:link{background-color:#004000; color:#FFFFFF; display:block; width:100%}
nav li ul li a:visited{background-color:#004000;color:#FFFFFF; display:block; width:100%}
nav li ul li a:hover{background-color:#FFFFFF; color:#004000; display:block; width:100%}
nav li ul li a:active{background-color:#FFFFFF; color:#004000; display:block; width:100%}
nav::after {clear:both}
.inputfbck{width: calc(100% - 10em);float:right;padding:3px;margin:0px;}
@media (max-width: 400px) { nav { font-size:0.7em; } }
@media (min-width: 400px) { nav { font-size:1em; } }
@media (min-width: 500px) {#formleft {float:left;width:50%;} #formright {float:right;width:50%;}}
}
@media print {nav, #footer {display:none}}
input[type=text], input[type=email], input[type=number] {min-height:2em; border-radius:10px}
#sending, #sentOK, #notSent {display:none}
.center {text-align:center}
#skip a {padding:6px; position:absolute; top:-40px; left:0px; color:white; border-right:1px solid white; border-bottom:1px solid white; border-bottom-right-radius:8px; background:#BF1722; transition:top 1s ease-out; z-index:100}
#skip a:focus {position:absolute; left:0px; top:0px; outline-color:transparent; transition: top .1s ease-in}
kbd {font-size:120%}
.bread {padding:0px;list-style:none; display:inline-block;}
.bread li {display:inline}
.bread li+li:before {content:"›"}
.new {color: #0000FF; font-weight:bold}
h2 > button {background-color:#eee; color:#444; cursor:pointer; padding:18px; font-weight:bold; font-size: 100%; width:100%; text-align:left; border:none; transition:0.4s}
h2 > button.active,h2 > button:hover {background-color:#ccc;}
h2 > button:after {content:"\002B"; color:#777; font-weight:bold; float:right; margin-left:5px;}
h2 > button.active:after {content:"\2212";}
.panel {padding: 0 10px; display:none; overflow:hidden;}
body {font-family: Arial, sans-serif; margin: 0; padding: 0;}
h1, .h2title {text-align:center}
fieldset {border-radius:10px;display:inline}
.lf,.labels {padding:0.2em; clear:both; width:100%}
.nolf {white-space: nowrap}
.atright {float:right}
.pad, #footer {padding:10px}
.applet {margin-left: auto;margin-right: auto; border: 0px none;width:90%;text-align:center;background-color:#c0c0c0;padding:10px;border-radius:10px}
.outerbox {display:table; color:blue}
.box {font-weight:bold; text-align:center; border-style:double; display:table-cell;border-radius:10px;}
.box > p {margin-left:5px;margin-right:5px;}
button {color: white; background-color: #3b3b3b; min-height:2.5em; min-width:2.5em; border-radius:5px}
#feedback {display:none}
#digits {width:5em}
#result > h3 {text-decoration:underline}
@media (min-width: 400px) {.input{width: calc(100% - 8em);float:right;padding:3px;margin:0px;}}
@media (max-width: 400px) {.input{width:100%;padding:3px;margin:0px;}}
#result ul {margin:0;padding:0px 20px 0px 20px;}
#valueapp {display:grid; row-gap:5px}
#polyinput {grid-column:1; grid-row:1}
#modinput {grid-column:1; grid-row:2}
#actbtn {grid-column:1; grid-row:3;display:flex; flex-flow:row wrap; justify-content:space-around; min-height:3em}
#lower {grid-column:1; grid-row:4}
sup::before {content:" raised to the power ";position:absolute;top:-9999px;left:-9999px}
.inputfbck{width: calc(100% - 10em);float:right;padding:3px;margin:0px}
.input{width: calc(100% - 8em);float:right;padding:3px;margin:0px}
r-t,r-2,.root2dig,.root3dig{display: inline-block; vertical-align:middle; border-top: 1px solid; border-left: 1px solid; transform: skew(-15deg); transform-origin: bottom left; position: relative;}
r-t,r-2 {margin:2px 10px}
.root2dig {margin:2px 10px 2px 18px}
.root3dig {margin:2px 10px 2px 26px}
e-q:before {content: "\00a0\00a0\00a0\00a0("}
e-q:after {content: ")"}
e-q,e-q:before,e-q:after {color: #800000; font-weight:bold}
r-t:before,r-2:before,.root2dig:before,.root3dig:before {content: ""; position:absolute; bottom:0; height:40%; width:5px; left:-5px; border-right:1px solid; transform:skew(30deg); transform-origin:bottom right;}
r-t:after,r-2:after,.root2dig:after,.root3dig:after {content: " end root ";position:absolute;top:-9999px;left:-9999px}
r-a,r-d,.radicand3,.radicand4,.radicand5{display: inline-block; padding-left:0.5em; transform:skew(15deg);}
r-a:before{content: " square root of "; position:absolute;top:-9999px;left:-9999px}
.radicand3,.radicand4,.radicand5 {top:-0.2em; left:-0.7em;}
.radicand3:before{content: " cubic root of "; position:absolute;top:-9999px;left:-9999px}
.radicand4:before{content: " fourth root of "; position:absolute;top:-9999px;left:-9999px}
.radicand5:before{content: " fifth root of "; position:absolute;top:-9999px;left:-9999px}
r-t>.befrad{position:absolute; font-size:80%; top:-0.2em; left: -1em; transform: skew(15deg);}
.root2dig>.befrad{position:absolute; font-size:80%; top:-0.2em; left: -1.5em; transform: skew(15deg);}
.root3dig>.befrad{position:absolute; font-size:80%; top:-0.2em; left: -2em; transform: skew(15deg);}
.befrad:after {content:" root of ";position:absolute;top:-9999px;left:-9999px}
f-f{display: inline-flex; flex-direction:column; padding:0.3em; align-items:center; vertical-align:middle;}
f-f:before {content:" start fraction ";position:absolute;top:-9999px;left:-9999px}
f-f:after {content:" end fraction ";position:absolute;top:-9999px;left:-9999px}
f-n {border-bottom: 2px solid grey; margin:-1px;}
f-d {border-top: 2px solid grey; margin:-1px;}
f-d:before {content:" over ";position:absolute;top:-9999px;left:-9999px}
p-p {padding-left:8px; padding-right:8px; position:relative; display:inline-block; margin-left:5px}
p-p:before {border-left:2px solid black; border-radius:50%; bottom:0; content:''; position:absolute; top:0; width:8px; left:-3px;}
p-p:after {border-right:2px solid black; border-radius:50%; bottom:0; content:''; position:absolute; top:0; width:8px; right:3px;}
o-t,o-p:before,o-p:after {position:absolute;top:-9999px;left:-9999px}
o-t {content:"times"}
o-p:before {content:" left parenthesis "}
o-p:after {content:" right parenthesis "}
@media screen and (prefers-color-scheme: dark) {
body {color: #ddd; background-color: #121212}
.applet {background-color:#606060; color: #fff}
p-p:before{border-left:2px solid #ddd}
p-p:after{border-right:2px solid #ddd}
h2 > button {background-color:#333; color:#eee}
h2 > button.active,h2 > button:hover {background-color:#555}
h2 > button:after {color:#777}
a {color: #a3d4a7}
a:link,a:active {color: #a3d4a7}
a:hover {color: #f5cba7}
a:visited {color: #d7bde2}
input, textarea, select {color: white; background-color: #3b3b3b}
button:disabled {color: #808080; background-color: #606060}
.new {color: #E0E000}
e-q,e-q:before,e-q:after,.outerbox {color:yellow}
}
</style>
<noscript>
<style>
.applet {display:none}
</style>
</noscript>
</head>
<body>
<div id="skip"><a href="#main">Skip to main content</a></div>
<nav aria-label="Main navigation">
<ul role="menubar">
<li role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="0">Electronics
<ul role="menu" class="alignleft popup">
<li role="menuitem"><a href="INTEL.HTM" hreflang="es" title="All Intel microprocessors from the 4004 up to Pentium (Spanish only)">Intel Microprocessors</a></li>
</ul>
</li>
<li role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="-1">Mathematics
<ul role="menu" class="alignleft popup">
<li role="menuitem"><a href="CALTORS.HTM" title="Web applications with JavaScript and WebAssembly implementing calculators">Calculators</a></li>
<li role="menuitem"><a href="NUMBERT.HTM" title="Articles and programs about number theory">Number Theory</a></li>
<li role="menuitem"><a href="PROBLEMS.HTM" title="Interesting math problems">Problems</a></li>
</ul>
</li>
<li role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="-1">Programs
<ul role="menu" class="alignright popup">
<li role="menuitem"><a href="ASSEM386.HTM" title="Programs written in 80386 Assembler">Assembler 80386</a></li>
<li role="menuitem"><a href="JAVAPROG.HTM" title="Web applications with JavaScript and WebAssembly">Web applications</a></li>
<li role="menuitem"><a href="GAMES.HTM" title="Computer games">Games</a></li>
</ul>
</li>
<li class="alignright" role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="-1">Contact
<ul role="menu" class="alignright popup">
<li role="menuitem"><a href="EPERS.HTM" title="Personal information">Personal</a></li>
<li role="menuitem"><a href="FORM.HTM" title="Form to send comments">Comments</a></li>
<li role="menuitem"><a href="EGBOOK.HTM" title="Old and new guestbook">Guestbook</a></li>
<li role="menuitem"><a href="PRIVACY.HTM" title="Privacy Policy">Privacy</a></li>
<li role="menuitem"><a href="DONATION.HTM" title="Donations to the author of this Web site">Donations</a></li>
</ul>
</li>
</ul>
<ul class="atright"><li><a href="FACTPOL.HTM" hreflang="es" title="Esta página Web en español">ESP</a></li></ul>
</nav>
<main id="main">
<article>
<h1>Polynomial factorization and roots calculator</h1>
<div class="pad">
<ol class="bread" vocab="https://schema.org/" typeof="BreadcrumbList">
<li property="itemListElement" typeof="ListItem">
<a property="item" typeof="WebPage" href="ENGLISH.HTM"><span property="name">Alpertron</span></a>
<meta property="position" content="1">
</li>
<li property="itemListElement" typeof="ListItem">
<a property="item" typeof="WebPage" href="JAVAPROG.HTM"><span property="name">Web applications</span></a>
<meta property="position" content="2">
</li>
<li property="itemListElement" typeof="ListItem">
<span property="name">Polynomial factorization calculator</span>
<meta property="position" content="3">
</li>
</ol>
</div>
<noscript><p><strong>The calculator does not work with Javascript disabled. Please check your browser settings.</strong></p></noscript>
<div class="applet" id="valueapp">
<div id="polyinput">
<label for="poly">Polynomial</label><input type="text" id="poly" value="" class="input" autocomplete="off" autocapitalize="off" spellcheck="false">
</div>
<div id="modinput">
<label for="mod">Modulus</label><input type="text" id="mod" value="0" class="input">
</div>
<div id="actbtn">
<button type="button" id="eval" title="Evaluate polynomial expression">Evaluate</button>
<button type="button" id="factor" title="Factor and find roots of polynomials">Factor</button>
<button type="button" id="steps" title="Show steps to find the roots of polynomials">Steps</button>
<button type="button" id="stop" title="Stop the calculation">Stop</button>
<button type="button" id="helpbtn" title="Show calculator help">Help</button>
<button type="button" id="clrinput" title="Erase input box contents">Clear<br>input</button><br>
</div>
<div id="lower">
<label for="digits">Digits per group</label> <input type="number" id="digits" value="6">
<span class="nolf"><label for="out">Output</label> <select id="out"><optgroup label="Select output type"><option value="0" selected>Pretty print</option><option value="1">TeX</option><option value="2">Pari/GP</option></optgroup></select></span>
</div>
</div>
<div id="help" aria-live="polite" class="pad">
<p>This Web application can evaluate and factor expressions resulting in quotients of polynomials modulo a prime number or a power of a prime number.
It can also evaluate, factor, and find exact roots of quotients of polynomials by entering zero in the <em>Modulus</em> input box.</p>
<p>You can enter polynomials quickly by using <em>dot notation</em>. For example, to enter 2<var>x</var><sup>4</sup> + 3<var>x</var><sup>2</sup> + 1, you can type: <kbd>2.4 + 3.2 + 1</kbd></p>
<h2><button type="button">Integer polynomials</button></h2>
<div class="panel">
<p>Integer polynomials in one variable are expressions that include a variable named <var>x</var>, integer numbers and the addition, subtraction and multiplication operators.</p>
<p>They can be expressed in the form: <var>f</var>(<var>x</var>) = <var>f</var><sub>0</sub> + <var>f</var><sub>1</sub>⁢<var>x</var> + <var>f</var><sub>2</sub>⁢<var>x</var><sup>2</sup> + ... + <var>f</var><sub>n</sub>⁢<var>x</var><sup>n</sup>.</p>
<p>The number <var>n</var> is the degree of the polynomial. The coefficient <var>f</var><sub>n</sub> is the leading coefficient and the coefficient <var>f</var><sub>0</sub> is the trailing coefficient.
They can be written as deg(<var>f</var>), lc(<var>f</var>) and tc(<var>f</var>) respectively.</p>
<p>Let <var>f</var>(<var>x</var>) and <var>g</var>(<var>x</var>) be two polynomials such that deg(<var>f</var>) ≥ deg(<var>g</var>). We can define addition, subtraction and multiplication as follows:</p>
<p><var>f</var>(<var>x</var>) + <var>g</var>(<var>x</var>) = <var>h</var>(<var>x</var>) means <var>h</var><sub><var>i</var></sub> = <var>f</var><sub><var>i</var></sub> + <var>g</var><sub><var>i</var></sub> if <var>i</var> ≤ deg(<var>g</var>) and <var>h</var><sub><var>i</var></sub> = <var>f</var><sub>i</sub> otherwise.</p>
<p><var>f</var>(<var>x</var>) − <var>g</var>(<var>x</var>) = <var>h</var>(<var>x</var>) means <var>h</var><sub><var>i</var></sub> = <var>f</var><sub><var>i</var></sub> − <var>g</var><sub><var>i</var></sub> if <var>i</var> ≤ deg(<var>g</var>) and <var>h</var><sub><var>i</var></sub> = <var>f</var><sub>i</sub> otherwise.</p>
<p><var>g</var>(<var>x</var>) − <var>f</var>(<var>x</var>) = <var>h</var>(<var>x</var>) means <var>h</var><sub><var>i</var></sub> = <var>g</var><sub><var>i</var></sub> − <var>f</var><sub><var>i</var></sub> if <var>i</var> ≤ deg(<var>g</var>) and <var>h</var><sub><var>i</var></sub> = −<var>f</var><sub>i</sub> otherwise.</p>
<p><var>f</var>(<var>x</var>) ⁢ <var>g</var>(<var>x</var>) = <var>h</var>(<var>x</var>) means
<var>h</var><sub><var>i</var></sub> = <var>f</var><sub>0</sub> ⁢ <var>g</var><sub><var>i</var></sub> + <var>f</var><sub>1</sub> ⁢ <var>g</var><sub><var>i</var> − 1</sub> + ... + <var>f</var><sub>i</sub> ⁢ <var>g</var><sub>0</sub> if <var>i</var> ≤ deg(<var>g</var>),
<var>h</var><sub><var>i</var></sub> = <var>f</var><sub><var>i</var> − deg(<var>g</var>)</sub> ⁢ <var>g</var><sub>deg(<var>g</var>)</sub> + <var>f</var><sub><var>i</var> + 1 − deg(<var>g</var>)</sub> ⁢ <var>g</var><sub>deg(<var>g</var>) − 1</sub> + ... + <var>f</var><sub>i</sub> ⁢ <var>g</var><sub>0</sub> otherwise.</p>
<p>The factorization of integer polynomials is a process to find one or more irreducible polynomials whose product is the original polynomial. An irreducible polynomial cannot be expressed as a product of two or more integer polynomials.</p>
<p>For example: <var>x</var><sup>4</sup> − 1 = (<var>x</var><sup>2</sup> + 1) ⁢ (<var>x</var> + 1) ⁢ (<var>x</var> − 1)</p>
<p>It can be shown that any integer polynomial can be factored in only one way in irreducible polynomials.</p>
</div>
<h2><button type="button">Polynomials modulo a prime number</button></h2>
<div class="panel">
<p>Multiplication of polynomials modulo a prime number can be performed in the usual way by multiplying the different terms of the polynomial
and then adding the coefficients of the same degree. Finally, the coefficients are reduced modulo that prime.</p>
<p>For example, the product of 3x<sup>2</sup> + 5x + 1 and 6x<sup>2</sup> + 4x + 3 modulo 7 is 18x<sup>4</sup> + (30+12)x<sup>3</sup> + (9+20+6)x<sup>2</sup> + (15+4)x + 3 modulo 7 which equals 4x<sup>4</sup> + 5x + 3</p>
<p>It can be shown that the polynomials modulo a prime can be factored into the leading coefficient and monic prime polynomials in only one way (monic polynomials have the leading coefficient equal to one.)</p>
<p>It can also be shown that if there are no repeated factors, the polynomial can be factored modulo a power of that prime in only one way.</p>
</div>
<h2><button type="button">Application usage</button></h2>
<div class="panel">
<p>Use the upper input box to enter the polynomial expression and the lower input box to enter a numerical expression for the modulus,
which must be either zero or an integer number greater than 1 of the form prime number raised to an exponent.
You can just evaluate the polynomial or evaluate and factor it, by pressing the corresponding button.</p>
<p>Example for integer polynomial factorization: to factor <var>x</var><sup>30</sup> − 1, type <kbd>x<span role="img" aria-label="caret">^</span>30<span role="img" aria-label="minus">-</span>1</kbd> in the upper input box and 0 in the lower input box.
Then press the factor button.</p>
<p>Example for polynomial modulo a prime factorization: copy any of the expressions below in the upper input box and type the number 211 (a prime number) in the lower input box.
Then press the button "Factor expression".</p>
<ul>
<li><kbd>6x<span role="img" aria-label=" caret">^</span>8+x<span role="img" aria-label=" caret">^</span>5+3</kbd></li>
<li><kbd>2*<span role="img" aria-label="left parenthesis">(</span>x+6<span role="img" aria-label="right parenthesis">)</span>*<span role="img" aria-label="left parenthesis">(</span>x-5<span role="img" aria-label="right parenthesis">)</span>+xx<span role="img" aria-label=" caret">^</span>4+23x</kbd></li>
</ul>
<p>The exponentiation symbol is not present in some mobile devices, so two asterisks ** can by typed as the exponentiation operator.
So, equivalent expressions would be:</p>
<ul>
<li><kbd>6x**8+x**5+3</kbd></li>
<li><kbd>2*<span role="img" aria-label="left parenthesis">(</span>x+6<span role="img" aria-label="right parenthesis">)</span>*<span role="img" aria-label="left parenthesis">(</span>x-5<span role="img" aria-label="right parenthesis">)</span>+xx**4+23x</kbd></li>
</ul>
<p>You can type a dot (.) and the application will replace it by "x<span role="img" aria-label=" caret">^</span>". This saves a lot of time in mobile devices because there is no
need to switch between alphabetical and numerical keyboards for simple polynomials.</p>
<p>For the first example you would type:</p>
<ul><li><kbd>6.8+.5+3</kbd></li></ul>
<p>Notice that factoring large degree polynomials will take a lot of time.
That's why the applet accepts polynomials of degree up to 1000.</p>
<p>The program has three options for output: with the option <em>Pretty print</em> you can see the exponents as superscripts
and the roots have the traditional, printed format; the option <em>TeX</em> shows the output in this format, which is used in many mathematical forums;
finally, the option <em>Pari-GP</em> is used when you have to copy the data to another application. The output is compatible with the application Pari-GP, only minor changes are required to copy the data to other math programs.</p>
<p>After the applet finishes factoring, it multiplies the factors in order to validate if they are equal to the input polynomial.</p>
<p>When the modulus box is zero, the application finds the roots of the polynomial factors using radical expressions. The program supports degrees up to 5.
By Abel-Ruffini theorem, some polynomials of degree 5 cannot be expressed by radical expressions.</p>
</div>
<h2><button type="button">Expressions</button></h2>
<div class="panel">
<p>You can use any letter to represent the variable. Multiple variables are not accepted. The program always use the letter <var>x</var> to show the output.</p>
<p>You can also enter expressions that use the following operators and parentheses:</p>
<ul>
<li><strong role="img" aria-label="plus sign">+</strong> for addition</li>
<li><strong role="img" aria-label="minus sign">-</strong> for subtraction</li>
<li><strong role="img" aria-label="asterisk">*</strong> for multiplication</li>
<li><strong role="img" aria-label="slash">/</strong> for division</li>
<li><strong role="img" aria-label="percent symbol">%</strong> for remainder of polynomial long division</li>
<li><span role="img" aria-label="caret or two asterisks"><strong>^</strong> or <strong>**</strong></span> for exponentiation</li>
<li><strong>Ans</strong>: retrieves the last answer.</li>
</ul>
<p>Operators and functions for the polynomial (upper box) only:</p>
<ul>
<li><strong>Gcd(f,g, ...)</strong>: Greatest common divisor of these polynomials. Example: GCD(x-1, x^2-1) = x-1.</li>
<li><strong>Lcm(f,g, ...)</strong>: Least common multiple of these polynomials. Example: LCM(x+1, x-1, x^2-1) = x^2-1.</li>
<li><strong>Der(f)</strong>: Derivative of this polynomial.</li>
<li><strong>LongDiv(f, g)</strong>: Long division of these polynomials.</li>
<li><strong>Random(a,b,c,d)</strong>: Random polynomial whose degree is selected between the first two parameters and the coefficients between the last two parameters.</li>
</ul>
<p>Operators and functions for the modulus (lower box) only:</p>
<ul>
<li> <strong><</strong>, <strong>==</strong>, <strong>></strong>; <strong><=</strong>, <strong>>=</strong>, != for comparisons. The operators return zero for false and -1 for true.</li>
<li> <strong>AND</strong>, <strong>OR</strong>, <strong>XOR</strong>, <strong>NOT</strong> for binary logic. The operations are done in binary (base 2). Positive (negative) numbers are prepended with an infinite number of bits set to zero (one).</li>
<li> <strong>SHL</strong> or <strong><<</strong>: When <var>b</var> ≥ 0, <var>a</var> SHL <var>b</var> shifts <var>a</var> left the number of bits specified by <var>b</var>. This is equivalent to <var>a</var> × 2<sup><var>b</var></sup>. Otherwise, <var>a</var> SHL <var>b</var> shifts <var>a</var> right the number of bits specified by −<var>b</var>. This is equivalent to floor(<var>a</var> / 2<sup>−<var>b</var></sup>). Example: 5 SHL 3 = 40.</li>
<li> <strong>SHR</strong> or <strong>>></strong>: When <var>b</var> ≥ 0, <var>a</var> SHR <var>b</var> shifts <var>a</var> right the number of bits specified by <var>b</var>. This is equivalent to floor(<var>a</var> / 2<sup><var>b</var></sup>). Otherwise, <var>a</var> SHR <var>b</var> shifts <var>a</var> left the number of bits specified by −<var>b</var>. This is equivalent to <var>a</var> × 2<sup>−<var>b</var></sup>. Example: -19 SHR 2 = -5.</li>
<li> <strong>n!</strong>: factorial (<var>n</var> must be greater than or equal to zero). Example: 6! = 6 × 5 × 4 × 3 × 2 = 720.</li>
<li> <strong>n!! ... !</strong>: multiple factorial (<var>n</var> must be greater than or equal to zero). It is the product of <var>n</var> times <var>n</var> − <var>k</var> times <var>n</var> − <var>2k</var> ... (all numbers greater than zero) where <var>k</var> is the number of exclamation marks. Example: 7!! = 7 × 5 × 3 × 1 = 105.</li>
<li> <strong>p#</strong>: primorial (product of all primes less or equal than <var>p</var>). Example: 12# = 11 × 7 × 5 × 3 × 2 = 2310.</li>
<li> <strong>B(n)</strong>: Previous probable prime before <em>n</em>. Example: B(24) = 23.</li>
<li> <strong>F(n)</strong>: Fibonacci number F<sub>n</sub> from the sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, etc. where each element equals the sum of the previous two members of the sequence. Example: F(7) = 13.</li>
<li> <strong>L(n)</strong>: Lucas number L<sub>n</sub> = F<sub><var>n</var>-1</sub> + F<sub><var>n</var>+1</sub></li>
<li> <strong>N(n)</strong>: Next probable prime after <em>n</em>. Example: N(24) = 29.</li>
<li> <strong>P(n)</strong>: Unrestricted Partition Number (number of decompositions of <var>n</var> into sums of integers without regard to order). Example: P(4) = 5 because the number 4 can be partitioned in 5 different ways: 4 = 3+1 = 2+2 = 2+1+1 = 1+1+1+1.</li>
<li> <strong>Gcd(m,n, ...)</strong>: Greatest common divisor of these integers. Example: GCD(12, 16) = 4.</li>
<li> <strong>Lcm(m,n, ...)</strong>: Least common multiple of these integers. Example: LCM(12, 16, 24) = 48.</li>
<li> <strong>FloorDiv(m,n)</strong>: integer part of the quotient of <var>m</var> divided by <var>n</var>. Examples: floordiv(10, 7) = 1 and floordiv(-10, 7) = -2.</li>
<li> <strong>Mod(m,n)</strong>: value of <var>m</var> modulo the absolute value of <var>n</var>. Examples: Mod(10, 7) = 3 and Mod(-10, 7) = 4.</li>
<li> <strong>Modinv(m,n)</strong>: inverse of <var>m</var> modulo <var>n</var>, only valid when <var>m</var> and <var>n</var> are coprime, meaning that they do not have common factors. Example: Modinv(3,7) = 5 because 3 × 5 ≡ 1 (mod 7)</li>
<li> <strong>Modpow(m,n,r)</strong>: finds <var>m</var><sup><var>n</var></sup> modulo <var>r</var>. Example: Modpow(3, 4, 7) = 4, because 3<sup>4</sup> ≡ 4 (mod 7).</li>
<li> <strong>Jacobi(m,n)</strong>: obtains the Jacobi symbol of <var>m</var> and <var>n</var>. When the second argument is prime, the result is zero when <var>m</var> is multiple of <var>n</var>, it is one if there is a solution of <var>x</var>² ≡ <var>m</var> (mod <var>n</var>) and it is equal to −1 when the mentioned congruence has no solution.</li>
<li> <strong>Random(m,n)</strong>: integer random number between <var>m</var> and <var>n</var>.</li>
<li> <strong>Abs(n)</strong>: absolute value of <var>n</var>.</li>
<li> <strong>Sign(n)</strong>: returns zero if <var>n</var> is zero, −1 if negative or 1 if positive.</li>
<li> <strong>IsPrime(n)</strong>: returns zero if <var>n</var> is not probable prime, −1 if it is. Example: IsPrime(5) = −1.</li>
<li> <strong>Sqrt(n)</strong>: Integer part of the square root of the argument.</li>
<li> <strong>Iroot(n,r)</strong>: Integer r-root of the first argument. Example: Iroot(8, 3) = 2.</li>
<li> <strong>NumDigits(n,r)</strong>: Number of digits of <var>n</var> in base <var>r</var>. Example: NumDigits(13, 2) = 4 because 13 in binary (base 2) is expressed as 1101.</li>
<li> <strong>SumDigits(n,r)</strong>: Sum of digits of <var>n</var> in base <var>r</var>. Example: SumDigits(213, 10) = 6 because the sum of the digits expressed in decimal is 2+1+3 = 6.</li>
<li> <strong>RevDigits(n,r)</strong>: finds the value obtained by writing backwards the digits of <var>n</var> in base <var>r</var>. Example: RevDigits(213, 10) = 312.</li>
</ul>
<p>You can use the prefix <em>0x</em> for hexadecimal numbers, for example 0x38 is equal to 56.</p>
</div>
<h2><button type="button">Long division</button></h2>
<div class="panel">
<h3>Division of polynomials modulo a prime number</h3>
<p>The polynomial division requires multiple modular divisions where the divisor is the leading coefficient of the divisor polynomial.</p>
<p>To compute the modular division <var>a</var> / <var>b</var> (mod <var>p</var>), first the modular multiplicative inverse <var>c</var> is found.
This number has the property <var>b</var>⁢<var>c</var> ≡ 1 (mod <var>p</var>) and it can be found using the extended Euclidean algorithm as follows:</p>
<p><code>
function modInv(value, modulus)<br>
{<br>
V1 ← 1; V3 ← value;<br>
U1 ← 0; U3 ← modulus;<br>
while V3 ≠ 0<br>
{<br>
QQ ← U3 / V3;<br>
T1 ← U1 − V1 * QQ;<br>
T3 ← U3 − V3 * QQ;<br>
U1 ← V1; U3 ← V3;<br>
V1 ← T1; V3 ← T3;<br>
}<br>
return U1;<br>
}
</code></p>
<p>Then the division is equal to the product <var>a</var>⁢<var>c</var> (mod <var>p</var>).</p>
<p>To minimize the number of modular divisions (which are expensive), we can multiply all coefficients of both polynomials (dividend and divisor) by the multiplicative inverse of the leading coefficient of the divisor polynomial.
In this way, we will divide by a monic polynomial, that is, a polynomial whose leading coefficient equals 1. This will not change the quotient, but the remainder will need to be multiplied by the leading coefficient of the divisor polynomial.</p>
<p>Example: perform the division (3⁢<var>x</var><sup>3</sup> + 7⁢<var>x</var><sup>2</sup> + 5⁢<var>x</var> + 6) / (4⁢<var>x</var><sup>2</sup> + 3⁢<var>x</var> + 10) (mod 11):</p>
<p>First we have to find the multiplicative inverse of 4 (mod 11), which equals 3, because 4 × 3 = 12 ≡ 1 (mod 11). Multiplying all coefficients by 3 we get:</p>
<p>(9⁢<var>x</var><sup>3</sup> + 10⁢<var>x</var><sup>2</sup> + 4⁢<var>x</var> + 7) / (<var>x</var><sup>2</sup> + 9⁢<var>x</var> + 8) (mod 11)</p>
<p>Dividing the leading coefficient of the dividend polynomial over the leading coefficient of the divisor polynomial: 9⁢<var>x</var><sup>3</sup> / <var>x</var><sup>2</sup> ≡ 9⁢<var>x</var> (mod 11).</p>
<p>Now we subtract the product of what we have just found by the divisor polynomial from the dividend polynomial. We obtain:</p>
<p>9⁢<var>x</var><sup>3</sup> + 10⁢<var>x</var><sup>2</sup> + 4⁢<var>x</var> + 7 - 9⁢<var>x</var>(<var>x</var><sup>2</sup> + 9⁢<var>x</var> + 8) ≡ 6⁢<var>x</var><sup>2</sup> + 9⁢<var>x</var> + 7 (mod 11). Notice that 10 − 9 × 9 ≡ 6 (mod 11) and 4 − 9 × 8 (mod 11) ≡ 9 (mod 11).</p>
<p>Dividing the leading coefficient of the remainder polynomial we just found over the leading coefficient of the divisor polynomial: 6⁢<var>x</var><sup>2</sup> / <var>x</var><sup>2</sup> ≡ 6 (mod 11).</p>
<p>Now we subtract the product of what we have just found by the divisor polynomial from the remainder polynomial. We obtain:</p>
<p>(6⁢<var>x</var><sup>2</sup> + 9⁢<var>x</var> + 7) − 6⁢(<var>x</var><sup>2</sup> + 9⁢<var>x</var> + 8) ≡ 10<var>x</var> + 3 (mod 11). Notice that 9 − 6 × 9 ≡ 10 (mod 11) and 7 − 6 × 8 ≡ 3 (mod 11).</p>
<p>The quotient polynomial equals 9⁢<var>x</var> + 6 and the remainder polynomial equals 4⁢(10<var>x</var> + 3) ≡ 7 <var>x</var> + 1 (mod 11).</p>
<h3>Division of integer polynomials</h3>
<p>The division proceeds in the same way as in the previous subsection, with the difference that there is no multiplicative inverse of the leading coefficient of the divisor polynomial. So, for each iteration of the algorithm, a division is required.
If the divisor polynomial is not monic, sometimes the division cannot be performed. This occurs when the leading coefficient of the remainder is not multiple of the leading coefficient of the divisor.</p>
</div>
<h2><button type="button">Greatest common divisor of polynomials</button></h2>
<div class="panel">
<p>The greatest common divisor of two polynomials is the polynomial of the highest possible degree, that divides both polynomials.</p>
<p>For example: gcd(<var>x</var><sup>2</sup> + 6⁢<var>x</var> + 5, 2⁢<var>x</var><sup>2</sup> + 13⁢<var>x</var> + 15) = <var>x</var> + 5</p>
<h3>GCD of polynomials modulo a prime number</h3>
<p>The greatest common divisor can be found using the Euclidean algorithm as follows:</p>
<p><code>
function gcdm(poly1, poly2, p)<br>
{<br>
a ← poly1;<br>
b ← poly2;<br>
while b ≠ 0<br>
t ← b;<br>
b ← remainder(a, b) (mod p);<br>
a ← t;<br>
return a;<br>
}<br>
</code></p>
<h3>GCD of integer polynomials</h3>
<p>While the same algorithm could be used for finding the gcd of two integer polynomials, the coefficients of the intermediate polynomials increase very quickly, so this is not useful.</p>
<p>There are two methods to find the gcd: the subresultant algorithm and the modular algorithm. The latter, invented by William Brown, uses gcd of polynomials modulo a prime, so this is better for our purposes.</p>
<p><code>
function gcdp(poly1, poly2)<br>
{<br>
c<sub>1</sub> ← cont(poly1);<br>
c<sub>2</sub> ← cont(poly2);<br>
c ← gcd(c<sub>1</sub>, c<sub>2</sub>);<br>
a ← poly1 / c<sub>1</sub>;<br>
b ← poly2 / c<sub>2</sub>;<br>
h ← gcd(lc(poly1), lc(poly2));<br>
d ← min(deg(poly1), deg(poly2));<br>
m ← 1;<br>
g<sub>m</sub> ← 0;<br>
repeat<br>
{<br>
do<br>
{<br>
do<br>
{<br>
p ← nextPrime();<br>
} while remainder(m*h, p) = 0;<br>
r ← poly1 (mod p);<br>
s ← poly2 (mod p);<br>
g<sub>p</sub> ← gcdm(r, s, p);<br>
if deg(g<sub>p</sub>) = 0<br>
{<br>
output c; stop;<br>
}<br>
} while deg(g<sub>p</sub>) > d;<br>
g<sub>p</sub> ← (h mod p)/lc(g<sub>p</sub>) * g<sub>p</sub>;<br>
if deg(g<sub>p</sub>) < d<br>
{<br>
m ← 1;<br>
g<sub>m</sub> ← 0;<br>
d ← deg(g<sub>p</sub>);<br>
}<br>
h ← CRA([g<sub>p</sub>, p], [g<sub>m</sub>, m]);<br>
if h = g<sub>m</sub><br>
{<br>
h ← h / cont(h);<br>
if remainder(a, h) = 0 and remainder(b, h) = 0<br>
{<br>
output c*h; stop;<br>
}<br>
}<br>
m ← p * m;<br>
g<sub>m</sub> ← h;<br>
}<br>
}
</code></p>
<p>The content of a polynomial is the greatest common divisor of all coefficients of that polynomial. The sign of the content matches the sign of the leading coefficient. It is expressed as cont(f) in the previous algorithm.</p>
<p>The coefficients of the result of the Chinese Remainder Algorithm (function CRA) computed modulo <var>m</var><var>p</var>, must be in the range −<var>m</var><var>p</var>/2 to <var>m</var><var>p</var>/2.</p>
<p>The idea behind this algorithm is to compute several gcd of the input polynomials modulo different primes. We can see that their degrees are greater or equal than the degree of the polynomial gcd.</p>
<p>There are three cases:</p>
<ul>
<li>The degree of the modular gcd is greater than the degree of previous modular gcd: the new result is discarded because it has incorrect degree.</li>
<li>The degree of the modular gcd is less than the degree of previous modular gcd: the old result is discarded because it has incorrect degree. The new result is used instead.</li>
<li>Both degrees are equal: the coefficients of both gcds are merged using the Chinese Remainder Theorem. This algorithm computes <var>g</var> (mod <var>m</var><var>p</var>) given <var>g</var><sub>m</sub> (mod <var>m</var>) and <var>g</var><sub>p</sub> (mod <var>p</var>).</li>
</ul>
<p>The algorithm continues until the computed polynomial divides both input polynomials.</p>
</div>
<h2><button type="button">Factoring polynomials modulo a prime number</button></h2>
<div class="panel">
<p>The factoring algorithm can be divided in four steps: square-free factorization, distinct degree factorization, equal degree factorization and factor lift. All steps require monic polynomials, so before starting, we will have to multiply all coefficients by the modular multiplicative inverse of the leading coefficient of the polynomial.</p>
<h3>Square-free factorization</h3>
<p>The next steps do not work if there are repeated factors, so the first step is to factor the polynomial in such a way that there are no repeated factors.</p>
<p>The derivative of the polynomial <var>f</var>(<var>x</var>) = <var>f</var><sub>0</sub> + <var>f</var><sub>1</sub>⁢<var>x</var> + <var>f</var><sub>2</sub>⁢<var>x</var><sup>2</sup> + ... + <var>f</var><sub>n</sub>⁢<var>x</var><sup>n</sup> is
<var>f</var>'(<var>x</var>) = <var>f</var><sub>1</sub> + 2⁢<var>f</var><sub>2</sub>⁢<var>x</var> + ... + <var>n</var>⁢<var>f</var><sub>n</sub>⁢<var>x</var><sup>n − 1</sup></p>
<p>The recursive algorithm is:</p>
<p><code>
function SFF(f)<br>
{<br>
i ← 1; g ← f';<br>
if g ≠ 0<br>
{<br>
c ← gcd(f, g);<br>
w ← f / c;<br>
while w ≠ 1<br>
{<br>
y ← gcd(w, c); z ← w / y;<br>
Output(z<sup>i</sup>); i ← i + 1;<br>
w ← y; c ← c / y;<br>
}<br>
if c ≠ 1<br>
{<br>
c ← c<sup>1/p</sup>;<br>
Output(SFF(c)<sup>p</sup>);<br>
}<br>
}<br>
else<br>
{<br>
f ← f<sup>1/p</sup>;<br>
Output(SFF(f)<sup>p</sup>);<br>
}<br>
}
</code></p>
<p>For each polynomial on the output of this algorithm we have to perform the next steps.</p>
<h3>Distinct degree factorization</h3>
<p>This is a method that exploits the fact that the product of all monic irreducible polynomials of degrees that divide <var>d</var> (mod <var>p</var>) equals <var>x</var><sup>e</sup> − <var>x</var> where <var>e</var> = <var>p</var><sup><var>d</var></sup>.</p>
<p><code>
function DDF(f, p)<br>
{<br>
i ← 1;<br>
h ← f;<br>
j ← x;<br>
q ← 0;<br>
while deg(h) ≥ 2⁢i<br>
{<br>
j ← j<sup>p</sup> (mod h);<br>
g ← gcdm(h, j − x);<br>
if g ≠ 1<br>
{<br>
Output(g, i);<br>
q ← 1;<br>
h ← h / g;<br>
}<br>
}<br>
if h ≠ 1<br>
{<br>
Output(h, deg(h));<br>
q ← 1;<br>
}<br>
if q = 0<br>
{<br>
Output(f, 1);<br>
}<br>
}
</code></p>
<p>The pairs that form the output of this function are the input for the next step. The first element of the pair is a factor of <var>f</var> which is the product of all factors of the degree specified in the second element of the pair.</p>
<h3>Equal degree factorization</h3>
<p>This is a probabilistic method due to David Cantor and Hans Zassenhaus that finds all factors of the same degree from the output of the previous algorithm:</p>
<p><code>
function EDF(f, d, p)<br>
{<br>
n ← deg(f);<br>
set list of factors to f;<br>
while size(list of factors) < n/d<br>
{<br>
h ← random polynomial with deg(h) < n;<br>
e ← (q<sup>d</sup> − 1) / 2;<br>
g ← h<sup>e</sup> − 1 (mod f);<br>
for each element u of list of factors<br>
{<br>
if deg(u) > d<br>
{<br>
j ← gcdm(g, u);<br>
if j ≠ 1 and j ≠ u<br>
{<br>
discard u from list of factors;<br>
add j and u/j to list of factors;<br>
}<br>
}<br>
}<br>
}<br>
Output list of factors<br>
}
</code></p>
<h3>Polynomial lift</h3>
<p>Once all irreducible factors of the polynomial modulo <var>p</var> are found, we can find the factor of the polynomial modulo <var>p</var><sup>n</sup> if there are no repeated factors. The following algorithm can lift from modulo <var>m</var> to <var>m</var><sup>2</sup>, so we can execute it several times until the complete lifting is done.</p>
<p>On input: f = g*h (mod m), s*g + t*h = 1 (mod m)</p>
<p>On output: f = g'*h' (mod m<sup>2</sup>), s'*g' + t'*h' = 1 (mod m<sup>2</sup>) with deg(s') < deg(h'), deg(t') < deg(g')</p>
<p>All calculations below are performed mod m<sup>2</sup>.</p>
<p><code>
e ← f - g*h<br>
Compute q, r such that s*e = q*h + r<br>
g' ← g + t*e + q*g<br>
h' ← h + r<br>
<br>
e ← s*g' + t*h' − 1<br>
Compute q, r such that s*e = q*h + r<br>
s' ← s − r<br>
t' ← t − t*e − q*g'
</code></p>
<p>The initial values of <var>s</var> and <var>t</var> are obtained from <var>g</var> and <var>h</var> using Extended Euclidean algorithm.</p>
</div>
<h2><button type="button">Factoring integer polynomials</button></h2>
<div class="panel">
<p>We can use the output of the previous section to factor integer polynomials.</p>
<p>First of all, we need to divide the polynomial by its content (the greatest common divisor of all coefficients with the sign of the leading coefficient). The result is the principal part, named pp(<var>f</var>).</p>
<p>The methods shown below do not work if the factors are repeated. To separate them, we can use Yun's algorithm as follows:</p>
<p>Let <var>f</var> = <var>a</var><sub>1</sub> ⁢ <var>a</var><sub>2</sub>² ⁢ <var>a</var><sub>3</sub>³ ⁢ ... ⁢ <var>a</var><sub><var>n</var></sub><sup>n</sup></p>
<p><code>a[0] = gcd(f, der(f));<br>
b[1] = f / a[0];<br>
c[1] = der(f) / a[0];<br>
d[1] = c[1] - der(f[1]);<br>
i = 1;<br>
repeat<br>
a[i] = gcd(b[i], d[i]);<br>
b[i+1] = b[i] / a[i];<br>
c[i+1] = d[i] / a[i];<br>
i = i + 1;<br>
d[i] = c[i] - der(b[i]);<br>
until b = 1;<br>
output a[1], ..., a[i-1];
</code></p>
<p>At this moment we know that there are no repeated factors. We have to find a small prime <var>p</var> for which the polynomial has no repeated factors. This can be easily found by checking that gcd(<var>f</var>, <var>f'</var>) ≡ 1 (mod <var>p</var>).</p>
<p>We need to find a bound of the coefficient of factors. The Knuth-Cohen bound for coefficients of polynomial factors can be computed as follows:</p>
<p>If polynomial <var>G</var> divides <var>F</var> we have for all <var>j</var>:</p>
<p>|<var>G</var><sub><var>j</var></sub>| ≤ binomial(<var>n</var> − 1, j)*(Σ<sub><var>i</var></sub> |<var>F</var><sub><var>i</var></sub>|<sup>2</sup>)<sup>1/2</sup> + binomial(<var>n</var> − 1, <var>j</var> −1) * |<var>F</var><sub><var>m</var></sub>|</p>
<p>where <var>m</var> is the degree of <var>F</var> and <var>n</var> is the degree of <var>G</var>. The maximum degree to be considered is <var>n</var> = ceil(<var>m</var>/2).</p>
<p>Once the bound <var>B</var> is found, we have to compute the least value of <var>e</var> such that 2⁢B < <var>p</var><sup>e</sup>.</p>
<p>Now we factor the polynomial mod <var>p</var><sup>e</sup> which has <var>r</var> different factors. If <var>r</var> > 10, we can try a different value of <var>p</var>, so we minimize the number of factors found. The application tries up to 5 different primes.</p>
<p>We will now combine the factors found modulo <var>p</var><sup>e</sup> to get integer polynomial factors. There are 2<sup>r</sup> possible combinations, but most of them can be easily discarded.</p>
<p>Let the combination of factors found are <var>f</var><sub>0</sub>, <var>f</var><sub>1</sub>, ..., <var>f</var><sub>s</sub>. Compute <var>a</var> ≡ lc(<var>f</var>) ⁢ tc(<var>f</var><sub>0</sub>)⁢ tc(<var>f</var><sub>1</sub>) ⁢ ... ⁢tc(<var>f</var><sub>s</sub>) (mod <var>p</var><sup>e</sup>) and <var>b</var> ≡ lc(<var>f</var>) ⁢ tc(<var>f</var>) (mod <var>p</var><sup>e</sup>). In both cases the products must be in the range −<var>p</var><sup>e</sup>/2 to <var>p</var><sup>e</sup>/2.
If <var>a</var> does not divide <var>b</var>, we can discard that combination.</p>
<p>For the very few combinations that remain, compute a ≡ lc (<var>f</var>) ⁢ <var>f</var><sub>0</sub> ⁢ <var>f</var><sub>1</sub> ⁢ ... ⁢ <var>f</var><sub>s</sub> (mod <var>p</var><sup>e</sup>). Again, this time the coefficients of this polynomial must be in the range −<var>p</var><sup>e</sup>/2 to <var>p</var><sup>e</sup>/2.
Compute <var>b</var> = gcdp(<var>a</var>, lc(<var>f</var>) ⁢ <var>f</var>). If the degree of <var>b</var> is zero, discard this combination. Otherwise, the polynomial <var>b</var> is a proper factor of <var>f</var>.</p>
<p>Even though the steps are very fast, for some polynomials the number of combinations is very huge. So, the program uses Van Hoeij algorithm which uses LLL algorithm to determine quickly the combinations to use.</p>
</div>
<h2><button type="button">Roots</button></h2>
<div class="panel">
<p>The program finds the roots from the irreducible polynomials obtained in the previous section.</p>
<p>For polynomials of degrees up to 4, the standard formulas are used. No cube roots of complex numbers are used. In these cases (named <em>casus irreducibilis</em>), the program uses trigonometric functions.</p>
<p>For polynomials of degree 5, the application uses the results of D. S. Dummit's paper <em><a href="https://www.ams.org/journals/mcom/1991-57-195/S0025-5718-1991-1079014-X/S0025-5718-1991-1079014-X.pdf">Solving Solvable Quintic</a></em>, Mathematics of Computation volume 57, number 195, July 1991, pp. 387-401.</p>
<p>The program can determine whether an irreducible polynomial is cyclotomic, i. e., a divisor of <var>x</var><sup><var>n</var></sup> − 1. In this case the program shows the complex roots of 1:</p>
<p><span role="img" aria-label="cosine of">cos</span> <f-f><f-n><var>m</var><span role="img" aria-label=" times pi"> π</span></f-n><f-d><var>n</var></f-d></f-f> +
i <span role="img" aria-label=" times sine of">sin</span><f-f><f-n><var>m</var><span role="img" aria-label=" times pi"> π</span></f-n><f-d><var>n</var></f-d></f-f></p>
<p>where <var>m</var> and <var>n</var> are coprime.</p>
<p>If <var>n</var> = 2<sup><var>q</var></sup> × 3<sup><var>r</var></sup> × 5<sup><var>s</var></sup> × 17<sup><var>t</var></sup>
where <var>r</var> < 2, <var>s</var> < 2 and <var>t</var> < 2, the program can find the roots as radical expressions.</p>
<p>For irreducible polynomials of the form <var>a</var> <var>x</var><sup>n</sup> + <var>b</var>, the roots can be computed as the product of a real number by a complex root of 1, so the method used in the previous paragraph is used.</p>
<p>For <var>a</var> <var>x</var><sup>2n</sup> + <var>b</var> <var>x</var><sup>n</sup> + <var>c</var> there are two cases. If the quadratic polynomial (discarding the variable <var>n</var>) has real roots, again we can use the methods of the previous paragraph.
Otherwise, only trigonometric functions are shown.</p>
<p>For almost all polynomials with degree 5 or greater, the roots cannot be expressed as radical expressions. To detect these cases with high probability, the program uses the results of two papers about Galois theory:</p>
<ul>
<li>J.H. Davenport, G.C. Smith, <em><a href="https://www.sciencedirect.com/science/article/pii/S002240499900078X">Fast recognition of alternating and symmetric Galois groups</a></em>, Journal of Pure and Applied Algebra 153 (2000) 17-25.</li>
<li>K. Conrad, <em><a href="https://kconrad.math.uconn.edu/blurbs/galoistheory/galoisSnAn.pdf">Recognizing Galois groups <var>S</var><sub><var>n</var></sub> and <var>A</var><sub><var>n</var></sub></a></em></li>
</ul>
</div>
<div class="noand">
<h2><button type="button">Source code</button></h2>
</div>
<div class="panel">
<div class="noand">
<p>You can download the source of the current program and the old sum polynomial factorization applet from <a href="https://github.com/alpertron/calculators">GitHub</a>. Notice that the source code is in C language and you need the <a href="https://emscripten.org/docs/getting_started/downloads.html">Emscripten</a> environment in order to generate JavaScript.</p>
</div>
</div>
<p>Written by Dario Alpern. Last updated 1 January 2025.</p>
</div>
<div id="result" aria-live="polite" class="pad"></div>
<div id="footer">
<p><span class="new">New!</span> You can download an application for Android that includes this calculator from <a href="https://play.google.com/store/apps/details?id=ar.com.alpertron.calculators">Google Play</a>.</p>
<p>If you find any error or you have a comment, please fill in the <a href="#" id="formlink">form</a>.</p>
<p>If you like these calculators and you want to support free software with no annoying advertisements, you can <a href="https://www.PayPal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MR65QPWZM5JT6&source=url">donate through PayPal</a>.</p>
</div>
</article>
</main>
<aside id="feedback" aria-label="Feedback form">
<h2 class="h2title">Feedback form</h2>
<form class="applet" id="formfeedback">
<input type="hidden" name="subject" value="Polynomial factorization calculator feedback">
<div id="formleft">
<div class="labels"><label for="name">Your name is:</label><input class="inputfbck" type="text" name="name" maxlength="40" id="name" autocomplete="name"></div>
<div class="labels"><label for="age">Age:</label><input class="inputfbck" type="number" name="age" min="0" max="999" id="age"></div>
<div class="labels"><label for="city">City:</label><input class="inputfbck" type="text" name="city" maxlength="70" id="city" autocomplete="address-level2"></div>
<div class="labels"><label for="province">Province/State:</label><input class="inputfbck" type="text" name="province" maxlength="70" id="province" autocomplete="address-level1"></div>
<div class="labels"><label for="country">Country:</label><input class="inputfbck" type="text" name="country" maxlength="70" id="country" autocomplete="country-name"></div>
<div class="labels"><label for="reply">E-mail address:</label><input class="inputfbck" type="email" name="reply" maxlength="70" id="reply" autocomplete="email"></div>
<p>All fields are optional. Enter your e-mail address if you want a reply from the author of this application.</p>
<p><input type="checkbox" id="adduserdata"><label for="adduserdata">Send polynomial to factor</label></p>
<input type="hidden" name="userdata" value="" id="userdata">
</div>
<div id="formright">
<label for="comments">Please feel free to add comments:</label><br>
<textarea name="Comments" rows="7" cols="40" id="comments"></textarea>
<p><label for="how">How did you find my page?</label><br>
<select name="how" title="How did you find my page?" id="how">
<optgroup label="Select response">
<option value="from a search engine" selected>From a search engine</option>
<option value="from a friend">From a friend</option>
<option value="from a link">From a link</option>
<option value="from Wikipedia">From Wikipedia or another reference</option>
<option value="other">Other</option>
</optgroup>
</select></p>
<fieldset><legend>Are the programs instructive?</legend>
<input type="radio" name="Instructive" value="Yes" id="insyes"><label for="insyes">Yes</label>
<input type="radio" name="Instructive" value="No" id="insno"><label for="insno">No</label>
</fieldset>
<fieldset><legend>Are the programs interesting?</legend>
<input type="radio" name="Interesting" value="Yes" id="intyes"><label for="intyes">Yes</label>
<input type="radio" name="Interesting" value="No" id="intno"><label for="intno">No</label>
</fieldset>
<p><button type="submit" disabled="disabled" id="formsend" title="Deliver this form">Send it in!</button>
<button type="reset">Reset</button>
<button type="button" id="formcancel" title="Do not deliver this form">Cancel</button></p>
</div>
<div class="lf"></div>
</form>
</aside>
<aside id="sending">
<p>Sending comments...</p>
</aside>
<aside id="sentOK">
<p>Feedback sent successfully.</p>
<div class="center"><button type="button" id="btnSentOK">Go back</button></div>
</aside>
<aside id="notSent">
<p>Feedback could not be sent.</p>
<div class="center"><button type="button" id="btnNotSent">Go back</button></div>
</aside>
<script type="text/wasmb64" id="wasmb64">
</script>
<script type="text/js-worker" id="worker">
</script>
<script>
<!--
//-->
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"browserRequirements": "Requires HTML5. Requires Javascript.",
"name": "Polynomial factorization calculator",
"description": "Web application that factors integer polynomials and polynomials modulo a power of a prime number. It also shows roots using radical expressions.",
"image": ["https://www.alpertron.com.ar/polfact.png"],
"datePublished": "2025-01-01",
"dateModified": "2025-01-01",
"operatingSystem": "Any",
"applicationCategory": "EducationalApplication",
"author": {
"@type": "Person",
"name": "Dario Alpern"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"ratingCount": "97"
},
"inLanguage": "en",
"license": "https://www.gnu.org/licenses/gpl-3.0.en.html",
"isAccessibleForFree": true,
"offers": {
"@type": "Offer",
"availability": "https://schema.org/OnlineOnly",
"price": "0",
"priceCurrency": "USD"
}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": ["MathSolver", "LearningResource"],
"name": "Polynomial factorization and roots calculator",
"url": "https://www.alpertron.com.ar/POLFACT.HTM",
"usageInfo": "https://www.alpertron.com.ar/PRIVACY.HTM",
"image": ["https://www.alpertron.com.ar/polfact.png"],
"inLanguage": "en",
"potentialAction": [{
"@type": "SolveMathAction",
"target": "https://www.alpertron.com.ar/POLFACT.HTM?q={math_expression_string}",
"mathExpression-input": "required name=math_expression_string",
"eduQuestionType": ["Polynomial Equation", "Polynomial Expression", "Biquadratic Equation", "Quadratic Equation", "Quadratic Expression", "Rational Expression", "Rational Equation", "Linear Equation"]
}],
"learningResourceType": "Math solver"
}
</script>
</body>
</html>