Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

floats/ #8

Open
utterances-bot opened this issue May 12, 2022 · 11 comments
Open

floats/ #8

utterances-bot opened this issue May 12, 2022 · 11 comments

Comments

@utterances-bot
Copy link

Converting Integers to Floats Using Hyperfocus - Mara's Blog

A few years ago, due to some random chain of events, I ended up implementing a conversion from 128 bit integers to 64 bit floats. This would’ve turned out to be a complete waste of time, except that my final version is faster than the builtin conversion every compiler I tested. In this blog post, I’ll explain what happened, how floats work, how this conversion works, and how it got a bit out of hand.

https://blog.m-ou.se/floats/

Copy link

A concrete example: the value 9.75 in binary looks like 1001.11,
so it is represented as a f64 with an exponent of 1026,

exponent for 9.75 is just 4(10), or 100(2), where 1026 come from?

@m-ou-se
Copy link
Owner

m-ou-se commented May 12, 2022

exponent for 9.75 is just 4(10), or 100(2), where 1026 come from?

@Dushistov

If you check the table with exponents:

   :   \
1026    1mmm.mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1025     1mm.mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1024      1m.mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1023       1.mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1022       0.1mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1021       0.01mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1020       0.001mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
   :            \

you'll see the row with 1026 matches the binary represenation of 9.75:

1026    1mmm.mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
        1001.11000… (=0.75)

Another way of saying it, is that 9.75 is 1001.11 = 1.00111 × 2³, and 3 + 1023 = 1026.

@SUPERCILEX
Copy link

Can these be turned back into compiler built-ins? Or is there a reason not to do that?

Copy link

what a gorgeous project! I can see why you put so much time into it, lots of unholy fun here.

I found that your final code is missing a bracket for the mantissa calculation and fails my tests as a result :'(

let m = a + (b - (b >> 63 & !a)) >> 63;

should be:

let m = a + ((b - (b >> 63 & !a)) >> 63);

because + has stronger precedence than >>

(although I personally prefer the following:)

let m = ((a) + (((b) - (((b) >> (63)) & (!a))) >> (63)));

@m-ou-se
Copy link
Owner

m-ou-se commented May 13, 2022

@lilly-lizard Oh oops. Those disappeared while editing this blog post somehow. Fixed. :)

@m-ou-se
Copy link
Owner

m-ou-se commented May 13, 2022

Can these be turned back into compiler built-ins? Or is there a reason not to do that?

@SUPERCILEX Yeah, I opened a PR for the compiler_builtins crate, two years ago, but got distracted and never finished it. It should probably also end up in Clang's compiler-rt and Gcc's libgcc, though, for it to be useful on all platforms.

@SUPERCILEX
Copy link

Haha, makes sense!

Copy link

scips commented May 15, 2022

I don´t know how I ended reading your blog on a Sunday morning but reading you gave me a great refreshing kick on how one person can share something that will speed up the work of millions.
Thanks for sharing! And I love the small notes of humor all along the journey. I was almost feeling what you felt with the "Boom" 💥, the "Uh", the "wait"... and I was thinking on how you wrote your post while revisiting your journey.
Sharing is caring!
Have a nice day!

Copy link

I'm reminded of some code that I wrote more than 30 years ago when I needed to convert a tape full of binary data from IBM VM/370 native 64-bit float to IEEE-754 64-bit float, without loss of any accuracy. The VM/370 used a base-16 exponent, and therefore (unlike IEEE-754) no implied leading 1. I could have written a FORTRAN program to dump the data in decimal format on the IBM and read it back on the target machine, but that seemed way too easy, and I was young and cocky, so I read the IBM assembler manual and got to work. I still have that code. Here's a gist of it, but good luck finding a machine that will run it: https://gist.github.com/DavidHarper/ba20799c6b72d6131f263316d53723fb

Copy link

This reminds me of dealing with the 32-bit float format about 25 years ago, when I was trying to implement as much floating-point as I could fit into a BASIC interpreter running on a PIC16C74 processor.

Copy link

lowasser commented Jun 4, 2022

Enjoyed this a lot! Once upon a time I did something similar for Java's BigInteger.doubleValue(): https://bugs.openjdk.java.net/browse/JDK-7131192. But you managed to make yours branch-free, and much smoother and more compact! Very nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants