const std = @import("std");
const math = std.math;
const common = @import("common.zig");
const Number = common.Number;
const floatFromUnsigned = common.floatFromUnsigned;
pub fn convertHex(comptime T: type, n_: Number(T)) T {
const MantissaT = common.mantissaType(T);
var n = n_;
if (n.mantissa == 0) {
return if (n.negative) -0.0 else 0.0;
}
const max_exp = math.floatExponentMax(T);
const min_exp = math.floatExponentMin(T);
const mantissa_bits = math.floatMantissaBits(T);
const exp_bits = math.floatExponentBits(T);
const exp_bias = min_exp - 1;
n.exponent += mantissa_bits;
while (n.mantissa != 0 and n.mantissa >> (mantissa_bits + 2) == 0) {
n.mantissa <<= 1;
n.exponent -= 1;
}
if (n.many_digits) {
n.mantissa |= 1;
}
while (n.mantissa >> (1 + mantissa_bits + 2) != 0) {
n.mantissa = (n.mantissa >> 1) | (n.mantissa & 1);
n.exponent += 1;
}
while (n.mantissa > 1 and n.exponent < min_exp - 2) {
n.mantissa = (n.mantissa >> 1) | (n.mantissa & 1);
n.exponent += 1;
}
var round = n.mantissa & 3;
n.mantissa >>= 2;
round |= n.mantissa & 1;
n.exponent += 2;
if (round == 3) {
n.mantissa += 1;
if (n.mantissa == 1 << (1 + mantissa_bits)) {
n.mantissa >>= 1;
n.exponent += 1;
}
}
if (n.mantissa >> mantissa_bits == 0) {
n.exponent = exp_bias;
}
if (n.exponent > max_exp) {
return math.inf(T);
}
var bits = n.mantissa & ((1 << mantissa_bits) - 1);
bits |= @intCast(MantissaT, (n.exponent - exp_bias) & ((1 << exp_bits) - 1)) << mantissa_bits;
if (n.negative) {
bits |= 1 << (mantissa_bits + exp_bits);
}
return floatFromUnsigned(T, MantissaT, bits);
}