@klayr/utils
Version:
Library containing generic utility functions for use with Klayr-related software
127 lines • 3.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Q = exports.q = void 0;
const constants_1 = require("./constants");
const numberToQ = (val, base) => {
if (Number.isInteger(val)) {
return BigInt(val) << base;
}
const [intStr, fractionalStr] = val.toString().split('.');
return ((BigInt(intStr) << base) +
(BigInt(fractionalStr) << base) / BigInt(10) ** BigInt(fractionalStr.length));
};
const q = (val, base) => Q.fromValue(val, base);
exports.q = q;
class Q {
constructor(val, base) {
this._val = val;
this._base = BigInt(base);
}
static fromValue(val, base) {
if (val instanceof Q) {
return new Q(val._val, val._base);
}
const bigintBase = BigInt(base);
if (typeof val === 'number') {
return new Q(numberToQ(val, bigintBase), bigintBase);
}
if (typeof val === 'bigint') {
return new Q(val * constants_1.TWO ** bigintBase, bigintBase);
}
if (val.equals(Buffer.alloc(0))) {
return new Q(BigInt(0), bigintBase);
}
return new Q(BigInt(`0x${val.toString('hex')}`), bigintBase);
}
add(n) {
this._checkBase(n);
return new Q(this._val + n._val, this._base);
}
sub(n) {
this._checkBase(n);
if (this._val < n._val) {
throw new Error('Invalid input, output cannot be negative.');
}
return new Q(this._val - n._val, this._base);
}
mul(n) {
this._checkBase(n);
return new Q((this._val * n._val) >> this._base, this._base);
}
div(n) {
this._checkBase(n);
if (n._val === constants_1.ZERO) {
throw new Error('Cannot be divided by zero.');
}
return new Q((this._val << this._base) / n._val, this._base);
}
muldiv(n, m, operation = 1) {
this._checkBase(n);
this._checkBase(m);
if (m._val === constants_1.ZERO) {
throw new Error('Cannot be divided by zero.');
}
const mulResult = this._val * n._val;
const scaledResult = mulResult << this._base;
const divResult = scaledResult / m._val;
if (operation === 1) {
return new Q(this._roundDown(divResult), this._base);
}
return new Q(this._roundUp(divResult), this._base);
}
inv() {
const numerator = new Q(constants_1.ONE << this._base, this._base);
return numerator.div(this);
}
toBuffer() {
return Buffer.from(this._bigintToHex(this._val), 'hex');
}
eq(n) {
return this._val === n._val;
}
lt(n) {
return this._val < n._val;
}
lte(n) {
return this._val <= n._val;
}
gt(n) {
return this._val > n._val;
}
gte(n) {
return this._val >= n._val;
}
floor() {
return this._roundDown(this._val);
}
ceil() {
return this._roundUp(this._val);
}
_checkBase(n) {
if (this._base !== n._base) {
throw new Error('Invalid input, base does not match.');
}
}
_roundDown(n) {
return n >> this._base;
}
_roundUp(n) {
const result = n >> this._base;
if (n % (constants_1.ONE << this._base) === BigInt(0)) {
return result;
}
return result + constants_1.ONE;
}
_bigintToHex(val) {
if (val === BigInt(0)) {
return '';
}
const result = val.toString(16);
if (result.length % 2 === 0) {
return result;
}
return `0${result}`;
}
}
exports.Q = Q;
//# sourceMappingURL=q.js.map