"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var number_decoder_1 = require("./number-decoder");
var FloatConverter = /** @class */ (function () {
    function FloatConverter(options) {
        this.options = options;
    }
    FloatConverter.prototype.encode = function (value) {
        return number_decoder_1.NumberConverter.toOpaqueMsb(FloatConverter.toArray(value), 32);
    };
    FloatConverter.prototype.decode = function (body) {
        return FloatConverter.toFloat(body);
    };
    /**
     *
     * @see https://stackoverflow.com/questions/3096646/how-to-convert-a-floating-point-number-to-its-binary-representation-ieee-754-i
     * @param number
     */
    FloatConverter.toArray = function (number) {
        var n = +number, status = (n !== n) || n == -Infinity || n == +Infinity ? n : 0, exp = 0, len = 281, // 2 * 127 + 1 + 23 + 3,
        bin = new Array(len), signal = (n = status !== 0 ? 0 : n) < 0, n = Math.abs(n), intPart = Math.floor(n), floatPart = n - intPart, i, lastBit, rounded, j, exponent;
        if (status !== 0) {
            if (n !== n) {
                return 0x7fc00000;
            }
            if (n === Infinity) {
                return 0x7f800000;
            }
            if (n === -Infinity) {
                return 0xff800000;
            }
        }
        i = len;
        while (i) {
            bin[--i] = 0;
        }
        i = 129;
        while (intPart && i) {
            bin[--i] = intPart % 2;
            intPart = Math.floor(intPart / 2);
        }
        i = 128;
        while (floatPart > 0 && i) {
            (bin[++i] = (floatPart *= 2) >= 1 ? 1 : 0) && --floatPart;
        }
        i = -1;
        while (++i < len && !bin[i])
            ;
        if (bin[(lastBit = 22 + (i = (exp = 128 - i) >= -126 && exp <= 127 ? i + 1 : 128 - (exp = -127))) + 1]) {
            if (!(rounded = bin[lastBit])) {
                j = lastBit + 2;
                while (!rounded && j < len) {
                    rounded = bin[j++];
                }
            }
            j = lastBit + 1;
            while (rounded && --j >= 0) {
                (bin[j] = !bin[j] - 0) && (rounded = 0);
            }
        }
        i = i - 2 < 0 ? -1 : i - 3;
        while (++i < len && !bin[i])
            ;
        (exp = 128 - i) >= -126 && exp <= 127 ? ++i : exp < -126 && (i = 255, exp = -127);
        (intPart || status !== 0) && (exp = 128, i = 129, status == -Infinity ? signal = true : (status !== status) && (bin[i] = 1));
        n = Math.abs(exp + 127);
        exponent = 0;
        j = 0;
        while (j < 8) {
            exponent += (n % 2) << j;
            n >>= 1;
            j++;
        }
        var mantissa = 0;
        n = i + 23;
        for (; i < n; i++) {
            mantissa = (mantissa << 1) + bin[i];
        }
        return ((signal ? 0x80000000 : 0) + (exponent << 23) + mantissa) | 0;
    };
    FloatConverter.toFloat = function (val) {
        return FloatConverter.numberToFloat(number_decoder_1.NumberConverter.fromOpaqueMsb(val, 32));
    };
    FloatConverter.numberToFloat = function (val) {
        var bits = 1 * val;
        var sign = ((bits & 0x80000000) == 0) ? 1 : -1;
        var exponent = ((bits & 0x7f800000) >> 23);
        var mantissa = (bits & 0x007fffff);
        mantissa |= 0x00800000;
        var f = 1.0 * (sign * mantissa * Math.pow(2, exponent - 150));
        return parseFloat(f.toFixed(5));
    };
    FloatConverter.instance32 = function () {
        if (!FloatConverter._instance32) {
            FloatConverter._instance32 = new FloatConverter();
        }
        return FloatConverter._instance32;
    };
    return FloatConverter;
}());
exports.FloatConverter = FloatConverter;
