X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fdocuments.git;a=blobdiff_plain;f=irc%2F%23ipdf.log;h=4c414215acf0746810a44c18e2ddd024d97508e0;hp=4df7d54f15362686f1e06e8284c9837b2c167166;hb=b4b47317861fac274b98877486bbba4de2419246;hpb=7405135393cd483690c441d40db21f5172b8a16f diff --git a/irc/#ipdf.log b/irc/#ipdf.log index 4df7d54..4c41421 100644 --- a/irc/#ipdf.log +++ b/irc/#ipdf.log @@ -1716,3 +1716,347 @@ 21:40 <@matches> Of course we are restricted by the zoom in the pdf viewer... 21:41 <@matches> This project is too meta 21:41 <@matches> It is doing my head in +--- Day changed Fri May 23 2014 +11:22 < sulix> Welp. Submitting this version: http://davidgow.net/stuff/LitReviewDavid.pdf +11:23 < sulix> (The introduction has only got more over the top, I'm afraid) +11:48 < sulix> Do you know what is happening/isn't happening RE: Revised project proposals? +12:03 < sulix> Well: Literature review is submitted. +12:03 < sulix> (In person to the coordinator, which is a little bit scary) +--- Day changed Sun May 25 2014 +15:42 <@matches> No meeting tomorrow by the way +15:43 < sulix> Ah. Cool. I have like 300 things to do. +15:43 < sulix> Just pushed fixes for all of the compile warnings, btw. +15:43 <@matches> Cool +15:44 <@matches> I want to keep editing my Lit Review :S +15:44 < sulix> I had thought that Float() always returns a "float", but it sometimes returns a double. +15:44 <@matches> Oh +15:44 <@matches> Whoops +15:44 <@matches> Well a double is technically still a float... +15:44 < sulix> (Also, it turns out OpenGL actualy breaks the C++ spec, and is therefore impossible to use without hacks if you have -Werror enabled) +15:45 <@matches> Sigh +15:45 < sulix> It was warning that I was losing precision from float x = Float(blah); +15:45 <@matches> One of the things I want to put in my lit review is a snarky paragraph about how no one actually obeys standards anyway +15:46 < sulix> There are points where you get function pointers as void* pointers, but C++ needs to work on systems where code and data are stored in different bits of memory with different size pointers. +15:46 <@matches> On the other hand no matter how much better I make the lit review no one will read it because I'm being assessed on a conference paper not a dissertation +15:46 <@matches> Ah +15:46 < sulix> So casting any data pointer to a function pointer is apparently illegal. +15:47 <@matches> That's annoying +15:47 < sulix> Fortunately, gcc doesn't complain if you start the line that does it with "__extension__", so that's what we do. +15:47 <@matches> Haha +15:54 <@matches> Ok I am still about 3 days behind on sleep but I guess I should do work +15:54 <@matches> Bye +--- Day changed Tue May 27 2014 +12:49 <@matches> We missed the Computable Document Format (CDF) by Mathematica by the way +12:49 <@matches> Wolfram would be offended +12:50 * matches hopes none of the Mathematica fanatics read the lit review +12:50 <@matches> Or this channel +12:54 <@matches> I did have both Mathematica and IPython as a dot point and they got the mighty question mark of confusion over them +12:54 <@matches> Maybe I'll add them in later +12:55 <@matches> Frames does not seem to agree with my assertion that practically anything can be considered a document format :P +12:55 <@matches> Plain text! +12:57 <@matches> So I was looking through last year's Mech/Chem final year conference +12:57 <@matches> Naturally there is nothing remotely like this project in there +12:57 <@matches> :( +--- Log opened Tue Jun 10 13:59:54 2014 +13:59 -!- matches [matches@motsugo.ucc.gu.uwa.edu.au] has joined #ipdf +13:59 -!- Irssi: #ipdf: Total of 2 nicks [1 ops, 0 halfops, 0 voices, 1 normal] +13:59 -!- Irssi: Join to #ipdf was synced in 3 secs +16:29 -!- mode/#ipdf [+o matches] by OperServ +--- Day changed Wed Jun 11 2014 +13:13 <@matches> JVB just asked me if it was possible to have a self updating pdf +13:13 <@matches> I suppose he didn't ask whether it would be easy +13:15 <@matches> As in, one that would download itself if there was a newer version +13:16 <@matches> Technically with the crippled PostScript it would be "No" but with all that stuff in the standard about DRM and "Action Objects" and Javascript and stuff... +13:18 <@matches> Hmm, a webserver running git and a cronjob and requiring authentication may solve his problem +13:18 <@matches> With pdf.js or just relying on browsers to have pdf plugins +13:18 <@matches> Wait why am I solving JVB's problem +--- Day changed Fri Jun 13 2014 +16:31 <@matches> So exams have finished +16:31 <@matches> Well my exams have finished +16:32 <@matches> Now I can go back to panicking about the project again +16:37 <@sulix> Excellent: it's your turn to do something impressive for the meeting on Monday, then. :P +--- Day changed Mon Jun 16 2014 +14:49 <@matches> Some of this OpenGL stuff doesn't quite add up +14:49 <@matches> Like m_cahed_display.UnBind(); m_cached_display.Blit(); +14:50 <@matches> Oh +14:50 <@matches> I see +14:50 <@matches> There is a difference +14:51 * matches -> OpenGL documentation +14:53 <@matches> Right I see +15:03 <@matches> Well, this makes a lot more sense than tpg's "Adventures in VEMS" in #ucc at least +15:18 <@sulix> Well that's an achievement, I guess. +15:18 <@sulix> Also http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf +15:18 <@sulix> It's the spec for "nullptr"... +15:20 <@matches> "Pointers are pretty cool. Pointers that are NULL are pretty cool. We address these issues by proposing nullptr" ? +15:21 <@sulix> Haha: Pretty much. +15:22 <@matches> Why not just reserve the word "null" +15:22 <@matches> I could get behind it then +15:23 <@matches> It is not a null reference +15:23 <@matches> But if you ever have a null reference something is horrifyingly wrong +15:23 <@matches> Bah humbug +15:24 <@sulix> They have a page about that where they said "everyone was naming their variables \"null\"". +15:24 * sulix realises he just escaped those quote. Oh dear. +15:24 <@matches> A valid point, which should have lead to "Everyone are morons" +15:24 <@matches> Fun fact +15:25 <@matches> Matlab (like fortran actually) will let you use key words as variable names. +15:25 <@sulix> "It's a feature!" +15:25 <@matches> Question on CITS2401 exam: "Why is 'ii' preferred over 'i' and 'jj' over 'j' for loop iteration?" +15:26 <@matches> Both i and j are the complex number sqrt(-1) +15:27 <@matches> It seems like naming it 'nullptr' instead of 'null' missed an opportunity to stop people naming their variables really confusing things :P +15:30 <@matches> Well I am infinitely wiser about nullptr now but I don't think it will stop me just using NULL +16:15 <@matches> This is slowly starting to make sense +16:35 <@matches> I'm having a bit of difficulty because it's all so optimised for the GPU +16:35 <@matches> I think what we need is an ObjectRenderer class or similar +16:36 <@matches> Have one for each type of object and implement RenderUsingGPU and RenderUsingCPU +16:36 <@matches> I will see what monstrosity I can come up with +16:36 <@matches> But a lot of that code for the circles and rectangles is exactly the same just copied and pasted with different variable names +16:37 <@matches> I think there is an official software engineering term for that sort of thing... +16:46 <@matches> Alright, breaking everything +16:46 <@matches> This will probably take a while +16:47 * matches dreads merges +17:02 <@sulix> Yeah, I was going to basically end up with an ObjectRenderer class, too. +17:02 <@sulix> So I'll leave it to you for now and procrasinate from doing my maths in some other way. +17:07 <@matches> Cool :) +17:52 <@matches> Now I'm not very strict about the whole RAII thing myself, but there seem to be some cases where things can probably just go in the constructor? +17:52 <@matches> I guess we can fight about those later +17:54 <@matches> I guess I can see us wanting to set m_render_inited to false and have it automatically recreate everything, maybe, but I can't see a case where we will want to recompile the shaders, so I am going to put the shader initialisation in the constructors +17:54 <@matches> I have gone mad with power +17:54 <@matches> Maaad +20:30 <@matches> This ObjectRenderer is like a two headed hydra +20:31 <@matches> I thought about using just the ibo and vbo and getting the indices out of it, but that's a bit terrible +20:31 <@matches> So it will have an ibo for the GPU and an array for the CPU +20:35 * sulix thinks this makes sense. +21:47 <@matches> Good news! I have things on the screen. Bad news. They are still on the GPU and they are wrong. +21:49 <@matches> More coffee required... +21:58 <@matches> Not sure if code wrong or fglrx having an existential crisis +22:04 <@matches> Unrelated to the segfaults of doom, but I just realised that there's all this interest in using GPUs for scientific computation, and everything seems to point to them having vastly inferior floating point computation to a CPU, which is a bit disconcerting +22:05 <@matches> I imagine the OpenCL libraries etc actually use the IEEE floating point capabilities? I hope? +22:05 * matches files under "beyond the scope of project" +22:06 <@sulix> If you commit code I can test it on non-fglrx if that'll help. +22:06 <@matches> I'd rather not commit it just yet, I am 90% sure it is something I have done wrong and don't want to shame myself by committing broken code +22:06 <@matches> It'd be like vomiting all over the codebase +22:07 * sulix is pretty sure half of his commits broke something. +22:29 <@matches> Ok I committed stuff that should in theory work with the test pattern again +22:30 <@matches> Using new and improved ObjectRenderer classes +22:30 <@matches> For some definition of improved +22:30 <@matches> It doesn't actually use the CPU yet +22:30 <@matches> It'll get there +22:33 <@matches> You can go and add your MandleBrotSetRenderer now though :P +22:36 <@sulix> Cool. +22:37 <@sulix> The circles do trigger that intel driver bug again, though... +22:38 <@matches> Ah damn +22:38 <@matches> Would making CIRCLE_FILLED the first ObjectType fix that? +22:38 <@sulix> It does. +22:38 <@sulix> (I just checked) +22:38 <@sulix> Yay intel! +22:39 <@matches> Haha +22:49 <@matches> Hey, does our rendering approach completely break compositing? +22:49 <@matches> Render all circles +22:49 <@matches> Then render all rectangles... +22:49 <@matches> There's no depth... +22:49 <@sulix> Um, maybe. +22:49 <@matches> :P +22:49 <@matches> I was just worrying about how to make compositing work using the CPU +22:49 <@matches> and then I realised it won't work using the GPU as it is either +22:50 <@sulix> If we're not doing alpha-blending, we could just add a z-coordinate and use the z-buffer. +22:50 <@sulix> Otherwise, they need to be sorted if they intersect. +22:50 <@matches> Let's not worry about this for now... +22:50 <@matches> Even though I spent a rather significant part of my lit review explaining how awesome compositing is +22:51 <@matches> I guess it doesn't matter, clearly the lit review was not intended for anyone to actually read +23:42 <@matches> I suspect RenderPixels doesn't work +23:45 <@sulix> This may be the case. +--- Day changed Tue Jun 17 2014 +01:05 <@matches> Behold the magnificence of CPU based rendering +01:06 <@matches> In which we pass a massive pixel array to the ObjectRenderer's and just save it to a BMP +01:06 <@matches> Because OpenGL +01:06 <@matches> I'll probably fix it later +01:11 <@matches> Whoops seg faults ahoy +01:12 <@matches> Wait I swear it wasn't segfaulting before I commited that +01:19 <@matches> It segfaults sometimes depending on where you have the view. If you just have one circle and zoom in you can see the amazingly less jagged looking lines. +01:19 <@matches> That, is a certified result +10:13 <@sulix> I got the CPU rendered version to show up on the screen. +10:14 <@sulix> RenderPixels was pretty broken. +10:38 <@matches> Nice +10:39 <@sulix> I think the segfaults are it trying to draw outside of the display. +10:39 <@matches> Yeah +10:39 <@sulix> I haven't managed to zoom in too much yet. +10:39 <@matches> My clipping is probably wrongish +10:40 <@matches> fonttex_frag.glsl? Fear +10:40 <@sulix> Yeah, the "basictex_frag" file did a bunch of pretty font-specific things. +10:40 <@matches> Ah +10:43 <@sulix> The CPU renderer also shows some random lines when there are no outlines on the screen. +10:43 <@matches> Is it just me or does it look slightly nicer on the CPU when zoomed out a bit +10:44 <@matches> Well it looks different +10:44 <@matches> I can't quite work out whether it looks nicer or worse :P +10:44 <@sulix> Okay, it doesn't segfault if the rectangle outlines are disabled. +10:45 <@matches> Ah +10:45 <@matches> Yeah it is setting top/bottom/left/right outside the pixels +10:45 <@sulix> I think there are just some slightly different edge-case rules when zoomed out. +10:47 <@matches> With my skills at writing renderers I should be working on the fglrx drivers +10:47 <@matches> :P +10:47 <@sulix> Things vanish if you zoom in too much, too. +10:48 <@matches> Blame it on floats +10:49 <@matches> The CPU renderer is using a width of 1 pixel less than it should be +10:49 <@sulix> Why are the floats sinking? :P +10:49 <@matches> That's unrelated +10:49 <@matches> It's probably an integer rounding issue somewhere +10:49 <@matches> When the view gets big something goes to zero +10:50 <@matches> The CPU renderer transforms everything to pixel positions and then renders using those +11:02 <@matches> The GPU renderer occassionally leaves off the corners of things +11:02 <@matches> I never noticed before +11:02 <@matches> Anyway I think the segfaults are fixed +11:03 <@matches> Looking at the mysterious disappearances next +11:04 <@matches> It's integer overflow! +11:04 <@matches> Facepalm +11:05 <@sulix> Is it int64_t time? +11:05 <@sulix> Or magic huge bigint time? +11:05 <@matches> No I don't think that's necessary +11:06 <@matches> If the transformed width is smaller or larger than the width of the screen you can surely just ignore it +11:06 <@matches> Well, depending on what you are drawing +11:08 <@matches> Well it does matter unless you do some clever maths +11:08 <@matches> The clever maths was your part of the project... +11:09 <@matches> So I will just make them int64_t for now +11:50 <@matches> Pushe +11:50 <@matches> *d +11:50 <@matches> I should probably just make all the coorinates into Real instead of int64_t actually +12:03 <@sulix> Wow: this is pretty awesome. +12:03 <@sulix> I still get the artefacts, but I have to zoom in a lot more. +12:03 <@matches> Haha +12:04 <@sulix> Also, the CPU rendering artefacts and the GPU rendering artefacts are pretty similar on my machine, so it looks like it's just precision causing them. +12:04 <@matches> That is nice +15:20 <@matches> I'm trying to do a performance graph. Gnuplot doesn't like it much +15:20 <@matches> Well actually it's python's crappy interface to gnuplot that doesn't like it +15:23 <@matches> ... tempted to implement the performance graph in ipdf... +15:23 <@matches> Just keep adding circles to the document +15:24 <@matches> So meta +15:25 <@matches> We need a cool performance graph-y thing +15:26 <@matches> I think doing it in OpenGL is going to be the least shitty way actually +15:26 <@matches> This is a wheel that's probably been invented but it was invented wrong +17:11 <@matches> I've got a performance graph sort of working +17:11 <@matches> It almost looks like we are doing real science! +17:13 <@matches> I think we'll need to put some effort into our data analysis though because it's extremely noisy +17:13 <@matches> Smoothing averages or something +17:13 <@matches> Smoothing averages are the best +17:14 <@matches> They make any data look amazing +17:15 <@matches> Anyway, CPU rendering is only worse than GPU rendering when you force re-rendering +17:16 <@matches> So well done with the amazingly efficient cached frame buffer +17:18 <@matches> We can probably make it draw every frame both on the CPU and GPU to compare them in real time +17:18 <@matches> The possibilities are limitless! +17:19 <@matches> Graphs graphs graphs! +17:20 <@matches> Also I did end up using Gnuplot and python (sorry) but I made it slightly less shitty +17:27 <@matches> I have pushed things +17:27 <@matches> Also we probably don't need all three of those ways to measure performance +21:00 <@sulix> I got the graphs working on my laptop: very nice. +21:00 <@sulix> I can see how more GPU time is used with GPU rendering and more CPU time with CPU rendering quite well, actually. +21:59 <@matches> So the objects all being in one structure of arrays is sort of inconvenient because the size of objects has to be constant +21:59 <@matches> Also the size of Real has to be constant +22:03 <@matches> I guess we could have union {Rect rect, Bezier bezier} and do rectangles and Beziers in the same thing but that is slightly terrifying +22:04 <@matches> But there's still the problem of Real because as soon as Real becomes arbitrary precision it will start allocating memory and not be fwrite/fread'able +22:04 <@matches> :S +22:05 <@matches> You'll still want the struct of arrays because that will make view reparenting much easier +22:05 <@matches> Gah +22:06 <@sulix> I'm tempted to just split it by type: Have an array of Rects, an array of Béziers, an array of Circles, etc. +22:06 <@matches> Yeah but you need to store an "indexes" array as well +22:06 <@matches> But that might be the least terrible +22:07 <@matches> Yes that should work +22:07 <@matches> Our fwrite/fread is still doomed though +22:07 <@matches> When shit gets Real +22:07 <@sulix> Yeah, you'd need some indices one way or another. +22:08 <@sulix> And yeah, we'll need a massive "ConvertWhateverRealIsStoredInTheFileToWhateverRealIsDefined" function or something. +22:08 <@matches> That will totally be its name +22:08 <@sulix> (Some old compilers had function name limits... I wonder if modern gcc has) +22:09 <@sulix> (There is but one way to find out!) +22:09 <@matches> We don't need an array of circles/ellipses since we get those for free with Rect. Unless you want circular arcs as well as bezier curves +22:10 <@matches> Which you probably will? So you can approximate beziers +22:10 <@matches> Anyway I'll worry about adding Beziers first and once we've worked that out others should hopefully be easier +22:11 <@matches> I was sort of thinking it would be good to be able to define groups of objects as a special object type +22:11 <@matches> Then you can make paths out of your beziers +22:11 <@matches> But they won't be fixed size +22:12 <@matches> Anyway I will see if you have magically solved the problem for me in the morning :P +22:14 <@sulix> I wouldn't count on it... +--- Day changed Wed Jun 18 2014 +16:50 <@matches> Behold, the glory of Beziers and Bresenham! +16:50 <@matches> Breseniers I shall call them +16:54 <@matches> I'm getting a very strong vibe of "Reinventing graphics technologies from the 1990s" at the moment +16:55 <@matches> I should probably look at floating point some more +16:55 <@matches> And reinvent numerical computation technologies from the 1980s +16:56 <@matches> We need a GPU renderer for the Beziers, and we need to fix save/load to not assume everything is a fixed size, and ... +16:56 <@matches> Argh +16:56 <@matches> All the things +17:00 <@matches> Maybe I'll multithread the CPU rendering too, just to make things more difficult :P +22:48 <@sulix> So I got some béziers rendering on the GPU. +22:48 <@sulix> They're not the ones in the document, and they're not in the right spots, though. +23:12 <@sulix> First 3 béziers are rendering properly on the GPU, then we get corrupted memory or something. +23:14 <@sulix> Ah: I see, I need some way of uploading which bézier IDs are being used. +23:41 <@sulix> Okay, Béziers now render on the GPU as well. +23:43 <@sulix> The code is a little bit ugly, and for that I am sorry, but blame the fact that the GL feature that makes this nice is only about a year old and so nothing supports it. +23:43 <@sulix> So we're basically uploading all of the raw document data into a huge texture. +23:47 <@sulix> (If you ask me, the GPU ones also look slightly nicer, though that's probably a bug) +--- Day changed Thu Jun 19 2014 +13:55 <@matches> From those papers I was under the impression just rendering a bezier on a GPU was an impressive feat, so well done :P +13:57 <@sulix> (It's basically just a direct port of your CPU implementation, tbh) +13:59 <@matches> When I zoom out the GPU ones look nicer, there's probably something wrong with my Bresenham implementation +13:59 <@matches> Although it was mostly shamelessly copied from "Computer Graphics" +13:59 <@matches> Except they were like "Here it is for 0 < m < 1, the rest can be done by symmetry" +14:02 <@matches> The lines definitely have gaps on the CPU, and they also seem too thick as you zoom out +14:02 <@matches> Having said that, I don't think the GPU starts at x0,y0 +14:03 <@matches> Anyway I'm going to implement a Rational number type and see if anything exciting happens (that's how you do research right?) +14:06 <@matches> Fortunately I sort of did most of this for one of the codejam problems (where it turned out I didn't really need Rational numbers but I thought I did) +14:20 <@sulix> Fixed the missing bit off the end. +16:43 <@matches> I suspect Rationals are either not a very good idea, or there is a bug in one of my fundamental operations +16:43 <@matches> +, -, *, / are hard +16:56 <@sulix> Is it at least a pretty bug? +16:59 <@matches> Um... +16:59 <@matches> No +17:00 <@matches> It seems buggy for anything other than the {0,0,1,1} starting view +17:14 <@matches> I suspect it's the expf in the mouse wheel scrolling +17:14 <@matches> Since you know, exp is definitely not a rational number... +17:15 <@matches> Hmm, but it shouldn't matter because it will just convert to the nearest rational number +17:16 <@matches> ie: p = (int64_t)(whatever*1e10) q = (int64_t)1e10 +17:28 <@matches> Oh +17:28 <@matches> Oh +17:28 <@matches> Head -> Desk +17:28 <@matches> Rational & operator*=(const Rational & r) {this->operator=(*this*r); return *this;} +17:28 <@matches> Rational & operator/=(const Rational & r) {this->operator=(*this*r); return *this;} +17:29 <@matches> Rational & operator-=(const Rational & r) {this->operator=(*this+r); return *this;} +17:29 <@matches> I think the worst part is that I actually said "It is probably a bug in my +,-,*,/ +17:29 <@matches> And it still took me this long to notice +17:30 <@matches> The second worst thing is I've made that sort of mistake like 1000 times before +17:30 <@matches> The third worst thing is I am recalling that article where the guy says "At least plus and times are sort of the same thing" +17:30 <@sulix> Feel the power of copy and paste flowing through you. +17:32 <@matches> Well let's not celebrate just yet, the view still goes to shit. Just slightly slower :P +17:33 -!- matches changed the topic of #ipdf to: NaNpdf +17:33 <@matches> Our document supports a view of {-inf,-inf,nan,nan} thus making it truly infinite precision +17:34 <@sulix> I had that happen a lot when I was writing the original zoom code. +18:19 <@matches> So I suspect that Rationals are just a really shitty number representation :P +18:20 <@matches> Specifically, you get integer overflows really really fast +18:20 <@matches> And if you are going to have a Rational that's BigInt / BigInt you may as well just have a BigFloat +18:21 <@matches> The ancients were probably right. +18:21 <@matches> When they decided not to use rationals. +18:23 <@matches> I guess floats are rationals technically, I mean the representation using P/Q +18:23 <@matches> I kind of wish I'd done some pure maths here... +18:23 <@matches> Or paid more attention in second year +18:28 <@matches> At least I sort of have conclusive evidence that rationals suck. As opposed to "it should be obvious to anyone with half a brain" +19:00 <@sulix> Floats are not rationals. +19:00 <@sulix> Not exactly. +19:01 <@sulix> Something which can be stored in a finite amount of space as a rational cannot always be stored in a finite amount of space as a float, but not vice-versa. +19:01 <@sulix> e.g.: 1/3 +19:04 <@sulix> Basically floats = rationals where the denominator must be a power of two. +19:05 <@sulix> (Of course, these are all the same in the limit, but the limit of a cauchy sequence of rationals gives the reals, so the point is kinda moot, there, anyway) +19:18 <@matches> Yeah floats are a subset of the rationals I think I meant +--- Day changed Sat Jun 21 2014 +16:22 <@matches> So I got a new smartphone today... I'm having fun trying to zoom in on things +16:24 <@matches> Actually the zooming isn't annoying so much as the needing to pan around to view all the text in a pdf +16:25 <@matches> This is what I get for buying the cheapest phone with the lowest resolution they had :P +16:26 <@matches> I didn't want to get one more expensive than my old one because I'm still convinced I will get around to fixing it one of these days +16:26 <@matches> Or months. Or years. But eventually. +--- Day changed Mon Jun 23 2014 +11:51 <@matches> The meeting happened at ~11:30 +12:49 <@sulix> Oh damn. I thought there wasn't going to be one today. +12:49 <@sulix> What did I miss? +13:04 <@matches> Basically I told him what we'd done +13:05 <@matches> Which was rendering on CPU or GPU, and Beziers (but only degree 2) +13:06 <@matches> And I implemented Rationals but they are terrible, so he sent me some code from an ACM competition about approximating things with Rationals +13:13 <@sulix> Some javascript guy is trying to convince people that the only numeric data type should be some custom 64-bit decimal thing. +13:13 <@sulix> A lot of people have started quoting Kahan at him. +13:20 <@matches> Haha