sebastiano.tronto.net

Source files and build scripts for my personal website
git clone https://git.tronto.net/sebastiano.tronto.net
Download | Log | Files | Refs | README

ecm.md (11772B)


      1 # Elliptic curves and JavaScript
      2 
      3 At my company we regularly have talks and other knowledge events.
      4 After attending many of these events, I decided to give a talk
      5 about [elliptic curves](https://en.wikipedia.org/wiki/Elliptic_curve),
      6 which I worked with during my PhD.
      7 
      8 The intended audience consists of software developers, but their
      9 background is mixed: some have studied Maths in university, but many did
     10 not. Most are not familiar with abstract algebra other than polynomials
     11 and matrices, let alone algebraic geometry. Considering all of this,
     12 I decided to give a presentation about
     13 [Lenstra elliptic curve factorization](https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization),
     14 so I could also show some code and do a practical demo.
     15 
     16 Since I gave a presentation on this topic to a different audience a
     17 couple of years ago, I could have simply adapted the slides and used the
     18 same code.  Instead, I took this as an opportunity to experiment with
     19 new tools and languages. This post is a summary of what I have learned
     20 while preparing this talk.
     21 
     22 All the code I talk about in this post, including the source for the
     23 slides, can be found in [this git repository](https://git.tronto.net/ecm).
     24 
     25 ## The code
     26 
     27 For the practical part of the talk I had to write some code to demonstrate
     28 the factorization algorithm. It's not much, maybe 200 lines or so, and
     29 I already had a working Python version. It was a rather straightforward
     30 implementation, and it used exceptions to handle the "a factor was found"
     31 part of the algorithm; although this is not amazing coding style, it
     32 was faithful to how the algorithm was originally explained - or to how
     33 I wanted to explain it, anyway.
     34 
     35 It was not bad code, but I wanted to experiment with something new.
     36 
     37 ### Adventures in C++
     38 
     39 Recently I have been learning C++, and I wanted to experiment with some
     40 of its more advanced features. So I decided to rewrite the whole thing.
     41 
     42 I had a clear idea of where I wanted to start: a small
     43 [library for modular arithmetic](https://git.tronto.net/zmodn/file/README.md.html),
     44 with compile-time fixed
     45 [modulus](https://en.wikipedia.org/wiki/Modular_arithmetic) via templates
     46 and heavy use of
     47 [type inference](https://en.wikipedia.org/wiki/Type_inference)
     48 for seamless operations between regular integers and integers modulo N.
     49 This endeavor was quite successful, and it taught me how to use
     50 templates and concepts, which I have talked about in
     51 [my previous blog post](../2025-01-21-taming-cpp-templates).
     52 
     53 When working on the previous part, I made sure that any kind of integer
     54 could be used as a base type for the modular integers, so I could use
     55 some custom big integer types to show off the power of the factorization
     56 algorithm with very large numbers. Unfortunately, I did not take into
     57 account that with my setup I needed a big integer class that supported
     58 *compile-time constants* - for example in the form of `constexpr`
     59 constructors. I could not find any, so I decided to write
     60 [my own big integer class](https://git.tronto.net/zmodn/file/bigint.h.html).
     61 This was less successful: implementing an *efficient* big integer library
     62 was not as straightforward as the modular integers library. I decided
     63 not to care about efficiency for the time being, but that would come
     64 back to bite me very soon.
     65 
     66 Finally, I put these two libraries together and implemented the elliptic
     67 curve factorization algorithm. This was not hard.  The only problem was
     68 that it was excruciatingly slow when I used large numbers, undoubtedly
     69 due to my half-assed big integer implementation.  I could restrict
     70 myself to using regular 64-bit integers, but then I would have to use
     71 to relatively small numbers, making the demo less interesting.  I looked
     72 online for other big integer libraries that I could use and I found
     73 [ctbignum](https://github.com/niekbouman/ctbignum), but I could not make
     74 it work together with my modular arithmetic class. The day of the
     75 presentation was approaching quickly, so I decided to go back to
     76 my original Python implementation instead.
     77 
     78 ### Back to Python
     79 
     80 When I looked back at my old Python implementation, I found it nicer
     81 and cleaner than how I remembered it. I did not have to do much
     82 cleanup, it was pretty much ready to go, and much more readable than
     83 the C++ verion for anyone who is not a C++ expert - and probably for C++
     84 experts too. Moreover, Python's seamless use of large integers was
     85 exactly what I was missing from the C++ version.
     86 
     87 One of the few changes I made to this code was reworking a little bit
     88 the "elliptic curve point" class I used. If anything, this was a good
     89 excuse to learn about
     90 [dataclasses](https://docs.python.org/3/library/dataclasses.html). I also
     91 decided to add
     92 [type hints](https://docs.python.org/3/library/typing.html), which I
     93 have recently found out about.
     94 
     95 And with little work, the old code was ready to go!
     96 
     97 ## The slides
     98 
     99 Compared to the code, the slides needed a few more adjustments.
    100 When I gave this talk the first time, it was for an audience of
    101 Math students at the end of their Bachelor program. I could freely
    102 use all that Math jargon that we Mathematicians like, such as
    103 "let K be a
    104 [field](https://en.wikipedia.org/wiki/Field_(mathematics))"
    105 and "E is a
    106 [projective](https://en.wikipedia.org/wiki/Projective_space) curve".
    107 But this time I had to phrase things differently. The content itself
    108 didn't need much change, but I had to use a more approachable language,
    109 at the cost of being a little less rigorous. For example, I could
    110 get rid of all the projective plane business by just saying "let's
    111 pretend that there is a point *at infinity*; trust me, the Math
    112 works out".
    113 
    114 The problem with changing the old slides is that I did not want to touch
    115 [LaTeX](https://nl.wikipedia.org/wiki/LaTeX)
    116 anymore. As a Mathematician I like it because it can do pretty much everything
    117 you need (did you know you can
    118 [draw diagrams programmatically](https://www.youtube.com/watch?v=mWqhB6qOIk0)?),
    119 but as a computer scientist I'd rather not deal with the mess that is a
    120 LaTeX installation.
    121 So what did I decide to use instead? HTML, CSS and a bit of JavaScript!
    122 
    123 ### Math formulas with MathJax
    124 
    125 Even without LaTeX, I still needed a way to write Math formulas in my
    126 slides. One way to achieve this is using [MathJax](https://www.mathjax.org),
    127 which allows you to write LaTeX or
    128 [MathML](https://en.wikipedia.org/wiki/MathML) formulas direclty in
    129 your HTML, and have them rendered dynamically. A minimal example
    130 looks like this:
    131 
    132 ```
    133 <!doctype html>
    134 <head>
    135 	<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
    136 	</script>
    137 </head>
    138 
    139 <body>
    140 	<p>Hello! \[ e^{\pi i} + 1 = 0 \]</p>
    141 </body>
    142 ```
    143 
    144 In the example above I am including the MathJax library directly from a
    145 URL. This means every time you load that page, a request is sent from
    146 your browser to the MathJax server to get the code for rendering the
    147 formulas. Among other things, this implies that my slides are going
    148 to be dependent on this external website, and that they won't work
    149 offline. The horror!
    150 
    151 In theory I could install MathJax locally (or on my server) and get rid
    152 of this dependency, and maybe at some point I'll do it. But for now
    153 it is just easier and faster to include the script like this. And while
    154 I was at it, I doubled down on the remote library thing and included 
    155 also [highlight.js](https://highlightjs.org),
    156 a package for rendering code blocks with syntax highlighting.
    157 
    158 ### Scrolling with JavaScript
    159 
    160 The other big feature I wanted for the slides was for them to look and
    161 behave like actual slides. So the whole HTML page should be divided into
    162 single frames, and I wanted to be able to move back and forth between
    163 frames by clicking or pressing a key.
    164 
    165 In order to do this, I had to write my first piece of JavaScript.
    166 The main part looks more or less like this:
    167 
    168 ```
    169 const slides = document.querySelectorAll(".slide");
    170 
    171 const keysNext = ["ArrowRight", "ArrowDown", " "];
    172 const keysPrev = ["ArrowLeft", "ArrowUp"];
    173 
    174 // Disable default action of the navigation keys (e.g. scrolling).
    175 document.addEventListener("keydown", function(e) {
    176 	if (keysNext.includes(e.key) || keysPrev.includes(e.key)) {
    177 		e.preventDefault();
    178 	}
    179 });
    180 
    181 function goto(slide) {
    182 	slide.focus();
    183 	slide.scrollIntoView({
    184 		behavior: "instant",
    185 		block: "start"
    186 	});
    187 }
    188 
    189 function onkeydown(i, e) {
    190 	if (keysNext.includes(e.key) && i+1 < slides.length) {
    191 		goto(slides[i+1]);
    192 	}
    193 	if (keysPrev.includes(e.key) && i > 0) {
    194 		goto(slides[i-1]);
    195 	}
    196 }
    197 
    198 function onclick(i, e) {
    199 	const w = slides[i].offsetWidth;
    200 	const x = e.clientX;
    201 
    202 	if (x > w/2 && i+1 < slides.length) {
    203 		goto(slides[i+1]);
    204 	}
    205 	if (x < w/2 && i > 0) {
    206 		goto(slides[i-1]);
    207 	}
    208 }
    209 
    210 for (let i = 0; i < slides.length; i++) {
    211 	slides[i].addEventListener("keydown", e => onkeydown(i, e));
    212 	slides[i].addEventListener("click", e => onclick(i, e));
    213 }
    214 
    215 goto(slides[0]); // Go to the first slide when the presentation starts
    216 ```
    217 
    218 First of all, every slide is a `div` with `class="slide"`. This allows
    219 me to select all the slides with `document.querySelectorAll(".slide")`.
    220 Then, after disabling any default handling of the arrows and space keys,
    221 I add a new event listeners to every slide. These listeners uses the
    222 `scrollIntoView()` function to scroll to the next or previous slide.
    223 The `onclick()` function similarly handles clicks, where a click on the
    224 left half of the screen goes to the previous slide and a click on the
    225 right half goes to the next one.
    226 
    227 And by the way, highjacking the default scrolling behavior is another
    228 trend of modern web development that I hate. By I am fine with using
    229 it here, because these slides are not meant to be a regular web page.
    230 
    231 I also a function to add a footer to every slide:
    232 
    233 ```
    234 function slideFooter() {
    235 	const start = "<div class=\"footer\"><table class=\"footer-table\"><tr>";
    236 	const title = "Elliptic Curves and the ECM algorithm"
    237 	const link = "<a href=https://tronto.net/talks/ecm>tronto.net/talks/ecm</a>";
    238 	const end = "</tr></table></div>";
    239 	const content =
    240 		"<td class=\"footer-title\">" + title + "</td>" +
    241 		"<td class=\"footer-link\">" + link + "</td>";
    242 
    243 	return start + content + end;
    244 }
    245 
    246 // In the main loop:
    247 // slides[i].innerHTML += slideFooter()
    248 ```
    249 
    250 In an older version I also had a small slide counter in the footer,
    251 but I decided not to use it in the end.
    252 
    253 Of course there was also some CSS work to
    254 do. A new thing I learned in this regard is the
    255 [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
    256 layout property, with which I was able to easily arrange
    257 pieces of text and pictures in the slides - shoutout to
    258 my friend [Jared](https://guissmo.com) for telling me about
    259 it. Apart from this I don't have anything interesting to comment
    260 about the CSS part of the slides. You can check the full code
    261 [here](https://git.tronto.net/ecm/file/index.html.html) if you want;
    262 everything is in a single HTML file.
    263 
    264 The result looks fine, but it does not work perfectly will every screen
    265 resolution. It's fine in 4:3 or 16:9, but with wider screens your
    266 mileage may vary. I could improve it and always use the device height
    267 (or width, but not both) as a reference. But this is quite some work
    268 for very little gain, and in the end all I care about is that I can
    269 show these slides from my laptop. I am sorry if you are viewing this
    270 presentation from a smartphone.
    271 
    272 You can view the slides
    273 [on this page](https://sebastiano.tronto.net/talks/ecm).
    274 
    275 ## Conclusion
    276 
    277 I didn't need to do all this work for this presentation, but it was fun to
    278 learn new stuff - not only for the C++ part, that I did not end up using
    279 anyway, but also for the slides. It's good to know a bit of JavaScript,
    280 even if I don't plan to use it much in the future.
    281 
    282 I scheduled this post to go online on the same day as my presentation -
    283 wish me good luck :)