-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgaussian_factors.sf
67 lines (53 loc) · 1.57 KB
/
gaussian_factors.sf
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
#!/usr/bin/ruby
# Author: Trizen
# Date: 09 May 2022
# https://github.com/trizen
# Find the factors of a Gaussian integer.
# See also:
# https://www.alpertron.com.ar/GAUSSIAN.HTM
# https://en.wikipedia.org/wiki/Table_of_Gaussian_integer_factorizations
func gaussian_factors(Gauss z) {
var Z = z
var n = z.norm
var factors = []
for p,e in (n.factor_exp) {
if (p == 2) {
var t = Gauss(1,1)
while (z % t == 0) {
factors << t
z /= t
}
}
elsif (p % 4 == 3) {
var t = Gauss(p)
while (z % t == 0) {
factors << t
z /= t
}
}
else {
for a,b in (sum_of_squares(p)) {
var t1 = Gauss(a,b)
var t2 = Gauss(b,a)
while (z % t1 == 0) {
factors << t1
z /= t1
}
while (z % t2 == 0) {
factors << t2
z /= t2
}
}
}
}
if (z != Gauss(1,0)) {
factors << z
}
assert_eq(factors.prod.abs, Z.abs)
assert_eq(factors.prod.norm, n)
return factors.sort.run_length
}
var z = Gauss(440, -55)
var factors = gaussian_factors(z)
say factors #=> [[Gauss(-1, 0), 1], [Gauss(1, 2), 1], [Gauss(2, 1), 2], [Gauss(2, 3), 1], [Gauss(11, 0), 1]]
say factors.prod_2d {|p,e| p**e } #=> Gauss(440, -55)