gaussian_factors.sf 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 09 May 2022
  4. # https://github.com/trizen
  5. # Find the factors of a Gaussian integer.
  6. # See also:
  7. # https://www.alpertron.com.ar/GAUSSIAN.HTM
  8. # https://en.wikipedia.org/wiki/Table_of_Gaussian_integer_factorizations
  9. func gaussian_factors(Gauss z) {
  10. var Z = z
  11. var n = z.norm
  12. var factors = []
  13. for p,e in (n.factor_exp) {
  14. if (p == 2) {
  15. var t = Gauss(1,1)
  16. while (z % t == 0) {
  17. factors << t
  18. z /= t
  19. }
  20. }
  21. elsif (p % 4 == 3) {
  22. var t = Gauss(p)
  23. while (z % t == 0) {
  24. factors << t
  25. z /= t
  26. }
  27. }
  28. else {
  29. for a,b in (sum_of_squares(p)) {
  30. var t1 = Gauss(a,b)
  31. var t2 = Gauss(b,a)
  32. while (z % t1 == 0) {
  33. factors << t1
  34. z /= t1
  35. }
  36. while (z % t2 == 0) {
  37. factors << t2
  38. z /= t2
  39. }
  40. }
  41. }
  42. }
  43. if (z != Gauss(1,0)) {
  44. factors << z
  45. }
  46. assert_eq(factors.prod.abs, Z.abs)
  47. assert_eq(factors.prod.norm, n)
  48. return factors.sort.run_length
  49. }
  50. var z = Gauss(440, -55)
  51. var factors = gaussian_factors(z)
  52. say factors #=> [[Gauss(-1, 0), 1], [Gauss(1, 2), 1], [Gauss(2, 1), 2], [Gauss(2, 3), 1], [Gauss(11, 0), 1]]
  53. say factors.prod_2d {|p,e| p**e } #=> Gauss(440, -55)