3 ms·
Does Rust have first class support for fixed point number formats? If not, is there a proposal for that?
by djmips 6y ago
Does Rust have first class support for fixed point number formats? If not, is there a proposal for that?
- deleted 6y ago[deleted]
- JoshTriplett 6y agoDo you mean something like decimal floating-point? No. There are several crates that provide such types, though: https://crates.io/search?q=decimal https://crates.io/search?q=decimal We've talked about having support for user-defined literals, so that you could have decimal literals; in the meantime, a macro works for that.
- tbirdz 6y agoI don't want to speak for djmips, but I believe he was referring to something more like https://en.wikipedia.org/wiki/Q_(number_format) https://en.wikipedia.org/wiki/Q_(number_format)
- djmips 6y agoThat's pretty cool. I hadn't seen that before. I knew DSPs have used fixed point for decades but not aware of this format.
- djmips 6y agoThanks for the crates search link! It looks like decimal floating point is something used for financial calculations. Fixed point is where say in a 32 bit word, 16 bits is used for the integer part and 16 bits for the fraction or any combination that you can declare. Usually notated like 16.16 or 16:16. Another format example in 32 bits could be 8.24 and also formats in other word sizes. I found some crates using 'fixed' as the search term. https://crates.io/search?page=1&per_page=10&q=fixed%20point https://crates.io/search?page=1&per_page=10&q=fixed%20point It's been my desire to have a language for embedded to have first class support for fixed point just from the ability to work with them like you would a floating point number and not have to worry about macros.
- JoshTriplett 6y agoAh, got it. Along the same lines, is there anything that'd be needed to have "first class support" other than literals? If we had user-defined literal formats, so that one of those fixed-point crates could define a format for fixed-point literals, would that suffice?
- jlokier 6y agoThe arithmetic should either work, or be type checked. Multiplying a Q8.24 with another Q8.24 makes a Q16.48. In C that's not the same as the '∗' operator; you'd generally cast both arguments to 64-bit first, and rely on the compiler being smart enough to use a 32x32->64 instruction if available instead of 64x64->64. But even that's ambiguous - is it signed or unsigned widening multiplication? Adding a Q8.8 to a Q4.12 needs a 4-bit shift before the addition. So does adding a Q5.27 to Q1.31. The right thing to do is, unfortunately, ambiguous. E.g. when adding Q5.27 to Q1.31, do you need to keep the full range and precision and end up with Q6.31? Or do you right shift the second argument, ignore overflow, and call it a day with a Q5.27 result that is implemented in C as (uint32_t)(a + (b >> 4)? (Though if it's signed, which it usually is, (b >> 4) is dodgy in C anyway as it's implementation-defined.) If you do ignore overflow, is that a saturating addition (like used for audio/graphics) or wraparound (like in C)? Really, those decisions depend on what the numbers mean, as well as range and precision assumptions the author may already know are valid for numerical reasons. So maybe there's a case for traits on number types which specify whether they are default-saturating, default-precision-maintaining, default-range-maintaining. Another operation is to change the representation, either to truncate/round some precision bits, reduce range bits (saturating or assuming), or expand range bits prior to doing some sums (because addition doesn't expand the range bits in real implementations, you have to explicitly do that yourself in advance of adding). The way I see this done in careful DSP in C or C-like languages is as a series of function or macro calls that specify input and output formats, avoiding operators and the ambiguity they imply.
- zozbot234 6y agoWorth noting that C does have a draft standard extension for fixed point arithmetic, that ought to address these issues.
- qppo 6y agoAre there any architectures in production today where fractional arithmetic is meaningfully different than emulated block floating point and have an LLVM backend already? I know there are some TI and ADI arch's with special fixed point data types built into their compilers (which are nonstandard extensions to C/C++, fwiw), but they are unsupported by LLVM last I checked. I've also heard that those niches are having their lunch eaten by ARM M4/M7 cores which have floating point vector instructions, and you can write Rust to target those today.