Function binaryToDecimal [src]

Convert a binary float representation to decimal.

Prototype

pub fn binaryToDecimal(comptime T: type, bits: T, mantissa_bits: std.math.Log2Int(T), exponent_bits: u5, explicit_leading_bit: bool, comptime tables: anytype) FloatDecimal(T)

Parameters

T: typebits: Tmantissa_bits: std.math.Log2Int(T)exponent_bits: u5explicit_leading_bit: bool

Source

pub fn binaryToDecimal(comptime T: type, bits: T, mantissa_bits: std.math.Log2Int(T), exponent_bits: u5, explicit_leading_bit: bool, comptime tables: anytype) FloatDecimal(T) { if (T != tables.T) { @compileError("table type does not match backend type: " ++ @typeName(tables.T) ++ " != " ++ @typeName(T)); } const bias = (@as(u32, 1) << (exponent_bits - 1)) - 1; const ieee_sign = ((bits >> (mantissa_bits + exponent_bits)) & 1) != 0; const ieee_mantissa = bits & ((@as(T, 1) << mantissa_bits) - 1); const ieee_exponent: u32 = @intCast((bits >> mantissa_bits) & ((@as(T, 1) << exponent_bits) - 1)); if (ieee_exponent == 0 and ieee_mantissa == 0) { return .{ .mantissa = 0, .exponent = 0, .sign = ieee_sign, }; } if (ieee_exponent == ((@as(u32, 1) << exponent_bits) - 1)) { return .{ .mantissa = if (explicit_leading_bit) ieee_mantissa & ((@as(T, 1) << (mantissa_bits - 1)) - 1) else ieee_mantissa, .exponent = special_exponent, .sign = ieee_sign, }; } var e2: i32 = undefined; var m2: T = undefined; if (explicit_leading_bit) { if (ieee_exponent == 0) { e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2; } else { e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2; } m2 = ieee_mantissa; } else { if (ieee_exponent == 0) { e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) - 2; m2 = ieee_mantissa; } else { e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) - 2; m2 = (@as(T, 1) << mantissa_bits) | ieee_mantissa; } } const even = (m2 & 1) == 0; const accept_bounds = even; // Step 2: Determine the interval of legal decimal representations. const mv = 4 * m2; const mm_shift: u1 = @intFromBool((ieee_mantissa != if (explicit_leading_bit) (@as(T, 1) << (mantissa_bits - 1)) else 0) or (ieee_exponent == 0)); // Step 3: Convert to a decimal power base using 128-bit arithmetic. var vr: T = undefined; var vp: T = undefined; var vm: T = undefined; var e10: i32 = undefined; var vm_is_trailing_zeros = false; var vr_is_trailing_zeros = false; if (e2 >= 0) { const q: u32 = log10Pow2(@intCast(e2)) - @intFromBool(e2 > 3); e10 = cast_i32(q); const k: i32 = @intCast(tables.POW5_INV_BITCOUNT + pow5Bits(q) - 1); const i: u32 = @intCast(-e2 + cast_i32(q) + k); const pow5 = tables.computeInvPow5(q); vr = tables.mulShift(4 * m2, &pow5, i); vp = tables.mulShift(4 * m2 + 2, &pow5, i); vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, i); if (q <= tables.bound1) { if (mv % 5 == 0) { vr_is_trailing_zeros = multipleOfPowerOf5(mv, if (tables.adjust_q) q -% 1 else q); } else if (accept_bounds) { vm_is_trailing_zeros = multipleOfPowerOf5(mv - 1 - mm_shift, q); } else { vp -= @intFromBool(multipleOfPowerOf5(mv + 2, q)); } } } else { const q: u32 = log10Pow5(@intCast(-e2)) - @intFromBool(-e2 > 1); e10 = cast_i32(q) + e2; const i: i32 = -e2 - cast_i32(q); const k: i32 = cast_i32(pow5Bits(@intCast(i))) - tables.POW5_BITCOUNT; const j: u32 = @intCast(cast_i32(q) - k); const pow5 = tables.computePow5(@intCast(i)); vr = tables.mulShift(4 * m2, &pow5, j); vp = tables.mulShift(4 * m2 + 2, &pow5, j); vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, j); if (q <= 1) { vr_is_trailing_zeros = true; if (accept_bounds) { vm_is_trailing_zeros = mm_shift == 1; } else { vp -= 1; } } else if (q < tables.bound2) { vr_is_trailing_zeros = multipleOfPowerOf2(mv, if (tables.adjust_q) q - 1 else q); } } // Step 4: Find the shortest decimal representation in the interval of legal representations. var removed: u32 = 0; var last_removed_digit: u8 = 0; while (vp / 10 > vm / 10) { vm_is_trailing_zeros = vm_is_trailing_zeros and vm % 10 == 0; vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0; last_removed_digit = @intCast(vr % 10); vr /= 10; vp /= 10; vm /= 10; removed += 1; } if (vm_is_trailing_zeros) { while (vm % 10 == 0) { vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0; last_removed_digit = @intCast(vr % 10); vr /= 10; vp /= 10; vm /= 10; removed += 1; } } if (vr_is_trailing_zeros and (last_removed_digit == 5) and (vr % 2 == 0)) { last_removed_digit = 4; } return .{ .mantissa = vr + @intFromBool((vr == vm and (!accept_bounds or !vm_is_trailing_zeros)) or last_removed_digit >= 5), .exponent = e10 + cast_i32(removed), .sign = ieee_sign, }; }