tough-rational
Version:
Rational class using BigInt with fallback to bignumber.js
161 lines (144 loc) • 3.36 kB
JavaScript
;
const BN = require('bignumber.js');
const util = require('./util');
const RationalInterfaceProto = require('./interface');
const parse = require('./fallback/parse');
BN.config({ ERRORS: false, DECIMAL_PLACES: 100 });
const mapCastToRational = util.map((v) => new Rational(v));
const mapToEncapsulatedRational = util.map(util.method('_getEncapsulatedRational'));
const castAndMapToEncapsulatedRational = util.flow(mapCastToRational, mapToEncapsulatedRational);
const createRational = (v) => new Rational(v);
const castResultToRational = (fn) => (...args) => createRational(fn(...args));
const toNonCoerced = (fn) => (...args) => fn(...castAndMapToEncapsulatedRational(args));
const toCoerced = util.flow(toNonCoerced, castResultToRational);
const mapToNonCoerced = util.map(toNonCoerced);
const mapToCoerced = util.map(toCoerced);
const maybeCoerceToRational = (n) => n instanceof BN ? new Rational(n) : typeof n === 'string' && n.replace(/,/g, '') || n;
const RationalSuperProto = Object.assign(Object.create(RationalInterfaceProto), {
_getEncapsulatedRational: util.shiftThis(util.property('_rational')),
_setEncapsulatedRational: util.setter('_rational')
});
const toShimmedMethod = (name) => (a, b) => a[name](b);
const mapToShimmedMethod = util.map(toShimmedMethod);
const [
multiply,
dividedBy,
dividedToIntegerBy,
plus,
minus,
pow,
mod
] = mapToCoerced(mapToShimmedMethod([
'multipliedBy',
'div',
'dividedToIntegerBy',
'plus',
'minus',
'pow',
'mod'
]));
const [
isZero,
eq,
gt,
geq,
lt,
leq,
isFinite,
isNaN,
cmp
] = mapToNonCoerced(mapToShimmedMethod([
'isZero',
'eq',
'gt',
'gte',
'lt',
'lte',
'isFinite',
'isNaN',
'comparedTo'
]));
const [
abs,
pow10,
div10,
fractionalComponent,
floor,
ceil,
shiftLeft,
shiftRight,
round
] = mapToCoerced([
require('./fallback/abs'),
require('./fallback/pow10'),
require('./fallback/div10'),
require('./fallback/fractional-component'),
require('./fallback/floor'),
require('./fallback/ceil'),
require('./fallback/shift-left'),
require('./fallback/shift-right'),
require('./fallback/round')
]);
const [
isNonZero,
neq,
isFloatingPoint,
ltZero,
gtZero,
isInfinity,
toString,
toHexString
] = mapToNonCoerced([
require('./fallback/is-non-zero'),
require('./fallback/neq'),
require('./fallback/is-floating-point'),
require('./fallback/lt-zero'),
require('./fallback/gt-zero'),
require('./fallback/is-infinity'),
require('./fallback/to-string'),
require('./fallback/to-hex-string')
]);
function Rational(input) {
if (!(this instanceof Rational)) return new Rational(input);
this._setEncapsulatedRational(parse.parseDynamic(input));
}
const toDecimalFallback = require('./fallback/to-decimal');
Rational.prototype = Object.assign(Object.create(RationalSuperProto), util.mapToShifted({
multiply,
dividedBy,
dividedToIntegerBy,
abs,
plus,
minus,
pow,
floor,
ceil,
mod,
isZero,
eq,
gt,
geq,
lt,
leq,
isFinite,
isNaN,
abs,
pow10,
div10,
fractionalComponent,
isNonZero,
neq,
isFloatingPoint,
ltZero,
gtZero,
isInfinity,
toString,
shiftLeft,
shiftRight,
toHexString,
round,
cmp,
toDecimal: toNonCoerced(toDecimalFallback)
}));
util.restoreConstructor(Rational);
module.exports = Rational;