"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.F2D14 = exports.F24D6 = exports.F16D16 = exports.IntN = exports.UIntN = exports.Int32 = exports.Int24 = exports.Int16 = exports.Int8 = exports.UInt32 = exports.UInt24 = exports.UInt16 = exports.UInt8 = exports.Fixed = void 0;
const errors_1 = require("@ot-builder/errors");
class Fixed {
    constructor(signed, integerBits, fractionBits) {
        this.signed = signed;
        this.shiftBits = 32 - integerBits - fractionBits;
        this.exponent = 1 << fractionBits;
        this.mask = (-1 << this.shiftBits) >>> this.shiftBits;
        this.size = Math.ceil((integerBits + fractionBits) / 8);
        if (this.signed) {
            const maxInt = this.clearMostSigBit(this.mask);
            this.min = this.fromUInt(maxInt - this.mask);
            this.max = this.fromUInt(maxInt);
        }
        else {
            this.min = 0;
            this.max = this.fromUInt(this.mask);
        }
    }
    clearMostSigBit(n) {
        let mask = n;
        mask |= mask >>> 1;
        mask |= mask >>> 2;
        mask |= mask >>> 4;
        mask |= mask >>> 8;
        mask |= mask >>> 16;
        mask = mask >>> 1;
        return n & mask;
    }
    fromUInt(n) {
        if (this.signed) {
            n = (n << this.shiftBits) >> this.shiftBits;
        }
        else {
            n = (n << this.shiftBits) >>> this.shiftBits;
        }
        return n / this.exponent;
    }
    toUInt(x) {
        return ((x * this.exponent) & this.mask) >>> 0;
    }
    from(x) {
        return this.fromUInt(this.toUInt(x));
    }
    read(bp) {
        switch (this.size) {
            case 1:
                return this.fromUInt(bp.uint8());
            case 2:
                return this.fromUInt(bp.uint16());
            case 3:
                return this.fromUInt((bp.uint8() << 16) | bp.uint16());
            case 4:
                return this.fromUInt(bp.uint32());
            default:
                throw errors_1.Errors.Primitives.UnsupportedIntSize();
        }
    }
    write(bb, n) {
        switch (this.size) {
            case 1:
                bb.uint8(this.toUInt(n));
                break;
            case 2:
                bb.uint16(this.toUInt(n));
                break;
            case 3:
                {
                    const iv = this.toUInt(n);
                    bb.uint8((iv >>> 16) & 0xff);
                    bb.uint16(iv & 0xffff);
                }
                break;
            case 4:
                bb.uint32(this.toUInt(n));
                break;
            default:
                throw errors_1.Errors.Primitives.UnsupportedIntSize();
        }
    }
}
exports.Fixed = Fixed;
exports.UInt8 = new Fixed(false, 8, 0);
exports.UInt16 = new Fixed(false, 16, 0);
exports.UInt24 = new Fixed(false, 24, 0);
exports.UInt32 = new Fixed(false, 32, 0);
exports.Int8 = new Fixed(true, 8, 0);
exports.Int16 = new Fixed(true, 16, 0);
exports.Int24 = new Fixed(true, 24, 0);
exports.Int32 = new Fixed(true, 32, 0);
exports.UIntN = [exports.UInt8, exports.UInt16, exports.UInt24, exports.UInt32];
exports.IntN = [exports.Int8, exports.Int16, exports.Int24, exports.Int32];
exports.F16D16 = new Fixed(true, 16, 16);
exports.F24D6 = new Fixed(true, 24, 6);
exports.F2D14 = new Fixed(true, 2, 14);
//# sourceMappingURL=fixed.js.map