const std = @import("std");
const math = std.math;
const common = @import("common.zig");
const BiasedFp = common.BiasedFp;
const Decimal = @import("decimal.zig").Decimal;
const mantissaType = common.mantissaType;
const max_shift = 60;
const num_powers = 19;
const powers = [_]u8{ 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59 };
pub fn getShift(n: usize) usize {
    return if (n < num_powers) powers[n] else max_shift;
}
pub fn convertSlow(comptime T: type, s: []const u8) BiasedFp(T) {
    const MantissaT = mantissaType(T);
    const min_exponent = -(1 << (math.floatExponentBits(T) - 1)) + 1;
    const infinite_power = (1 << math.floatExponentBits(T)) - 1;
    const mantissa_explicit_bits = math.floatMantissaBits(T);
    var d = Decimal(T).parse(s); 
    if (d.num_digits == 0 or d.decimal_point < Decimal(T).min_exponent) {
        return BiasedFp(T).zero();
    } else if (d.decimal_point >= Decimal(T).max_exponent) {
        return BiasedFp(T).inf(T);
    }
    var exp2: i32 = 0;
    
    while (d.decimal_point > 0) {
        const n = @intCast(usize, d.decimal_point);
        const shift = getShift(n);
        d.rightShift(shift);
        if (d.decimal_point < -Decimal(T).decimal_point_range) {
            return BiasedFp(T).zero();
        }
        exp2 += @intCast(i32, shift);
    }
    
    while (d.decimal_point <= 0) {
        const shift = blk: {
            if (d.decimal_point == 0) {
                break :blk switch (d.digits[0]) {
                    5...9 => break,
                    0, 1 => @as(usize, 2),
                    else => 1,
                };
            } else {
                const n = @intCast(usize, -d.decimal_point);
                break :blk getShift(n);
            }
        };
        d.leftShift(shift);
        if (d.decimal_point > Decimal(T).decimal_point_range) {
            return BiasedFp(T).inf(T);
        }
        exp2 -= @intCast(i32, shift);
    }
    
    exp2 -= 1;
    while (min_exponent + 1 > exp2) {
        var n = @intCast(usize, (min_exponent + 1) - exp2);
        if (n > max_shift) {
            n = max_shift;
        }
        d.rightShift(n);
        exp2 += @intCast(i32, n);
    }
    if (exp2 - min_exponent >= infinite_power) {
        return BiasedFp(T).inf(T);
    }
    
    
    d.leftShift(mantissa_explicit_bits + 1);
    var mantissa = d.round();
    if (mantissa >= (@as(MantissaT, 1) << (mantissa_explicit_bits + 1))) {
        
        
        d.rightShift(1);
        exp2 += 1;
        mantissa = d.round();
        if ((exp2 - min_exponent) >= infinite_power) {
            return BiasedFp(T).inf(T);
        }
    }
    var power2 = exp2 - min_exponent;
    if (mantissa < (@as(MantissaT, 1) << mantissa_explicit_bits)) {
        power2 -= 1;
    }
    
    mantissa &= (@as(MantissaT, 1) << mantissa_explicit_bits) - 1;
    return .{ .f = mantissa, .e = power2 };
}