| 1 | %% Elliptic curve messing about |
| 2 | |
| 3 | %% y^2 = x^3 + a x^2 + b |
| 4 | |
| 5 | numeric u, v; |
| 6 | numeric a, b; |
| 7 | numeric minx, maxx, miny, maxy; |
| 8 | transform gt; |
| 9 | pair O; |
| 10 | %% prologues := 1; |
| 11 | a = -2; b = 1; |
| 12 | scale = 2 cm; |
| 13 | labeloffset := 6 pt; |
| 14 | |
| 15 | ahlength := 2 mm; |
| 16 | ahangle := 30; |
| 17 | |
| 18 | O = (0, 0); |
| 19 | |
| 20 | vardef ecy(expr x) = sqrt (x*x*x + a*x + b) enddef; |
| 21 | vardef ecadd(expr u, v) = |
| 22 | numeric ux, uy, vx, vy; |
| 23 | numeric dx, dy; |
| 24 | numeric m; |
| 25 | ux := xpart u; uy = ypart u; |
| 26 | vx := xpart v; vy = ypart v; |
| 27 | if ux = vx: |
| 28 | m := (3*ux*ux + a)/(2*uy); |
| 29 | else: |
| 30 | m := (vy - uy)/(vx - ux); |
| 31 | fi |
| 32 | dx := m**2 - ux - vx; |
| 33 | dy := m * (ux - dx) - uy; |
| 34 | (dx, dy) |
| 35 | enddef; |
| 36 | |
| 37 | minx = -2; maxx = 3; |
| 38 | maxy = ecy(maxx); miny = -maxy; |
| 39 | u = 7/5 cm; |
| 40 | v = u * (maxx - minx)/(maxy - miny); |
| 41 | gt = identity xscaled u yscaled v shifted (10 cm, 10 cm); |
| 42 | |
| 43 | vardef eclabel@#(expr l, z) = |
| 44 | pickup pencircle scaled 1/4 pt; |
| 45 | draw fullcircle scaled 1 mm shifted (z transformed gt); |
| 46 | draw thelabel@#(l, z transformed gt); |
| 47 | enddef; |
| 48 | |
| 49 | vardef drawcurve = |
| 50 | boolean ok; |
| 51 | path p; |
| 52 | numeric t; |
| 53 | pickup pencircle scaled 1/4 pt; |
| 54 | drawarrow ((minx, 0) -- (maxx, 0)) transformed gt; |
| 55 | drawarrow ((0, miny) -- (0, maxy)) transformed gt; |
| 56 | ok := false; |
| 57 | pickup pencircle scaled 2/3 pt; |
| 58 | for x = minx step 0.01 until maxx: |
| 59 | t := x*x*x + a*x + b; |
| 60 | if t >= 0: |
| 61 | y := sqrt t; |
| 62 | if ok: |
| 63 | p := p .. (x, y); |
| 64 | else: |
| 65 | p := (x, y); |
| 66 | fi |
| 67 | ok := true; |
| 68 | else: |
| 69 | if ok: |
| 70 | draw (reverse p reflectedabout (O, O + right) .. p .. cycle) |
| 71 | transformed gt; |
| 72 | fi |
| 73 | ok := false; |
| 74 | fi |
| 75 | endfor |
| 76 | if ok: |
| 77 | draw (reverse p reflectedabout (O, O + right) .. p) transformed gt; |
| 78 | fi |
| 79 | enddef; |
| 80 | |
| 81 | vardef setbackground(expr c) = |
| 82 | save bboxmargin; |
| 83 | picture pic; |
| 84 | bboxmargin := 1/2 cm; |
| 85 | pic := currentpicture; |
| 86 | currentpicture := nullpicture; |
| 87 | fill (bbox pic) withcolor c; |
| 88 | draw pic; |
| 89 | enddef; |
| 90 | |
| 91 | beginfig(0); |
| 92 | drawcurve; |
| 93 | x0 := -5/4; x1 := 1/4; |
| 94 | y0 := -ecy(x0); y1 := ecy(x1); |
| 95 | z2 = ecadd(z0, z1); |
| 96 | x3 := x2; y3 := -y2; |
| 97 | pickup pencircle scaled 1/4 pt; |
| 98 | draw ((-0.1)[z0, z3] -- 1.1[z0, z3]) transformed gt dashed evenly; |
| 99 | draw ((-0.1)[z2, z3] -- 1.1[z2, z3]) transformed gt dashed evenly; |
| 100 | eclabel.bot(btex $P_0$ etex, z0); |
| 101 | eclabel.top(btex $P_1$ etex, z1); |
| 102 | eclabel.rt(btex $P'$ etex, z3); |
| 103 | eclabel.lft(btex $P_2 = -P' = P_0 + P_1$ etex, z2); |
| 104 | setbackground(white); |
| 105 | endfig; |
| 106 | |
| 107 | beginfig(1); |
| 108 | drawcurve; |
| 109 | x0 := -18/16; |
| 110 | y0 = ecy(x0); |
| 111 | z1 = ecadd(z0, z0); |
| 112 | x2 := x1; y2 := -y1; |
| 113 | pickup pencircle scaled 1/4 pt; |
| 114 | draw ((-0.1)[z0, z2] -- 1.1[z0, z2]) transformed gt dashed evenly; |
| 115 | draw ((-0.1)[z2, z1] -- 1.1[z2, z1]) transformed gt dashed evenly; |
| 116 | eclabel.top(btex $P_0$ etex, z0); |
| 117 | eclabel.rt(btex $P'$ etex, z2); |
| 118 | eclabel.lft(btex $P_1 = -P' = 2 P_0$ etex, z1); |
| 119 | setbackground(white); |
| 120 | endfig; |
| 121 | |
| 122 | beginfig(2); |
| 123 | drawcurve; |
| 124 | x0 := 5/2; |
| 125 | y0 = ecy(x0); |
| 126 | x1 := x0; y1 := -y0; |
| 127 | pickup pencircle scaled 1/4 pt; |
| 128 | draw ((x0, miny) -- (x0, maxy)) transformed gt dashed evenly; |
| 129 | eclabel.rt(btex $P_0$ etex, z0); |
| 130 | eclabel.rt(btex $P_1$ etex, z1); |
| 131 | setbackground(white); |
| 132 | endfig; |
| 133 | |
| 134 | end; |