-
-
Notifications
You must be signed in to change notification settings - Fork 72
Description
Given that support for floating-point has been proposed before (see #92 and #180), I have a suggestion for a way that they could be implemented without locking users into a specific format.
My suggestion is that a new type be added, which I will call f for now, that matches numbers with a fractional component (10.9, 10., .9, etc). This type would have four built-in functions to act on it: whole(f), fraction(f), exponent(f), and mantissa(f). whole gives the whole portion of the number, fraction gives the fractional part of the number, exponent gives the exponent of the number as if it were represented in binary scientific notation, and mantissa gives the mantissa of the number as it were represented in scientific representation, with the radix point removed.
Example for how this could be used to define the formats for a 32-bit IEEE 754 float (ignoring subnormals) and a fixed 16.16 type:
#ruledef f32 {
{float:f}_f32 => {
; sign 1b | exponent 8b | mantissa 23b
s = float >= 0 ? 0 : 1
e = exponent(float) + 127 ; bias
m = mantissa(float)
assert(exponent > 0) ; Filter out subnormals
assert(exponent < 255) ; Filter out values to large to represent
; The assumptions here are that negative indicies exist, and that when using them the value would be padded on the right.
s @ e`8 @ m[-2:-24] ; Top-most mantissa bit is implicit
}
inf => 0x7F800000`32
}
#ruledef fx16_16 {
{fixed:f}_fx16_16 => {
assert(fixed >= -32768)
assert(fixed < 32768)
whole(fixed)`16 @ fraction(fixed)[-1:-16]
}
}
10.125_f32 ; s = 0
; e = 130
; m = 0b101000100000000000000000...
; s @ e`8 @ m[-2:-24]
; 0b0'10000010'01000100000000000000000
; 0x41220000
1.21_fx16_16 ; whole(fixed) = 1
; fraction(fixed) = 00110101110000101001000....
; whole(fixed)`16 @ fraction(fixed)[-1:-16]
; 0b0000000000000001'0011010111000010
; 0x0001'35C2
I hope what I'm trying to suggest is actually possible to understand from what I've written.