quaternion_integers.sf 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/ruby
  2. # Simple implementation of quaternion integers.
  3. # See also:
  4. # https://en.wikipedia.org/wiki/QuaternionInteger
  5. class QuaternionInteger(a, b=0, c=0, d=0) {
  6. method to_s {
  7. "QuaternionInteger(#{a}, #{b}, #{c}, #{d})"
  8. }
  9. method ==(QuaternionInteger z) {
  10. (a == z.a) && (b == z.b) && (c == z.c) && (d == z.d)
  11. }
  12. method add (QuaternionInteger z) {
  13. var (a2,b2,c2,d2) = (z.a, z.b, z.c, z.d)
  14. QuaternionInteger(a+a2, b+b2, c+c2, d+d2)
  15. }
  16. __CLASS__.alias_method(:add, '+')
  17. method sub (QuaternionInteger z) {
  18. var (a2,b2,c2,d2) = (z.a, z.b, z.c, z.d)
  19. QuaternionInteger(a-a2, b-b2, c-c2, d-d2)
  20. }
  21. __CLASS__.alias_method(:sub, '-')
  22. method mul (QuaternionInteger z) {
  23. var (a2,b2,c2,d2) = (z.a, z.b, z.c, z.d)
  24. QuaternionInteger(
  25. a*a2 - b*b2 - c*c2 - d*d2,
  26. a*b2 + b*a2 + c*d2 - d*c2,
  27. a*c2 - b*d2 + c*a2 + d*b2,
  28. a*d2 + b*c2 - c*b2 + d*a2,
  29. )
  30. }
  31. __CLASS__.alias_method(:mul, '*')
  32. method mod (Number m) {
  33. QuaternionInteger(a % m, b % m, c % m, d % m)
  34. }
  35. __CLASS__.alias_method(:mod, '%')
  36. method pow(Number n) {
  37. var x = self
  38. var c = QuaternionInteger(1)
  39. for bit in (n.digits(2)) {
  40. c *= x if bit
  41. x *= x
  42. }
  43. return c
  44. }
  45. __CLASS__.alias_method(:pow, '**')
  46. method powmod(Number n, Number m) {
  47. var x = self
  48. var c = QuaternionInteger(1)
  49. for bit in (n.digits(2)) {
  50. (c *= x) %= m if bit #=
  51. (x *= x) %= m #=
  52. }
  53. return c
  54. }
  55. }
  56. # Integers (a,b) such that a^2 - a*b + b^2 give the powers of 7.
  57. with (QuaternionInteger(1,2,3,4)) {|q|
  58. say 15.of { q.pow(_).a } #=> [1, 1, -28, -86, 668, 3916, -12208, -141896, 82448, 4421776, 6370112, -119913056, -430929472, 2735532736, 18398949632]
  59. say 15.of { q.pow(_).b } #=> [0, 2, 4, -52, -224, 1112, 8944, -15472, -299264, -134368, 8709184, 21449408, -218376704, -1080235648, 4390829824]
  60. say 15.of { q.pow(_).c } #=> [0, 3, 6, -78, -336, 1668, 13416, -23208, -448896, -201552, 13063776, 32174112, -327565056, -1620353472, 6586244736]
  61. say 15.of { q.pow(_).d } #=> [0, 4, 8, -104, -448, 2224, 17888, -30944, -598528, -268736, 17418368, 42898816, -436753408, -2160471296, 8781659648]
  62. }
  63. var n = lcm(1..20)
  64. var m = (2**64 + 1)
  65. with (QuaternionInteger(2,3,4,5)) {|q|
  66. var r = q.powmod(n, m)
  67. say gcd(r.b, m) #=> 274177
  68. say gcd(r.c, m) #=> 274177
  69. say gcd(r.d, m) #=> 274177
  70. }