module EC {
var A = 0
var B = 7
class Horizon {
method to_s {
"EC Point at horizon"
}
method *(_) {
self
}
method -(_) {
self
}
}
class Point(Number x, Number y) {
method to_s {
"EC Point at x=#{x}, y=#{y}"
}
method neg {
Point(x, -y)
}
method -(Point p) {
self + -p
}
method +(Point p) {
if (x == p.x) {
return (y == p.y ? self*2 : Horizon())
}
else {
var slope = (p.y - y)/(p.x - x)
var x2 = (slope**2 - x - p.x)
var y2 = (slope * (x - x2) - y)
Point(x2, y2)
}
}
method +(Horizon _) {
self
}
method *((0)) {
Horizon()
}
method *((1)) {
self
}
method *((2)) {
var l = (3 * x**2 + A)/(2 * y)
var x2 = (l**2 - 2*x)
var y2 = (l * (x - x2) - y)
Point(x2, y2)
}
method *(Number n) {
2*(self * (n>>1)) + self*(n % 2)
}
}
class Horizon {
method +(Point p) {
p
}
}
class Number {
method +(Point p) {
p + self
}
method *(Point p) {
p * self
}
method *(Horizon h) {
h
}
method -(Point p) {
-p + self
}
}
}
say var p = with(1) {|v| EC::Point(v, sqrt(abs(1 - v**3 - EC::A*v - EC::B))) }
say var q = with(2) {|v| EC::Point(v, sqrt(abs(1 - v**3 - EC::A*v - EC::B))) }
say var s = (p + q)
say ("checking alignment: ", abs((p.x - q.x)*(-s.y - q.y) - (p.y - q.y)*(s.x - q.x)) < 1e-20)
Output:
EC Point at x=1, y=2.64575131106459059050161575363926042571025918308
EC Point at x=2, y=3.74165738677394138558374873231654930175601980778
EC Point at x=-1.79898987322333068322364213893577309997540625528, y=0.421678696849803028974882458314430376814790014487
checking alignment: true