gaussian_integers.sf 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #!/usr/bin/ruby
  2. # Simple implementation of Gaussian integers.
  3. # See also:
  4. # https://en.wikipedia.org/wiki/Gaussian_integer
  5. class Gaussian(a, b) { # represents: a + b*i
  6. method to_s {
  7. "Gaussian(#{a}, #{b})"
  8. }
  9. method reals {
  10. (a,b)
  11. }
  12. method ==(Gaussian c) {
  13. (a == c.a) && (b == c.b)
  14. }
  15. method conjugate {
  16. Gaussian(a, -b)
  17. }
  18. method norm {
  19. a*a + b*b
  20. }
  21. method add (Gaussian z) {
  22. var (c,d) = (z.a, z.b)
  23. Gaussian(a+c, b+d)
  24. }
  25. __CLASS__.alias_method(:add, '+')
  26. method sub (Gaussian z) {
  27. var (c,d) = (z.a, z.b)
  28. Gaussian(a-c, b-d)
  29. }
  30. __CLASS__.alias_method(:sub, '-')
  31. method mul (Gaussian z) {
  32. var (c,d) = (z.a, z.b)
  33. Gaussian(a*c - b*d, a*d + b*c)
  34. }
  35. __CLASS__.alias_method(:mul, '*')
  36. method mod (Number m) {
  37. Gaussian(a % m, b % m)
  38. }
  39. __CLASS__.alias_method(:mod, '%')
  40. method pow(Number n) {
  41. var x = self
  42. var c = Gaussian(1, 0)
  43. for bit in (n.digits(2)) {
  44. c *= x if bit
  45. x *= x
  46. }
  47. return c
  48. }
  49. __CLASS__.alias_method(:pow, '**')
  50. method powmod(Number n, Number m) {
  51. var x = self
  52. var c = Gaussian(1, 0)
  53. for bit in (n.digits(2)) {
  54. (c *= x) %= m if bit #=
  55. (x *= x) %= m #=
  56. }
  57. return c
  58. }
  59. }
  60. var a = Gaussian(3,4)**10
  61. var b = Gaussian(3,4).powmod(97, 1234)
  62. say a
  63. say b
  64. # Run some tests
  65. assert_eq([a.reals], [reals(Gauss(3,4)**10)])
  66. assert_eq([b.reals], [reals(Gauss(3,4).powmod(97, 1234))])
  67. assert_eq([reals(a+b)], [reals(Gauss(reals(a)) + Gauss(reals(b)))])
  68. assert_eq([reals(a-b)], [reals(Gauss(reals(a)) - Gauss(reals(b)))])