frexp
Breaks x into a normalized fraction and an integral power of two. f == frac * 2^exp, with |frac| in the interval [0.5, 1).
Special Cases:
- frexp(+-0) = +-0, 0
- frexp(+-inf) = +-inf, 0
- frexp(nan) = nan, undefined
Function parameters
Parameters
- x:anytype
Functions in this namespace
Functions
Source
Implementation
pub fn frexp(x: anytype) Frexp(@TypeOf(x)) {
const T: type = @TypeOf(x);
const bits: comptime_int = @typeInfo(T).float.bits;
const Int: type = std.meta.Int(.unsigned, bits);
const exp_bits: comptime_int = math.floatExponentBits(T);
const mant_bits: comptime_int = math.floatMantissaBits(T);
const frac_bits: comptime_int = math.floatFractionalBits(T);
const exp_min: comptime_int = math.floatExponentMin(T);
const ExpInt: type = std.meta.Int(.unsigned, exp_bits);
const MantInt: type = std.meta.Int(.unsigned, mant_bits);
const FracInt: type = std.meta.Int(.unsigned, frac_bits);
const unreal_exponent: comptime_int = (1 << exp_bits) - 1;
const bias: comptime_int = (1 << (exp_bits - 1)) - 2;
const exp_mask: comptime_int = unreal_exponent << mant_bits;
const zero_exponent: comptime_int = bias << mant_bits;
const sign_mask: comptime_int = 1 << (bits - 1);
const not_exp: comptime_int = ~@as(Int, exp_mask);
const ones_place: comptime_int = mant_bits - frac_bits;
const extra_denorm_shift: comptime_int = 1 - ones_place;
var result: Frexp(T) = undefined;
var v: Int = @bitCast(x);
const m: MantInt = @truncate(v);
const e: ExpInt = @truncate(v >> mant_bits);
switch (e) {
0 => {
if (m != 0) {
// subnormal
const offset = @clz(m);
const shift = offset + extra_denorm_shift;
v &= sign_mask;
v |= zero_exponent;
v |= math.shl(MantInt, m, shift);
result.exponent = exp_min - @as(i32, offset) + ones_place;
} else {
// +-0 = (+-0, 0)
result.exponent = 0;
}
},
unreal_exponent => {
// +-nan -> {+-nan, undefined}
result.exponent = undefined;
// +-inf -> {+-inf, 0}
if (@as(FracInt, @truncate(v)) == 0)
result.exponent = 0;
},
else => {
// normal
v &= not_exp;
v |= zero_exponent;
result.exponent = @as(i32, e) - bias;
},
}
result.significand = @bitCast(v);
return result;
}