nerdamer 1.1.13 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +184 -0
- package/README.md +293 -312
- package/dist/bundle.js +2 -0
- package/dist/bundle.js.LICENSE.txt +7 -0
- package/dist/parser.js +2 -0
- package/dist/parser.js.LICENSE.txt +7 -0
- package/docs-data/parser-functions.json +1960 -0
- package/index.d.ts +10 -426
- package/output/algebra/adapters.d.ts +33 -0
- package/output/algebra/adapters.js +109 -0
- package/output/algebra/algorithms/arith.d.ts +84 -0
- package/output/algebra/algorithms/arith.js +323 -0
- package/output/algebra/algorithms/factor.d.ts +3 -0
- package/output/algebra/algorithms/factor.js +5 -0
- package/output/algebra/algorithms/factorMultivariate.d.ts +23 -0
- package/output/algebra/algorithms/factorMultivariate.js +2393 -0
- package/output/algebra/algorithms/factorUnivariate.d.ts +72 -0
- package/output/algebra/algorithms/factorUnivariate.js +1072 -0
- package/output/algebra/algorithms/gcd.d.ts +22 -0
- package/output/algebra/algorithms/gcd.js +690 -0
- package/output/algebra/algorithms/groebnerBase.d.ts +157 -0
- package/output/algebra/algorithms/groebnerBase.js +1166 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +137 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.js +346 -0
- package/output/algebra/algorithms/poly.d.ts +228 -0
- package/output/algebra/algorithms/poly.js +1299 -0
- package/output/algebra/algorithms/rational.d.ts +17 -0
- package/output/algebra/algorithms/rational.js +115 -0
- package/output/algebra/factor/factor.d.ts +62 -0
- package/output/algebra/factor/factor.js +158 -0
- package/output/algebra/gcd/gcd.d.ts +29 -0
- package/output/algebra/gcd/gcd.js +141 -0
- package/output/algebra/groebner.d.ts +21 -0
- package/output/algebra/groebner.js +42 -0
- package/output/algebra/partfrac.d.ts +19 -0
- package/output/algebra/partfrac.js +398 -0
- package/output/algebra/polynomialize.d.ts +20 -0
- package/output/algebra/polynomialize.js +24 -0
- package/output/algebra/simplify/complexsimp.d.ts +7 -0
- package/output/algebra/simplify/complexsimp.js +24 -0
- package/output/algebra/simplify/factorCommon.d.ts +13 -0
- package/output/algebra/simplify/factorCommon.js +136 -0
- package/output/algebra/simplify/funcsimp.d.ts +26 -0
- package/output/algebra/simplify/funcsimp.js +633 -0
- package/output/algebra/simplify/invtrigrewrite.d.ts +10 -0
- package/output/algebra/simplify/invtrigrewrite.js +96 -0
- package/output/algebra/simplify/ratsimp.d.ts +21 -0
- package/output/algebra/simplify/ratsimp.js +140 -0
- package/output/algebra/simplify/simplify.d.ts +25 -0
- package/output/algebra/simplify/simplify.js +228 -0
- package/output/algebra/simplify/trigreduce.d.ts +38 -0
- package/output/algebra/simplify/trigreduce.js +424 -0
- package/output/algebra/simplify/trigrewrite.d.ts +17 -0
- package/output/algebra/simplify/trigrewrite.js +156 -0
- package/output/algebra/simplify/trigsimp.d.ts +11 -0
- package/output/algebra/simplify/trigsimp.js +369 -0
- package/output/algebra/simplify/utils.d.ts +32 -0
- package/output/algebra/simplify/utils.js +56 -0
- package/output/algebra/utils.d.ts +32 -0
- package/output/algebra/utils.js +48 -0
- package/output/api/advanced.d.ts +7 -0
- package/output/api/advanced.js +18 -0
- package/output/api/algebra.d.ts +17 -0
- package/output/api/algebra.js +32 -0
- package/output/api/assumptions.d.ts +4 -0
- package/output/api/assumptions.js +11 -0
- package/output/api/calculus.d.ts +9 -0
- package/output/api/calculus.js +21 -0
- package/output/api/core.d.ts +17 -0
- package/output/api/core.js +41 -0
- package/output/api/debug.d.ts +16 -0
- package/output/api/debug.js +23 -0
- package/output/api/parser.d.ts +85 -0
- package/output/api/parser.js +16 -0
- package/output/api/solve.d.ts +10 -0
- package/output/api/solve.js +16 -0
- package/output/api/structures.d.ts +10 -0
- package/output/api/structures.js +22 -0
- package/output/calculus/derivative/diff.d.ts +30 -0
- package/output/calculus/derivative/diff.js +238 -0
- package/output/calculus/fresnel.d.ts +16 -0
- package/output/calculus/fresnel.js +39 -0
- package/output/calculus/integrate/byParts.d.ts +18 -0
- package/output/calculus/integrate/byParts.js +339 -0
- package/output/calculus/integrate/bySubstitution.d.ts +135 -0
- package/output/calculus/integrate/bySubstitution.js +411 -0
- package/output/calculus/integrate/integrate.d.ts +38 -0
- package/output/calculus/integrate/integrate.js +652 -0
- package/output/calculus/integrate/integrationTable.d.ts +2 -0
- package/output/calculus/integrate/integrationTable.js +914 -0
- package/output/calculus/integrate/utils.d.ts +28 -0
- package/output/calculus/integrate/utils.js +96 -0
- package/output/calculus/laplace/ilaplace.d.ts +31 -0
- package/output/calculus/laplace/ilaplace.js +192 -0
- package/output/calculus/laplace/ilaplaceTable.d.ts +2 -0
- package/output/calculus/laplace/ilaplaceTable.js +200 -0
- package/output/calculus/laplace/laplace.d.ts +22 -0
- package/output/calculus/laplace/laplace.js +109 -0
- package/output/calculus/laplace/laplaceTable.d.ts +2 -0
- package/output/calculus/laplace/laplaceTable.js +187 -0
- package/output/calculus/limit/limit.d.ts +35 -0
- package/output/calculus/limit/limit.js +1183 -0
- package/output/calculus/limit/limitsTable.d.ts +2 -0
- package/output/calculus/limit/limitsTable.js +7 -0
- package/output/core/Settings.d.ts +32 -0
- package/output/core/Settings.js +68 -0
- package/output/core/adapters.d.ts +18 -0
- package/output/core/adapters.js +40 -0
- package/output/core/classes/assumption/Assumption.d.ts +218 -0
- package/output/core/classes/assumption/Assumption.js +605 -0
- package/output/core/classes/assumption/assertiveFunctions.d.ts +6 -0
- package/output/core/classes/assumption/assertiveFunctions.js +64 -0
- package/output/core/classes/assumption/assume.d.ts +90 -0
- package/output/core/classes/assumption/assume.js +145 -0
- package/output/core/classes/collection/Collection.d.ts +107 -0
- package/output/core/classes/collection/Collection.js +231 -0
- package/output/core/classes/complex/Complex.d.ts +99 -0
- package/output/core/classes/complex/Complex.js +135 -0
- package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
- package/output/core/classes/decimalSet/DecimalSet.js +453 -0
- package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
- package/output/core/classes/dictionary/Dictionary.js +213 -0
- package/output/core/classes/equation/Equation.d.ts +256 -0
- package/output/core/classes/equation/Equation.js +350 -0
- package/output/core/classes/expression/CoeffObject.d.ts +100 -0
- package/output/core/classes/expression/CoeffObject.js +198 -0
- package/output/core/classes/expression/Expression.d.ts +1674 -0
- package/output/core/classes/expression/Expression.js +2332 -0
- package/output/core/classes/expression/analysis.d.ts +25 -0
- package/output/core/classes/expression/analysis.js +218 -0
- package/output/core/classes/expression/collect.d.ts +9 -0
- package/output/core/classes/expression/collect.js +49 -0
- package/output/core/classes/expression/format.d.ts +45 -0
- package/output/core/classes/expression/format.js +217 -0
- package/output/core/classes/expression/products.d.ts +23 -0
- package/output/core/classes/expression/products.js +115 -0
- package/output/core/classes/expression/shortcuts.d.ts +35 -0
- package/output/core/classes/expression/shortcuts.js +129 -0
- package/output/core/classes/expression/traversal.d.ts +31 -0
- package/output/core/classes/expression/traversal.js +216 -0
- package/output/core/classes/expression/trig.d.ts +25 -0
- package/output/core/classes/expression/trig.js +40 -0
- package/output/core/classes/expression/utils.d.ts +52 -0
- package/output/core/classes/expression/utils.js +189 -0
- package/output/core/classes/lookupTable/LookupTable.d.ts +12 -0
- package/output/core/classes/lookupTable/LookupTable.js +55 -0
- package/output/core/classes/matrix/Matrix.d.ts +227 -0
- package/output/core/classes/matrix/Matrix.js +889 -0
- package/output/core/classes/matrix/Sylvester.d.ts +11 -0
- package/output/core/classes/matrix/Sylvester.js +54 -0
- package/output/core/classes/matrix/functions.d.ts +26 -0
- package/output/core/classes/matrix/functions.js +52 -0
- package/output/core/classes/matrix/utils.d.ts +9 -0
- package/output/core/classes/matrix/utils.js +22 -0
- package/output/core/classes/parser/Parser.d.ts +480 -0
- package/output/core/classes/parser/Parser.js +1812 -0
- package/output/core/classes/parser/Token.d.ts +58 -0
- package/output/core/classes/parser/Token.js +137 -0
- package/output/core/classes/parser/constants.d.ts +160 -0
- package/output/core/classes/parser/constants.js +227 -0
- package/output/core/classes/parser/helpers.d.ts +21 -0
- package/output/core/classes/parser/helpers.js +42 -0
- package/output/core/classes/parser/operations/add.d.ts +15 -0
- package/output/core/classes/parser/operations/add.js +238 -0
- package/output/core/classes/parser/operations/comma.d.ts +7 -0
- package/output/core/classes/parser/operations/comma.js +11 -0
- package/output/core/classes/parser/operations/compare.d.ts +21 -0
- package/output/core/classes/parser/operations/compare.js +461 -0
- package/output/core/classes/parser/operations/divide.d.ts +2 -0
- package/output/core/classes/parser/operations/divide.js +72 -0
- package/output/core/classes/parser/operations/functions.d.ts +46 -0
- package/output/core/classes/parser/operations/functions.js +430 -0
- package/output/core/classes/parser/operations/multiply.d.ts +11 -0
- package/output/core/classes/parser/operations/multiply.js +321 -0
- package/output/core/classes/parser/operations/power.d.ts +48 -0
- package/output/core/classes/parser/operations/power.js +673 -0
- package/output/core/classes/parser/operations/subtract.d.ts +3 -0
- package/output/core/classes/parser/operations/subtract.js +35 -0
- package/output/core/classes/parser/preprocess.d.ts +14 -0
- package/output/core/classes/parser/preprocess.js +259 -0
- package/output/core/classes/parser/scripting/controlFlow.d.ts +121 -0
- package/output/core/classes/parser/scripting/controlFlow.js +355 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +10 -0
- package/output/core/classes/parser/scripting/evaluate.js +112 -0
- package/output/core/classes/parser/scripting/functions.d.ts +14 -0
- package/output/core/classes/parser/scripting/functions.js +59 -0
- package/output/core/classes/parser/scripting/scope.d.ts +35 -0
- package/output/core/classes/parser/scripting/scope.js +155 -0
- package/output/core/classes/parser/types.d.ts +125 -0
- package/output/core/classes/parser/types.js +2 -0
- package/output/core/classes/parser/wrappers/IndexedReference.d.ts +31 -0
- package/output/core/classes/parser/wrappers/IndexedReference.js +68 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +24 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.js +51 -0
- package/output/core/classes/polynomial/Polynomial.d.ts +500 -0
- package/output/core/classes/polynomial/Polynomial.js +1149 -0
- package/output/core/classes/polynomial/Term.d.ts +222 -0
- package/output/core/classes/polynomial/Term.js +430 -0
- package/output/core/classes/polynomial/functions.d.ts +69 -0
- package/output/core/classes/polynomial/functions.js +126 -0
- package/output/core/classes/polynomial/utils.d.ts +62 -0
- package/output/core/classes/polynomial/utils.js +206 -0
- package/output/core/classes/rational/Rational.d.ts +504 -0
- package/output/core/classes/rational/Rational.js +779 -0
- package/output/core/classes/seq/SEQ.d.ts +13 -0
- package/output/core/classes/seq/SEQ.js +137 -0
- package/output/core/classes/valuesSet/ValuesSet.d.ts +179 -0
- package/output/core/classes/valuesSet/ValuesSet.js +381 -0
- package/output/core/classes/vector/Vector.d.ts +222 -0
- package/output/core/classes/vector/Vector.js +497 -0
- package/output/core/classes/vector/functions.d.ts +28 -0
- package/output/core/classes/vector/functions.js +47 -0
- package/output/core/common/classes/MathematicalAggregate.d.ts +53 -0
- package/output/core/common/classes/MathematicalAggregate.js +140 -0
- package/output/core/common/classes/Scope.d.ts +62 -0
- package/output/core/common/classes/Scope.js +122 -0
- package/output/core/common/classes/StructuredEntity.d.ts +55 -0
- package/output/core/common/classes/StructuredEntity.js +151 -0
- package/output/core/common/common.d.ts +63 -0
- package/output/core/common/common.js +279 -0
- package/output/core/common/functions/functions.d.ts +14 -0
- package/output/core/common/functions/functions.js +33 -0
- package/output/core/common/functions/structuredEntityUtils.d.ts +27 -0
- package/output/core/common/functions/structuredEntityUtils.js +40 -0
- package/output/core/converters/BaseConverter.d.ts +97 -0
- package/output/core/converters/BaseConverter.js +405 -0
- package/output/core/converters/Converter.d.ts +111 -0
- package/output/core/converters/Converter.js +802 -0
- package/output/core/converters/Pattern.d.ts +71 -0
- package/output/core/converters/Pattern.js +302 -0
- package/output/core/dispatch.d.ts +34 -0
- package/output/core/dispatch.js +304 -0
- package/output/core/errors.d.ts +531 -0
- package/output/core/errors.js +621 -0
- package/output/core/functions/bigint/bigint.d.ts +121 -0
- package/output/core/functions/bigint/bigint.js +392 -0
- package/output/core/functions/bigint/primeFactor.d.ts +49 -0
- package/output/core/functions/bigint/primeFactor.js +267 -0
- package/output/core/functions/bigint/primes.d.ts +1 -0
- package/output/core/functions/bigint/primes.js +11 -0
- package/output/core/functions/build/definitions.d.ts +12 -0
- package/output/core/functions/build/definitions.js +133 -0
- package/output/core/functions/build/index.d.ts +32 -0
- package/output/core/functions/build/index.js +136 -0
- package/output/core/functions/complex.d.ts +90 -0
- package/output/core/functions/complex.js +482 -0
- package/output/core/functions/decimal.d.ts +24 -0
- package/output/core/functions/decimal.js +664 -0
- package/output/core/functions/expand/expand.d.ts +42 -0
- package/output/core/functions/expand/expand.js +376 -0
- package/output/core/functions/fresnelNumeric.d.ts +12 -0
- package/output/core/functions/fresnelNumeric.js +123 -0
- package/output/core/functions/numeric.d.ts +140 -0
- package/output/core/functions/numeric.js +790 -0
- package/output/core/functions/rationalNormalization.d.ts +11 -0
- package/output/core/functions/rationalNormalization.js +117 -0
- package/output/core/functions/setFunction.d.ts +19 -0
- package/output/core/functions/setFunction.js +75 -0
- package/output/core/functions/string.d.ts +26 -0
- package/output/core/functions/string.js +101 -0
- package/output/core/functions/subst.d.ts +90 -0
- package/output/core/functions/subst.js +498 -0
- package/output/core/functions/utils.d.ts +24 -0
- package/output/core/functions/utils.js +51 -0
- package/output/core/types.d.ts +48 -0
- package/output/core/types.js +2 -0
- package/output/index.d.ts +339 -0
- package/output/index.js +715 -0
- package/output/math/defint/defintDecimal.d.ts +37 -0
- package/output/math/defint/defintDecimal.js +320 -0
- package/output/math/defint/defintNative.d.ts +57 -0
- package/output/math/defint/defintNative.js +292 -0
- package/output/math/geometry.d.ts +8 -0
- package/output/math/geometry.js +32 -0
- package/output/math/math.d.ts +655 -0
- package/output/math/math.js +1811 -0
- package/output/math/trig.d.ts +518 -0
- package/output/math/trig.js +1444 -0
- package/output/math/trunc.d.ts +19 -0
- package/output/math/trunc.js +36 -0
- package/output/math/utils.d.ts +60 -0
- package/output/math/utils.js +180 -0
- package/output/solve/classes/DecimalMatrix.d.ts +17 -0
- package/output/solve/classes/DecimalMatrix.js +86 -0
- package/output/solve/classes/FunctionSolver.d.ts +135 -0
- package/output/solve/classes/FunctionSolver.js +433 -0
- package/output/solve/classes/MultivariateSolver.d.ts +84 -0
- package/output/solve/classes/MultivariateSolver.js +240 -0
- package/output/solve/classes/PolynomialSolver.d.ts +85 -0
- package/output/solve/classes/PolynomialSolver.js +292 -0
- package/output/solve/classes/SolutionSet.d.ts +153 -0
- package/output/solve/classes/SolutionSet.js +357 -0
- package/output/solve/classes/Solver.d.ts +17 -0
- package/output/solve/classes/Solver.js +132 -0
- package/output/solve/classes/SymbolicSolver.d.ts +74 -0
- package/output/solve/classes/SymbolicSolver.js +601 -0
- package/output/solve/linsolve.d.ts +51 -0
- package/output/solve/linsolve.js +225 -0
- package/output/solve/solve.d.ts +34 -0
- package/output/solve/solve.js +260 -0
- package/output/solve/solveSystem.d.ts +31 -0
- package/output/solve/solveSystem.js +290 -0
- package/output/solve/utils.d.ts +9 -0
- package/output/solve/utils.js +62 -0
- package/output/utils/array.d.ts +42 -0
- package/output/utils/array.js +98 -0
- package/output/utils/debug.d.ts +131 -0
- package/output/utils/debug.js +295 -0
- package/output/utils/decimal.d.ts +3 -0
- package/output/utils/decimal.js +16 -0
- package/output/utils/numeric.d.ts +14 -0
- package/output/utils/numeric.js +51 -0
- package/output/utils/object.d.ts +26 -0
- package/output/utils/object.js +56 -0
- package/package.json +213 -57
- package/.travis.yml +0 -3
- package/Algebra.js +0 -4568
- package/BREAKING_CHANGES.md +0 -5
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -14
- package/Calculus.js +0 -2675
- package/Extra.js +0 -622
- package/Solve.js +0 -1783
- package/all.js +0 -16
- package/all.min.js +0 -1
- package/gulpfile.js +0 -16
- package/index.html +0 -158
- package/license.txt +0 -19
- package/nerdamer.core.js +0 -12510
- package/spec/LaTeX.spec.js +0 -302
- package/spec/TeXConvert.spec.js +0 -8
- package/spec/algebra.spec.js +0 -287
- package/spec/basic_parser.spec.js +0 -134
- package/spec/build.spec.js +0 -131
- package/spec/calculus.spec.js +0 -183
- package/spec/core.spec.js +0 -2970
- package/spec/extra.spec.js +0 -54
- package/spec/solve.spec.js +0 -126
- package/spec/support/jasmine.json +0 -11
- package/spec/support/utils.js +0 -42
- package/spec/text.spec.js +0 -132
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Rational = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const common_1 = require("../../common/common");
|
|
9
|
+
const errors_1 = require("../../errors");
|
|
10
|
+
const bigint_1 = require("../../functions/bigint/bigint");
|
|
11
|
+
const bigint_2 = require("../../functions/bigint/bigint");
|
|
12
|
+
const string_1 = require("../../functions/string");
|
|
13
|
+
const Expression_1 = require("../expression/Expression");
|
|
14
|
+
const constants_1 = require("../parser/constants");
|
|
15
|
+
/**
|
|
16
|
+
* Represents an exact rational value as a `bigint` numerator and denominator.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* Core rational arithmetic is exact: decimal and scientific-notation input is converted to
|
|
20
|
+
* the exact fraction represented by the input text rather than stored as a floating-point
|
|
21
|
+
* approximation. The notable exception is non-integer {@link Rational.pow}, which uses
|
|
22
|
+
* `decimal.js` numerical exponentiation. The {@link Rational.asDecimal} flag records
|
|
23
|
+
* presentation intent only; it does not change the underlying rational representation.
|
|
24
|
+
*
|
|
25
|
+
* Values produced by {@link Rational.create} and the arithmetic methods are normally reduced
|
|
26
|
+
* and use a positive denominator. The public constructor is lower level: it stores its two
|
|
27
|
+
* `bigint` arguments exactly as supplied and does not reduce the fraction, normalize the
|
|
28
|
+
* denominator sign, or reject a zero denominator. Sign, comparison, and integer helpers assume
|
|
29
|
+
* the normal representation, so callers constructing values directly are responsible for
|
|
30
|
+
* preserving that representation.
|
|
31
|
+
*
|
|
32
|
+
* `Rational` instances are mutable because their representation fields are public and
|
|
33
|
+
* {@link Rational.updateValue} updates the instance in place. The ordinary arithmetic methods
|
|
34
|
+
* return new values and do not mutate their operands.
|
|
35
|
+
*/
|
|
36
|
+
class Rational {
|
|
37
|
+
/**
|
|
38
|
+
* Finite-precision rational approximation of Euler's number at the current configured precision.
|
|
39
|
+
*
|
|
40
|
+
* Recomputed when {@link Rational.set} changes the precision.
|
|
41
|
+
*/
|
|
42
|
+
static E = Rational.create(constants_1.PARSER_CONSTANTS.e());
|
|
43
|
+
/**
|
|
44
|
+
* Finite-precision rational approximation of pi at the current configured precision.
|
|
45
|
+
*
|
|
46
|
+
* Recomputed when {@link Rational.set} changes the precision.
|
|
47
|
+
*/
|
|
48
|
+
static PI = Rational.create(constants_1.PARSER_CONSTANTS.pi());
|
|
49
|
+
/**
|
|
50
|
+
* Precision setting shared with `decimal.js` and used as the default digit count by
|
|
51
|
+
* {@link Rational.toDecimalString}. Change it through {@link Rational.set}.
|
|
52
|
+
*/
|
|
53
|
+
static precision = decimal_js_1.default.precision;
|
|
54
|
+
/**
|
|
55
|
+
* Whether text output should preserve decimal presentation by default.
|
|
56
|
+
*
|
|
57
|
+
* This flag does not change the exact numerator/denominator representation. Most rational
|
|
58
|
+
* arithmetic propagates decimal intent when either operand has it set.
|
|
59
|
+
*/
|
|
60
|
+
asDecimal = false;
|
|
61
|
+
/** Marker used by Nerdamer's runtime type guards. */
|
|
62
|
+
dataType = constants_1.RATIONAL;
|
|
63
|
+
/** Denominator of the exact rational representation. */
|
|
64
|
+
denominator;
|
|
65
|
+
/** Numerator of the exact rational representation. */
|
|
66
|
+
numerator;
|
|
67
|
+
/**
|
|
68
|
+
* The supplied textual value.
|
|
69
|
+
*
|
|
70
|
+
* Numeric behavior is defined by {@link Rational.numerator} and
|
|
71
|
+
* {@link Rational.denominator}; callers should not treat this field as an independent
|
|
72
|
+
* authoritative numeric representation.
|
|
73
|
+
*/
|
|
74
|
+
value;
|
|
75
|
+
/**
|
|
76
|
+
* Creates a rational from raw numerator and denominator components.
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* This constructor performs no normalization or validation. Prefer
|
|
80
|
+
* {@link Rational.create} for user input and for values that must use Nerdamer's normal
|
|
81
|
+
* reduced-fraction representation.
|
|
82
|
+
*
|
|
83
|
+
* @param a - Numerator to store.
|
|
84
|
+
* @param b - Denominator to store.
|
|
85
|
+
*/
|
|
86
|
+
constructor(a, b) {
|
|
87
|
+
this.numerator = a;
|
|
88
|
+
this.denominator = b;
|
|
89
|
+
this.value = b === 1n ? String(a) : `${a}/${b}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Tests whether every supplied rational is strictly negative.
|
|
93
|
+
*
|
|
94
|
+
* @param args - Rational values to test.
|
|
95
|
+
* @returns `true` when each value has sign `-1`.
|
|
96
|
+
*/
|
|
97
|
+
static allNegative(...args) {
|
|
98
|
+
for (const e of args) {
|
|
99
|
+
if (e.sign() !== -1) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates a normalized rational from an integer, fraction, decimal, or scientific-notation value.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* Fraction strings are reduced and a negative denominator is moved to the numerator. Decimal
|
|
110
|
+
* and scientific-notation strings are converted to the exact rational represented by their
|
|
111
|
+
* finite decimal text. Those forms also set {@link Rational.asDecimal}, so later text output
|
|
112
|
+
* normally remains decimal even though the stored arithmetic stays exact.
|
|
113
|
+
*
|
|
114
|
+
* @param value - Integer `bigint` or numeric string to convert.
|
|
115
|
+
* @returns A new normalized `Rational`.
|
|
116
|
+
*
|
|
117
|
+
* @throws {@link DivisionByZeroError}
|
|
118
|
+
* Thrown when a fraction string has a zero denominator.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* Rational.create('2/4').text(); // "1/2"
|
|
123
|
+
* Rational.create('0.125').text(); // "0.125"
|
|
124
|
+
* Rational.create('4e1').text(); // "40.0"
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
static create(value) {
|
|
128
|
+
let a;
|
|
129
|
+
let b;
|
|
130
|
+
let asDecimal = false;
|
|
131
|
+
if (typeof value === 'bigint') {
|
|
132
|
+
a = value;
|
|
133
|
+
b = 1n;
|
|
134
|
+
value = String(a);
|
|
135
|
+
}
|
|
136
|
+
else if (/^[+-]?\d+$/.test(value)) {
|
|
137
|
+
a = BigInt(value);
|
|
138
|
+
b = 1n;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
if (value.includes('/')) {
|
|
142
|
+
[a, b] = value.split('/').map(x => BigInt(x));
|
|
143
|
+
if (b === 0n) {
|
|
144
|
+
throw new errors_1.DivisionByZeroError((0, errors_1.message)('divisionByZero'));
|
|
145
|
+
}
|
|
146
|
+
if (b < 0n) {
|
|
147
|
+
a = -a;
|
|
148
|
+
b = -b;
|
|
149
|
+
}
|
|
150
|
+
[a, b] = (0, bigint_1.simplifyRatio)(a, b);
|
|
151
|
+
value = b === 1n ? String(a) : `${a}/${b}`;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const isScientific = value.toLocaleLowerCase().includes('e');
|
|
155
|
+
asDecimal = isScientific || value.includes(constants_1.DOT);
|
|
156
|
+
if (isScientific) {
|
|
157
|
+
value = (0, string_1.scientificToDecimal)(value);
|
|
158
|
+
// All scientific numbers are decimal
|
|
159
|
+
asDecimal = true;
|
|
160
|
+
}
|
|
161
|
+
[a, b] = (0, bigint_1.convert)(value);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const rational = new Rational(a, b);
|
|
165
|
+
rational.value = value;
|
|
166
|
+
rational.asDecimal = asDecimal;
|
|
167
|
+
return rational;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Computes the rational greatest common divisor across the supplied values.
|
|
171
|
+
*
|
|
172
|
+
* @remarks
|
|
173
|
+
* The operation is folded pairwise and preserves decimal presentation intent when it is
|
|
174
|
+
* present on an operand.
|
|
175
|
+
*
|
|
176
|
+
* @param args - Rational values whose common divisor should be computed.
|
|
177
|
+
* @returns The pairwise rational GCD.
|
|
178
|
+
*/
|
|
179
|
+
static GCD(...args) {
|
|
180
|
+
let retval = args[0];
|
|
181
|
+
for (let i = 1; i < args.length; i++) {
|
|
182
|
+
retval = retval.GCD(args[i]);
|
|
183
|
+
}
|
|
184
|
+
return retval;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Returns the currently configured rational/Decimal precision setting.
|
|
188
|
+
*
|
|
189
|
+
* @returns The configured precision value.
|
|
190
|
+
*/
|
|
191
|
+
static getPrecision() {
|
|
192
|
+
return Rational.precision;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Returns a value unchanged for compatibility with generic numeric hooks.
|
|
196
|
+
*
|
|
197
|
+
* @param value - Value to pass through.
|
|
198
|
+
* @returns The same value reference or primitive supplied by the caller.
|
|
199
|
+
*/
|
|
200
|
+
static hook(value) {
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Tests whether a value carries Nerdamer's rational runtime type marker.
|
|
205
|
+
*
|
|
206
|
+
* @remarks
|
|
207
|
+
* This is a marker-based guard rather than an `instanceof` check, which allows compatible
|
|
208
|
+
* Nerdamer rational objects to be recognized where constructor identity is not the useful
|
|
209
|
+
* distinction.
|
|
210
|
+
*
|
|
211
|
+
* @param value - Value to inspect.
|
|
212
|
+
* @returns `true` when `value.dataType` is Nerdamer's rational marker.
|
|
213
|
+
*/
|
|
214
|
+
static isRational(value) {
|
|
215
|
+
return (0, common_1.isNerdamerNativeType)(value, constants_1.RATIONAL);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Computes the rational least common multiple across the supplied values.
|
|
219
|
+
*
|
|
220
|
+
* @remarks
|
|
221
|
+
* The operation is folded pairwise and preserves decimal presentation intent when it is
|
|
222
|
+
* present on an operand.
|
|
223
|
+
*
|
|
224
|
+
* @param args - Rational values whose common multiple should be computed.
|
|
225
|
+
* @returns The pairwise rational LCM.
|
|
226
|
+
*/
|
|
227
|
+
static LCM(...args) {
|
|
228
|
+
let retval = args[0];
|
|
229
|
+
for (let i = 1; i < args.length; i++) {
|
|
230
|
+
retval = retval.LCM(args[i]);
|
|
231
|
+
}
|
|
232
|
+
return retval;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Copies a rational's representation and presentation metadata.
|
|
236
|
+
*
|
|
237
|
+
* @param x - Rational to copy.
|
|
238
|
+
* @returns A distinct `Rational` with the same numerator, denominator, `value`, and
|
|
239
|
+
* decimal-presentation flag.
|
|
240
|
+
*/
|
|
241
|
+
static makeCopy(x) {
|
|
242
|
+
const copy = new Rational(x.numerator, x.denominator);
|
|
243
|
+
copy.value = x.value;
|
|
244
|
+
copy.asDecimal = x.asDecimal;
|
|
245
|
+
return copy;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Updates shared numeric settings used by rational decimal conversion.
|
|
249
|
+
*
|
|
250
|
+
* @remarks
|
|
251
|
+
* Currently only `precision` is acted upon. Setting it updates the global `decimal.js`
|
|
252
|
+
* precision, records the value used by {@link Rational.toDecimalString}, and recomputes
|
|
253
|
+
* {@link Rational.PI} and {@link Rational.E} at the new precision.
|
|
254
|
+
*
|
|
255
|
+
* @param values - Settings object; `precision` is the supported numeric setting.
|
|
256
|
+
*/
|
|
257
|
+
static set(values) {
|
|
258
|
+
if ('precision' in values) {
|
|
259
|
+
const precision = Number(values.precision);
|
|
260
|
+
// Update the precision for decimal to match
|
|
261
|
+
decimal_js_1.default.set({
|
|
262
|
+
precision: precision,
|
|
263
|
+
});
|
|
264
|
+
// Set the precision for this class after Decimal accepts the value
|
|
265
|
+
Rational.precision = precision;
|
|
266
|
+
// Update pi
|
|
267
|
+
Rational.PI = Rational.create(constants_1.PARSER_CONSTANTS.pi());
|
|
268
|
+
Rational.E = Rational.create(constants_1.PARSER_CONSTANTS.e());
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Converts a string to a rational or normalizes rational ownership for a caller.
|
|
273
|
+
*
|
|
274
|
+
* @remarks
|
|
275
|
+
* Strings always produce a new value through {@link Rational.create}. An existing `Rational`
|
|
276
|
+
* is returned by identity unless `ensureCopy` is `true`.
|
|
277
|
+
*
|
|
278
|
+
* @param x - Numeric string or rational value.
|
|
279
|
+
* @param ensureCopy - Guarantee a distinct object when `x` is already a `Rational`.
|
|
280
|
+
* @returns The converted rational, a copy, or the original rational according to `ensureCopy`.
|
|
281
|
+
*/
|
|
282
|
+
static toRational(x, ensureCopy = false) {
|
|
283
|
+
// Convert any strings to Rationals
|
|
284
|
+
if (typeof x === 'string') {
|
|
285
|
+
return Rational.create(x);
|
|
286
|
+
}
|
|
287
|
+
// If they want a guaranteed copy then just return a copy
|
|
288
|
+
if (ensureCopy) {
|
|
289
|
+
return Rational.makeCopy(x);
|
|
290
|
+
}
|
|
291
|
+
// Otherwise just return the original rational
|
|
292
|
+
return x;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Returns the absolute value without modifying this rational.
|
|
296
|
+
*
|
|
297
|
+
* @returns A copied rational whose numerator is nonnegative.
|
|
298
|
+
*/
|
|
299
|
+
abs() {
|
|
300
|
+
const retval = this.copy();
|
|
301
|
+
retval.numerator = (0, bigint_1.abs)(retval.numerator);
|
|
302
|
+
retval.updateValue();
|
|
303
|
+
return retval;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Creates a distinct copy of this rational.
|
|
307
|
+
*
|
|
308
|
+
* @returns A new object with the same numeric representation and presentation metadata.
|
|
309
|
+
*/
|
|
310
|
+
copy() {
|
|
311
|
+
return Rational.makeCopy(this);
|
|
312
|
+
}
|
|
313
|
+
div(num) {
|
|
314
|
+
let retval;
|
|
315
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
316
|
+
retval = Expression_1.Expression.create(this).div(num);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
num = Rational.toRational(num, true);
|
|
320
|
+
// Invert and multiply
|
|
321
|
+
// There is no need to track the result type in this function since it's being handled by invert and multiply
|
|
322
|
+
retval = this.times(num.invert());
|
|
323
|
+
}
|
|
324
|
+
return retval;
|
|
325
|
+
}
|
|
326
|
+
eq(num) {
|
|
327
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
328
|
+
return Expression_1.Expression.create(this).eq(num);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
num = Rational.toRational(num);
|
|
332
|
+
return this.numerator * num.denominator === num.numerator * this.denominator;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Tests whether the stored denominator is even.
|
|
337
|
+
*
|
|
338
|
+
* @returns `true` when {@link Rational.denominator} is divisible by two.
|
|
339
|
+
*/
|
|
340
|
+
evenDenominator() {
|
|
341
|
+
return (0, bigint_1.isEven)(this.denominator);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Tests whether the stored numerator is even.
|
|
345
|
+
*
|
|
346
|
+
* @returns `true` when {@link Rational.numerator} is divisible by two.
|
|
347
|
+
*/
|
|
348
|
+
evenNumerator() {
|
|
349
|
+
return (0, bigint_1.isEven)(this.numerator);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Computes the rational greatest common divisor with another value.
|
|
353
|
+
*
|
|
354
|
+
* @param num - Rational or numeric string to combine with this value.
|
|
355
|
+
* @returns A new reduced rational GCD. Decimal presentation is preserved when either operand
|
|
356
|
+
* was marked for decimal output.
|
|
357
|
+
*/
|
|
358
|
+
GCD(num) {
|
|
359
|
+
num = Rational.toRational(num);
|
|
360
|
+
const [n, d] = (0, bigint_1.simplifyRatio)((0, bigint_2.GCD)(this.numerator * num.denominator, this.denominator * num.numerator), this.denominator * num.denominator);
|
|
361
|
+
const retval = new Rational(n, d);
|
|
362
|
+
retval.asDecimal = this.asDecimal || num.asDecimal;
|
|
363
|
+
return retval;
|
|
364
|
+
}
|
|
365
|
+
gt(num) {
|
|
366
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
367
|
+
return Expression_1.Expression.create(this).gt(num);
|
|
368
|
+
}
|
|
369
|
+
num = Rational.toRational(num);
|
|
370
|
+
return this.numerator * num.denominator > num.numerator * this.denominator;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Tests whether this rational is greater than or equal to another rational value.
|
|
374
|
+
*
|
|
375
|
+
* @param num - Rational or numeric string to compare against.
|
|
376
|
+
* @returns `true` when this rational is greater than or equal to `num`.
|
|
377
|
+
*/
|
|
378
|
+
gte(num) {
|
|
379
|
+
num = Rational.toRational(num);
|
|
380
|
+
return this.numerator * num.denominator >= num.numerator * this.denominator;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Returns the multiplicative inverse of this rational.
|
|
384
|
+
*
|
|
385
|
+
* @remarks
|
|
386
|
+
* The original object is not modified. For normally constructed rationals, the returned
|
|
387
|
+
* denominator remains positive and the sign is carried by the numerator.
|
|
388
|
+
*
|
|
389
|
+
* @returns A new rational representing `1 / this`.
|
|
390
|
+
* @throws {@link DivisionByZeroError}
|
|
391
|
+
* Thrown when this rational is exactly zero.
|
|
392
|
+
*/
|
|
393
|
+
invert() {
|
|
394
|
+
// Throw if trying to divide by zero
|
|
395
|
+
if (this.isZero()) {
|
|
396
|
+
throw new errors_1.DivisionByZeroError((0, errors_1.message)('divisionByZero'));
|
|
397
|
+
}
|
|
398
|
+
const retval = this.copy();
|
|
399
|
+
// Store the sign
|
|
400
|
+
const sgn = retval.sign();
|
|
401
|
+
// Remove it from the numerator.
|
|
402
|
+
retval.numerator = (0, bigint_1.abs)(retval.numerator);
|
|
403
|
+
// Switch them
|
|
404
|
+
[retval.numerator, retval.denominator] = [retval.denominator, retval.numerator];
|
|
405
|
+
// Put back the sign and return
|
|
406
|
+
return sgn === -1 ? retval.neg() : retval.updateValue();
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Tests whether this value is an even integer.
|
|
410
|
+
*
|
|
411
|
+
* @returns `true` only when the denominator is one and the numerator is even.
|
|
412
|
+
*/
|
|
413
|
+
isEven() {
|
|
414
|
+
return this.isInteger() && this.evenNumerator();
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Tests whether this rational is stored in integer form.
|
|
418
|
+
*
|
|
419
|
+
* @remarks
|
|
420
|
+
* This checks only whether the denominator is exactly `1n`. Values built with the raw
|
|
421
|
+
* constructor must therefore be reduced first if equivalent forms such as `8/4` should be
|
|
422
|
+
* recognized as integers.
|
|
423
|
+
*
|
|
424
|
+
* @returns `true` when the stored denominator is one.
|
|
425
|
+
*/
|
|
426
|
+
isInteger() {
|
|
427
|
+
return this.denominator === 1n;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Tests whether this rational is exactly `-1` in normalized integer form.
|
|
431
|
+
*
|
|
432
|
+
* @returns `true` for numerator `-1n` and denominator `1n`.
|
|
433
|
+
*/
|
|
434
|
+
isMinusOne() {
|
|
435
|
+
return this.numerator === -1n && this.denominator === 1n;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Tests whether the stored numerator is negative.
|
|
439
|
+
*
|
|
440
|
+
* @remarks
|
|
441
|
+
* Nerdamer's normal rational representation keeps the denominator positive, so the numerator
|
|
442
|
+
* carries the sign. Raw constructor values with a negative denominator do not follow that
|
|
443
|
+
* representation.
|
|
444
|
+
*
|
|
445
|
+
* @returns `true` when the numerator is negative.
|
|
446
|
+
*/
|
|
447
|
+
isNegative() {
|
|
448
|
+
return this.numerator < 0n;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Tests whether this rational is exactly `1` in normalized integer form.
|
|
452
|
+
*
|
|
453
|
+
* @returns `true` for numerator `1n` and denominator `1n`.
|
|
454
|
+
*/
|
|
455
|
+
isOne() {
|
|
456
|
+
return this.numerator === 1n && this.denominator === 1n;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Tests whether this rational is exactly zero.
|
|
460
|
+
*
|
|
461
|
+
* @returns `true` when the numerator is zero.
|
|
462
|
+
*/
|
|
463
|
+
isZero() {
|
|
464
|
+
return this.numerator === 0n;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Computes the rational least common multiple with another value.
|
|
468
|
+
*
|
|
469
|
+
* @param num - Rational or numeric string to combine with this value.
|
|
470
|
+
* @returns A new reduced, nonnegative rational LCM. Zero combined with any rational returns
|
|
471
|
+
* zero. Decimal presentation is preserved when either operand was marked for decimal output.
|
|
472
|
+
*/
|
|
473
|
+
LCM(num) {
|
|
474
|
+
num = Rational.toRational(num);
|
|
475
|
+
let n = 0n;
|
|
476
|
+
let d = 1n;
|
|
477
|
+
if (!this.isZero() && !num.isZero()) {
|
|
478
|
+
[n, d] = (0, bigint_1.simplifyRatio)((0, bigint_1.abs)(this.numerator * num.numerator), (0, bigint_2.GCD)(this.numerator * num.denominator, this.denominator * num.numerator));
|
|
479
|
+
}
|
|
480
|
+
const retval = new Rational(n, d);
|
|
481
|
+
retval.asDecimal = this.asDecimal || num.asDecimal;
|
|
482
|
+
return retval;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Tests whether this rational is less than another rational value.
|
|
486
|
+
*
|
|
487
|
+
* @param num - Rational or numeric string to compare against.
|
|
488
|
+
* @returns `true` when this rational is less than `num`.
|
|
489
|
+
*/
|
|
490
|
+
lt(num) {
|
|
491
|
+
num = Rational.toRational(num);
|
|
492
|
+
return this.numerator * num.denominator < num.numerator * this.denominator;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Tests whether this rational is less than or equal to another rational value.
|
|
496
|
+
*
|
|
497
|
+
* @param num - Rational or numeric string to compare against.
|
|
498
|
+
* @returns `true` when this rational is less than or equal to `num`.
|
|
499
|
+
*/
|
|
500
|
+
lte(num) {
|
|
501
|
+
num = Rational.toRational(num);
|
|
502
|
+
return this.numerator * num.denominator <= num.numerator * this.denominator;
|
|
503
|
+
}
|
|
504
|
+
minus(num) {
|
|
505
|
+
let retval;
|
|
506
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
507
|
+
retval = Expression_1.Expression.create(this).minus(num);
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
num = Rational.toRational(num, true);
|
|
511
|
+
retval = this.plus(num.neg());
|
|
512
|
+
}
|
|
513
|
+
// Negate and add
|
|
514
|
+
return retval;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Computes the exact rational modulo with another value.
|
|
518
|
+
*
|
|
519
|
+
* @remarks
|
|
520
|
+
* The operands are converted to a common denominator, Nerdamer's integer modulo operation is
|
|
521
|
+
* applied to the corresponding numerators, and the resulting fraction is reduced. Decimal
|
|
522
|
+
* presentation is preserved when either operand was marked for decimal output.
|
|
523
|
+
*
|
|
524
|
+
* @param num - Nonzero rational or numeric string used as the modulus.
|
|
525
|
+
* @returns The reduced rational remainder.
|
|
526
|
+
* @throws A native `RangeError` when `num` is zero.
|
|
527
|
+
*/
|
|
528
|
+
mod(num) {
|
|
529
|
+
num = Rational.toRational(num);
|
|
530
|
+
// Make their denominators common and get the mod of the common numerators
|
|
531
|
+
const numerator = (0, bigint_2.mod)(this.numerator * num.denominator, num.numerator * this.denominator);
|
|
532
|
+
const denominator = this.denominator * num.denominator;
|
|
533
|
+
const result = new Rational(...(0, bigint_1.simplifyRatio)(numerator, denominator));
|
|
534
|
+
result.asDecimal = this.asDecimal || num.asDecimal;
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Returns the additive inverse of this rational.
|
|
539
|
+
*
|
|
540
|
+
* @returns A new rational with the numerator sign reversed.
|
|
541
|
+
*/
|
|
542
|
+
neg() {
|
|
543
|
+
const retval = this.copy();
|
|
544
|
+
retval.numerator *= -1n;
|
|
545
|
+
retval.updateValue();
|
|
546
|
+
return retval;
|
|
547
|
+
}
|
|
548
|
+
plus(num) {
|
|
549
|
+
let retval;
|
|
550
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
551
|
+
retval = Expression_1.Expression.create(this).plus(num);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
num = Rational.toRational(num);
|
|
555
|
+
let numerator;
|
|
556
|
+
let denominator;
|
|
557
|
+
// let result: Rational = new Rational('0');
|
|
558
|
+
// If they have the same denominator then we can add the numerators.
|
|
559
|
+
if (num.denominator === this.denominator) {
|
|
560
|
+
numerator = num.numerator + this.numerator;
|
|
561
|
+
denominator = num.denominator;
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
// Fractional addition and then simplify using their gcd.
|
|
565
|
+
numerator = this.numerator * num.denominator + num.numerator * this.denominator;
|
|
566
|
+
denominator = this.denominator * num.denominator;
|
|
567
|
+
}
|
|
568
|
+
[numerator, denominator] = (0, bigint_1.simplifyRatio)(numerator, denominator);
|
|
569
|
+
retval = new Rational(numerator, denominator);
|
|
570
|
+
// Ensure that any operation with a decimal results in a decimal
|
|
571
|
+
retval.asDecimal = this.asDecimal || num.asDecimal;
|
|
572
|
+
}
|
|
573
|
+
return retval;
|
|
574
|
+
}
|
|
575
|
+
pow(num) {
|
|
576
|
+
let retval;
|
|
577
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
578
|
+
retval = Expression_1.Expression.create(this).pow(num);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
num = Rational.toRational(num);
|
|
582
|
+
if (this.isZero() && num.isZero()) {
|
|
583
|
+
throw new errors_1.ZeroToZeroPowerError((0, errors_1.message)('zeroToZeroPower'));
|
|
584
|
+
}
|
|
585
|
+
if (num.isInteger()) {
|
|
586
|
+
let exponent = num.numerator;
|
|
587
|
+
let baseNumerator = this.numerator;
|
|
588
|
+
let baseDenominator = this.denominator;
|
|
589
|
+
if (exponent < 0n) {
|
|
590
|
+
const inverted = this.invert();
|
|
591
|
+
baseNumerator = inverted.numerator;
|
|
592
|
+
baseDenominator = inverted.denominator;
|
|
593
|
+
exponent = (0, bigint_1.abs)(exponent);
|
|
594
|
+
}
|
|
595
|
+
const [numerator, denominator] = (0, bigint_1.simplifyRatio)(baseNumerator ** exponent, baseDenominator ** exponent);
|
|
596
|
+
retval = new Rational(numerator, denominator);
|
|
597
|
+
retval.asDecimal = this.asDecimal;
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
const s = this.toDecimal().toPower(num.toDecimal()).toString();
|
|
601
|
+
retval = Rational.create(s);
|
|
602
|
+
retval.asDecimal = this.asDecimal || retval.asDecimal;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return retval;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Returns the sign carried by the numerator.
|
|
609
|
+
*
|
|
610
|
+
* @returns `-1` for a negative numerator, `0` for zero, or `1` for a positive numerator.
|
|
611
|
+
*/
|
|
612
|
+
sign() {
|
|
613
|
+
return (0, bigint_1.sign)(this.numerator);
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Formats this rational as fraction, integer, or decimal text.
|
|
617
|
+
*
|
|
618
|
+
* @remarks
|
|
619
|
+
* Decimal formatting is selected when {@link Rational.asDecimal} is set or when
|
|
620
|
+
* `options.decimal` is truthy. Non-integer decimal output uses `decimal.js`; an optional
|
|
621
|
+
* `options.precision` temporarily controls its significant-digit precision for this conversion.
|
|
622
|
+
* Integer decimal output includes a `.0` suffix. Without decimal formatting, non-integer
|
|
623
|
+
* fractions are emitted from the stored numerator and denominator, and integers as plain text.
|
|
624
|
+
*
|
|
625
|
+
* @param options - Formatting options. `decimal` forces decimal output and `precision` controls
|
|
626
|
+
* decimal conversion precision when applicable.
|
|
627
|
+
* @returns The formatted numeric text.
|
|
628
|
+
*/
|
|
629
|
+
text(options) {
|
|
630
|
+
let value;
|
|
631
|
+
const thisIsInteger = this.isInteger();
|
|
632
|
+
// Mark it as a decimal if it is such
|
|
633
|
+
if (this.asDecimal || options?.decimal) {
|
|
634
|
+
if (thisIsInteger) {
|
|
635
|
+
value = `${this.numerator}.0`;
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
const previousPrecision = decimal_js_1.default.precision;
|
|
639
|
+
const precision = Number(options?.precision) || previousPrecision;
|
|
640
|
+
if (precision === previousPrecision) {
|
|
641
|
+
value = this.toDecimal().toString();
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
try {
|
|
645
|
+
decimal_js_1.default.set({ precision: precision });
|
|
646
|
+
value = this.toDecimal().toString();
|
|
647
|
+
}
|
|
648
|
+
finally {
|
|
649
|
+
decimal_js_1.default.set({ precision: previousPrecision });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
// decimal.js trims insignificant zeros and can round a non-integer rational
|
|
653
|
+
// to a plain integer string. Preserve the requested decimal presentation.
|
|
654
|
+
if (!value.includes('.') && !/[eE]/.test(value)) {
|
|
655
|
+
value += '.0';
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
else if (thisIsInteger) {
|
|
660
|
+
value = `${this.numerator}`;
|
|
661
|
+
}
|
|
662
|
+
else {
|
|
663
|
+
value = `${this.numerator}/${this.denominator}`;
|
|
664
|
+
}
|
|
665
|
+
return value;
|
|
666
|
+
}
|
|
667
|
+
times(num) {
|
|
668
|
+
let retval;
|
|
669
|
+
if (Expression_1.Expression.isExpression(num)) {
|
|
670
|
+
retval = num.times(this);
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
num = Rational.toRational(num);
|
|
674
|
+
const [numerator, denominator] = (0, bigint_1.simplifyRatio)(this.numerator * num.numerator, this.denominator * num.denominator);
|
|
675
|
+
retval = new Rational(numerator, denominator);
|
|
676
|
+
// Ensure that any operation with a decimal results in a decimal
|
|
677
|
+
retval.asDecimal = this.asDecimal || num.asDecimal;
|
|
678
|
+
}
|
|
679
|
+
return retval;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Converts the exact fraction to a `decimal.js` value at the current global Decimal precision.
|
|
683
|
+
*
|
|
684
|
+
* Integer rationals avoid an unnecessary Decimal division.
|
|
685
|
+
*
|
|
686
|
+
* @returns A new Decimal representing `numerator / denominator`.
|
|
687
|
+
*/
|
|
688
|
+
toDecimal() {
|
|
689
|
+
let retval = new decimal_js_1.default(String(this.numerator));
|
|
690
|
+
if (this.denominator !== 1n) {
|
|
691
|
+
retval = retval.div(String(this.denominator));
|
|
692
|
+
}
|
|
693
|
+
return retval;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Converts the exact fraction to decimal text using integer arithmetic.
|
|
697
|
+
*
|
|
698
|
+
* @remarks
|
|
699
|
+
* `precision` is the maximum number of digits generated after the decimal point. The
|
|
700
|
+
* conversion truncates at that position rather than rounding, then removes trailing zeros
|
|
701
|
+
* and a trailing decimal point. When omitted, the configured Rational precision is used.
|
|
702
|
+
*
|
|
703
|
+
* This method does not depend on {@link Rational.asDecimal}; it always requests decimal text.
|
|
704
|
+
*
|
|
705
|
+
* @param precision - Number of fractional digits to generate.
|
|
706
|
+
* @returns Truncated decimal text with unnecessary trailing zeros removed.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```ts
|
|
710
|
+
* Rational.create('1/3').toDecimalString(5); // "0.33333"
|
|
711
|
+
* Rational.create('7/4').toDecimalString(5); // "1.75"
|
|
712
|
+
* ```
|
|
713
|
+
*/
|
|
714
|
+
toDecimalString(precision) {
|
|
715
|
+
// return this.toDecimal().toString();
|
|
716
|
+
const sgn = (0, bigint_1.sign)(this.numerator);
|
|
717
|
+
const a = (0, bigint_1.abs)(this.numerator);
|
|
718
|
+
const b = this.denominator;
|
|
719
|
+
const whole = a / b;
|
|
720
|
+
const rem = a % b;
|
|
721
|
+
const decimalPlaces = precision ?? Rational.precision;
|
|
722
|
+
const dec = ((10n ** BigInt(decimalPlaces) * rem) / b).toString();
|
|
723
|
+
const retval = `${sgn < 0 ? '-' : ''}${whole}.${'0'.repeat(Math.max(0, decimalPlaces - dec.length))}${dec}`
|
|
724
|
+
.replace(/0+$/g, '')
|
|
725
|
+
.replace(/\.$/g, '');
|
|
726
|
+
return retval;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Returns the same formatted representation as {@link Rational.text}.
|
|
730
|
+
*
|
|
731
|
+
* @param options - Formatting options forwarded to `text`.
|
|
732
|
+
* @returns The formatted rational string.
|
|
733
|
+
*/
|
|
734
|
+
toString(options) {
|
|
735
|
+
return this.text(options);
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Refreshes {@link Rational.value} from the current numerator and denominator.
|
|
739
|
+
*
|
|
740
|
+
* @remarks
|
|
741
|
+
* This is one of the few mutating methods on `Rational`; it updates this object and returns
|
|
742
|
+
* the same reference.
|
|
743
|
+
*
|
|
744
|
+
* @returns This rational instance.
|
|
745
|
+
*/
|
|
746
|
+
updateValue() {
|
|
747
|
+
this.value =
|
|
748
|
+
this.denominator === 1n
|
|
749
|
+
? String(this.numerator)
|
|
750
|
+
: `${this.numerator}/${this.denominator}`;
|
|
751
|
+
return this;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Converts this rational to a native JavaScript number.
|
|
755
|
+
*
|
|
756
|
+
* @remarks
|
|
757
|
+
* This conversion is approximate and subject to the range and precision limits of
|
|
758
|
+
* JavaScript `number`. Numerator and denominator values that are both safe integers use
|
|
759
|
+
* native division directly; larger values retain the Decimal-backed fallback so finite ratios
|
|
760
|
+
* are not lost merely because an individual component exceeds the native numeric range.
|
|
761
|
+
* Use the rational representation or {@link Rational.toDecimal} when native-number limits
|
|
762
|
+
* are unacceptable.
|
|
763
|
+
*
|
|
764
|
+
* @returns The approximate native numeric value.
|
|
765
|
+
*/
|
|
766
|
+
valueOf() {
|
|
767
|
+
const numerator = Number(this.numerator);
|
|
768
|
+
const denominator = Number(this.denominator);
|
|
769
|
+
let retval;
|
|
770
|
+
if (Number.isSafeInteger(numerator) && Number.isSafeInteger(denominator)) {
|
|
771
|
+
retval = numerator / denominator;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
retval = Number(this.toDecimal());
|
|
775
|
+
}
|
|
776
|
+
return retval;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
exports.Rational = Rational;
|