elliptic_curve_arithmetic.sf 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Elliptic_curve_arithmetic
  4. #
  5. module EC {
  6. var A = 0
  7. var B = 7
  8. class Horizon {
  9. method to_s {
  10. "EC Point at horizon"
  11. }
  12. method *(_) {
  13. self
  14. }
  15. method -(_) {
  16. self
  17. }
  18. }
  19. class Point(Number x, Number y) {
  20. method to_s {
  21. "EC Point at x=#{x}, y=#{y}"
  22. }
  23. method neg {
  24. Point(x, -y)
  25. }
  26. method -(Point p) {
  27. self + -p
  28. }
  29. method +(Point p) {
  30. if (x == p.x) {
  31. return (y == p.y ? self*2 : Horizon())
  32. }
  33. else {
  34. var slope = (p.y - y)/(p.x - x)
  35. var x2 = (slope**2 - x - p.x)
  36. var y2 = (slope * (x - x2) - y)
  37. Point(x2, y2)
  38. }
  39. }
  40. method +(Horizon _) {
  41. self
  42. }
  43. method *((0)) {
  44. Horizon()
  45. }
  46. method *((1)) {
  47. self
  48. }
  49. method *((2)) {
  50. var l = (3 * x**2 + A)/(2 * y)
  51. var x2 = (l**2 - 2*x)
  52. var y2 = (l * (x - x2) - y)
  53. Point(x2, y2)
  54. }
  55. method *(Number n) {
  56. 2*(self * (n>>1)) + self*(n % 2)
  57. }
  58. }
  59. class Horizon {
  60. method +(Point p) {
  61. p
  62. }
  63. }
  64. class Number {
  65. method +(Point p) {
  66. p + self
  67. }
  68. method *(Point p) {
  69. p * self
  70. }
  71. method *(Horizon h) {
  72. h
  73. }
  74. method -(Point p) {
  75. -p + self
  76. }
  77. }
  78. }
  79. say var p = with(1) {|v| EC::Point(v, sqrt(abs(1 - v**3 - EC::A*v - EC::B))) }
  80. say var q = with(2) {|v| EC::Point(v, sqrt(abs(1 - v**3 - EC::A*v - EC::B))) }
  81. say var s = (p + q)
  82. var bool = (abs((p.x - q.x)*(-s.y - q.y) - (p.y - q.y)*(s.x - q.x)) < 1e-20)
  83. say "checking alignment: #{bool}"
  84. assert_eq(bool, true)