-
Notifications
You must be signed in to change notification settings - Fork 0
/
point.rb
77 lines (64 loc) · 1.66 KB
/
point.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class Point
attr_reader :x, :y, :a, :b, :y_2, :x_3, :ax
def initialize(x:, y:, a:, b:)
@x = x
@y = y
@a = a
@b = b
@y_2 = y ** 2
@x_3 = x ** 3
@ax = a * x
unless point_on_curve?
raise 'Point provided must be on the curve: y_2 = x_3 + ax + b'
end
end
def ==(comparand)
(x == comparand.x) &&
(y == comparand.y) &&
(a == comparand.a) &&
(b == comparand.b)
end
def +(summand)
# self + I == self
return self if summand.zero?
# summand + I == summand
return summand if self.zero?
# P + (-P) == I
return point_at_infinity if (x == summand.x) && (-y == summand.y)
slope = if x == summand.x && y == summand.y
# dy/dx of y_2 == x_3 + ax + b
(3 * x**2 + a)/(2 * y)
elsif x != summand.x
# Slope of line between the two points.
(y - summand.y)/(x - summand.x)
end
# Find where the line intersects the curve at a third point.
x_at_third_intersection = slope**2 - summand.x - x
y_at_third_intersection = slope * (x_at_third_intersection - summand.x) + summand.y
# Find the inverse point
inverse_of_y_at_third_intersection = -y_at_third_intersection
Point.new(x: x_at_third_intersection,
y: inverse_of_y_at_third_intersection,
a: a,
b: b)
end
def *(int)
result = 0
int.times { result = result + self }
result
end
def point_on_curve?
@_point_on_curve ||= (
y_2 == x_3 + ax + b
)
end
def zero?
false
end
def -@
Point.new(x: x,
y: -y,
a: a,
b: b)
end
end