28188, "damianmoz", "[Documentation]: Using the transmute feature", "2025-12-11T07:34:26Z"
Should such an example of the transmute feature be useful, one use for this feature is to deliver the fractional and integral parts of a real(w) number, the modf() function in C. Returning the result as a tuple of two real(w) numbers, the integral component and the fractional component, the function called split() for want of a better name could be written as
proc split(x : real(?w)) // return the integral and fractional parts of x
{
// IEEE 754 functionality
param b = bias(x);
param p = precision(x);
// get IEEE 754 erncodings of x itself and |x|
const _x = x.transmute(uint(w));
const _a = abs(x).transmute(uint(w));
// extract the biased exponent of x
const e = _a >> (p - 1);
// extract the negative bit of x and
// then convert it to a real(w) number
// this yields an IEEE 754 signed zero
const z = (_x - _a).transmute(real(w));
if e < b then // |x| < 1.0
{
return (z, x);
}
else if x != x then // x is a NaN
{
return (x, x);
}
else if e < b + (p - 1) then // x might have a fractional component
{
// create a mask corresponding to the significand of x
param _S = (~(0:uint(w))) >> (w - p + 1);
// get the bits associated with the fractional component
const _t = _x & (_S >> (e - b));
if _t != 0 then // there is a fractional component
{
// strip those bits from the encoding of x
// and convert the net to a real(w) number
const _r = (_x - _t).transmute(real(w));
return (r, x - r);
}
}
return (x, z);
The param procs to provide p and b might be:
// IEEE 754 precision - p (also = the digits in the significand)
// (handles T = real(w) where w = 16, 32, 64 and 128)
proc precision(type T) param where isReal(T)
{
param w = numBits(T);
param p = w + 2 * (w >> 7) - 3 * (w >> 5) - 5;
return p:uint(w);
}
proc precision(x : real(?w)) param do return precision(real(w));
// IEEE 754 exponent bias - b (also = the largest unbiased exponent)
proc bias(type T) param where isReal(T)
{
param w = numBits(T);
param _1 = 1:uint(w);
param p = precision(T):int(64);
return (_1 << (w - 1 - p)) - _1;
}
proc bias(x : real(?w)) param do return bias(real(w));