ilp-protocol-stream
Version:
Interledger Transport Protocol for sending multiple streams of money and data over ILP.
102 lines • 3.73 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = __importDefault(require("assert"));
const long_1 = __importDefault(require("long"));
const long_2 = require("./long");
class Rational {
constructor(numer, denom, unsigned) {
if (!unsigned) {
throw new Error('signed rationals are not implemented');
}
assert_1.default.strictEqual(numer.unsigned, unsigned, 'numerator is incorrectly signed');
assert_1.default.strictEqual(denom.unsigned, unsigned, 'denominator is incorrectly signed');
(0, assert_1.default)(!denom.isZero(), 'denominator must be non-zero');
this.a = numer;
this.b = denom;
this.unsigned = unsigned;
}
static isRational(value) {
return value instanceof Rational;
}
static fromNumbers(numer, denom, unsigned) {
return new Rational(long_1.default.fromNumber(numer, unsigned), long_1.default.fromNumber(denom, unsigned), unsigned);
}
static fromNumber(value, unsigned) {
if (!isFinite(value)) {
throw new Error('value must be finite');
}
else if (unsigned && value < 0) {
throw new Error('unsigned value must be positive');
}
if (value % 1 === 0) {
return Rational.fromNumbers(value, 1, unsigned);
}
const mag = Math.floor(Math.log(value) / Math.LN10);
let shift = mag < 0 ? 18 : 18 - mag;
let den = 1;
while (Math.floor(value * den) !== value * den && shift > 0) {
den *= 10;
shift--;
}
return Rational.fromNumbers(value * den, den, unsigned);
}
multiplyByLong(value) {
return (0, long_2.multiplyDivideFloor)(value, this.a, this.b);
}
multiplyByLongCeil(value) {
return (0, long_2.multiplyDivideCeil)(value, this.a, this.b);
}
multiplyByRational(other) {
return new Rational(this.a.multiply(other.a), this.b.multiply(other.b), this.unsigned);
}
greaterThanOne() {
return this.a.greaterThan(this.b);
}
complement() {
if (this.a.greaterThan(this.b)) {
throw new Error('cannot take complement of rational >1');
}
return new Rational(this.b.subtract(this.a), this.b, this.unsigned);
}
reciprocal() {
return new Rational(this.b, this.a, this.unsigned);
}
toNumber() {
return this.a.toNumber() / this.b.toNumber();
}
toString() {
const str = trimRight(this.toFixed(19), '0');
return str[str.length - 1] === '.' ? str.slice(0, -1) : str;
}
toFixed(digits) {
digits = digits || 0;
const quotient = this.a.divide(this.b);
if (digits === 0) {
return quotient.toString();
}
const remainder = this.a.modulo(this.b);
const remainderString = (0, long_2.multiplyDivideRound)(remainder, power10(digits), this.b).toString();
return quotient.toString() + '.' + '0'.repeat(digits - remainderString.length) + remainderString;
}
}
exports.default = Rational;
Rational.UZERO = new Rational(long_1.default.UZERO, long_1.default.UONE, true);
function trimRight(str, ch) {
for (let i = str.length - 1; i >= 0; i--) {
if (str[i] !== ch) {
return str.slice(0, i + 1);
}
}
return '';
}
function power10(n) {
const ten = long_1.default.fromNumber(10, true);
let value = long_1.default.UONE;
while (n--)
value = value.multiply(ten);
return value;
}
//# sourceMappingURL=rational.js.map