Show HN: Floating point arithmetic types in C++ for any size and any base
76 points
3 days ago
| 9 comments
| github.com
| HN
Since there is so much interest on HN in floats lately and their software implementations, I wanted to show mine. It has no use and is just for teaching me floats and C++. Give me your thoughts.
listeria
12 hours ago
[-]
reply
dataflow
9 hours ago
[-]
Why is std::is_object even specialized here? Isn't it always true regardless?
reply
seg_fault
11 hours ago
[-]
I don't get what you mean. I thought they specify how the type can be used?
reply
badmintonbaseba
11 hours ago
[-]
The cppreference page says:

> If the program adds specializations for std::is_fundamental or std::is_fundamental_v, the behavior is undefined.

This is an oversimplification. The actual rule is https://eel.is/c++draft/library#namespace.std-2 .

> the specialization meets the standard library requirements for the original template.

For is_fundamental<YourClassType> it means that is_fundamental<YourClassType>::value must be false, as YourClassType is not a fundamental type, as defined in https://eel.is/c++draft/basic.fundamental#17 .

Some traits are just not designed to be customization points.

reply
secondcoming
11 hours ago
[-]
Technically, you're not supposed to add your own specialisations to the `std` namespace
reply
pmalynin
10 hours ago
[-]
In general this isn’t true (i guess it is in this specific context). For example I believe it’s totally expected to specialize std hash
reply
tyleo
9 hours ago
[-]
I’ve also done this with hash… though given the footguns scattered about, I wouldn’t be surprised if it broke the spec.
reply
Conscat
4 hours ago
[-]
That is a completely intended way to use std::hash, along with a few other functions like std::tuple_size and std::tuple_element.
reply
amelius
14 minutes ago
[-]
Isn't this in libgmp already?

https://gmplib.org/

reply
fuhsnn
12 hours ago
[-]
For "any size" I was kind of expecting arbitrary sized mantissa/exponent, can be useful for emulating weird DACs, for example, 12-bit mantissa and 3-bit exponent[1].

[1] https://ajxs.me/blog/Yamaha_DX7_Technical_Analysis.html

reply
seg_fault
11 hours ago
[-]
Actually you can specify the numeric limits of the mantissa and the exponent. They can be specified as template arguments[0]. So you could do:

      Float<uint8_t, // type of the mantissa
            uint8_t, // type of the exponent
            0,       // lowest possible value of the mantissa
            4095,    // highest possible value of the mantissa
            0,       // lowest possible value of the exponent
            7>       // highest possible value of the exponent
The Float then simulates an unsigned 12bit mantissa and a 3bit exponent. Sure it still takes 16 bytes. But you could create a union with bitfields where you shrink that even further.

[0] https://github.com/clemensmanert/fas/blob/58f9effbe6c13ab334...

reply
Archit3ch
11 hours ago
[-]
Can you go in the other direction? Higher exponent and mantissa than regular float/double?
reply
seg_fault
11 hours ago
[-]
Sure.

    Float<int64_t, int64_t>
Gives you a signed Mantissa with 64 bit and a signed Exponent with 64bit. Since there are numeric limits for int64_t available, Float knows the max and the min value.

You could get even bigger ranges for Float by implementing your own big integer type.

reply
badmintonbaseba
12 hours ago
[-]
Possibly could be combined with C23's _BitInt(N) for the template arguments? I think it's available in clang as a C++ extension.

edit: or I guess you could have your own Tmantissa and Texponent types as custom classes that correctly model _BitInt(N), they don't seem to be required to be builtin integral types.

reply
nly
8 hours ago
[-]
reply
badmintonbaseba
12 hours ago
[-]
Nice!

> TODO: (configurable) rounding support

What's the default rounding mode? Round to nearest even?

You might be interested in https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p33... too, which is a recent paper for introducing reproducible floating point to C++.

Very small floating point types can be handy for exhaustive testing of floating point function templates, especially ones that take multiple arguments. Walking over all floating point values for a small type often finds most if not all corner cases that can manifest with a floating point type of any size.

reply
seg_fault
12 hours ago
[-]
Rounding: actually it just cuts off. I have not spent much time to think about how to specify and implement the different rounding modes. Maybe some day...

Thanks for the hint to the paper. I also faced these issues. Thus, I provided a constructor which accepts mantissa and exponent as values. Very handy for the unittests.

reply
badmintonbaseba
11 hours ago
[-]
By cutting off do you mean that it correctly rounds towards zero? Maybe you can implement rounding to closest by just doing the calculation in a one digit wider mantissa with rounding to zero and observing the last digit, at least for an even base. It won't be rounding to even though, but for that a 2 digit wider mantissa is probably enough.

Rounding to nearest with an odd base doesn't seem to be as straightforwardly implementable from rounding to zero calculations at a higher precision.

reply
seg_fault
11 hours ago
[-]
I remember that I tried that some time ago. Especially the multiplication was tough, but I can not recall where I gave up. When I find some time, I will pick it up again :)
reply
skissane
10 hours ago
[-]
No LICENSE. Have you thought about adding one?
reply
seg_fault
2 hours ago
[-]
Somebody wants to use it? :D I thought about something like where people can use it but have to make changed public. I am just curious, what should be changed. But I dont think there is actually a real world use case.
reply
codr7
12 hours ago
[-]
Here is an example of the other end of the spectrum that I've used a couple of times: very simple fixpoints.

https://github.com/codr7/claes/blob/main/src/claes/f64.hpp

reply
a_t48
12 hours ago
[-]
Have nothing to say other than - neat!
reply
seg_fault
11 hours ago
[-]
Thank you :)
reply
rurban
10 hours ago
[-]
It's copyrighted so I should not even look at it, and therefore not comment on it.
reply
dahart
3 hours ago
[-]
All creative works are copyrighted by default in the U.S. and any countries adhering to the Berne convention, unless copyrights are explicitly waived (which is not always an option). This is true regardless of what copyright notices exist, so by that standard you shouldn’t look at or comment on anything. ;) But, it’s legal to look at something copyrighted, you just can’t copy & distribute it. Just curious, did you mean that it lacks an open source license and you only look at open source, or was this just a joke that went sideways, or something else?
reply
syockit
4 hours ago
[-]
It's copyrighted, but nothing stops you from looking at it. It's akin to looking a t a mural painted at someone's house. You can also comment as long as you don't post snippets of the code (except for when fair use is applicable).
reply
sebtron
2 hours ago
[-]
I suppose you do not read books or watch movies either
reply
seg_fault
2 hours ago
[-]
Removed it.
reply
recursive
5 hours ago
[-]
And yet...
reply
rurban
4 hours ago
[-]
The API looks fine, well
reply