document-compute.js 1.5.8 → 1.5.9

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/dist/index.cjs CHANGED
@@ -11,20 +11,17 @@ function toRational(value) {
11
11
  };
12
12
  }
13
13
  function gcd(a, b) {
14
- let x = a < 0n ? -a : a;
15
- let y = b;
14
+ let x = b;
15
+ let y = (a % b + b) % b;
16
16
  while (y !== 0n) [x, y] = [y, x % y];
17
17
  return x;
18
18
  }
19
19
  function reduce(n, d) {
20
20
  if (d === 0n) throw new RangeError("rational.ts: denominator must not be zero");
21
- const sign = d < 0n ? -1n : 1n;
22
- const num = n * sign;
23
- const den = d * sign;
24
- const g = gcd(num, den);
21
+ const g = gcd(n, d);
25
22
  return {
26
- n: num / g,
27
- d: den / g
23
+ n: n / g,
24
+ d: d / g
28
25
  };
29
26
  }
30
27
  function toExactRational(value) {
@@ -267,9 +264,7 @@ function negateInterval(a) {
267
264
  return interval(-a.max, -a.min, a.dimension);
268
265
  }
269
266
  function absInterval(a) {
270
- if (a.min >= 0) return a;
271
- if (a.max <= 0) return negateInterval(a);
272
- return interval(0, Math.max(-a.min, a.max), a.dimension);
267
+ return interval(Math.max(0, a.min, -a.max), Math.max(-a.min, a.max), a.dimension);
273
268
  }
274
269
  //#endregion
275
270
  //#region src/compute/evaluate.ts
@@ -283,7 +278,7 @@ function isInterval(value) {
283
278
  function toInterval(value) {
284
279
  return isInterval(value) ? value : pointInterval(value.magnitude, value.dimension);
285
280
  }
286
- function asQuantity$1(value, context) {
281
+ function asQuantity(value, context) {
287
282
  if (isInterval(value)) throw new UnsupportedExpressionError(context, "this position requires a plain Quantity, not an Interval");
288
283
  return value;
289
284
  }
@@ -335,6 +330,9 @@ function evaluate(expression, bindings, context = EMPTY_SYMBOL_TABLE$2) {
335
330
  case "unparsed": throw new UnsupportedExpressionError("evaluate", `this node is source LaTeX ("${expression.latex}") document-schema.js's lowering could not represent structurally, so there is nothing to evaluate`);
336
331
  }
337
332
  }
333
+ function evaluateQuantity(expression, bindings, context = EMPTY_SYMBOL_TABLE$2) {
334
+ return asQuantity(evaluate(expression, bindings, context), "evaluateQuantity");
335
+ }
338
336
  function evaluateQty(node, context) {
339
337
  const unit = context.units.find((entry) => entry.id === node.unit);
340
338
  if (unit === void 0) throw new UnknownUnitError(node.unit);
@@ -371,13 +369,13 @@ function evaluateApp(node, bindings, context) {
371
369
  }
372
370
  if (node.operator === "math:pow") {
373
371
  const [base, exponent] = expectTwoArgs(args, "'math:pow'");
374
- return powQuantity(asQuantity$1(base, "evaluate"), asQuantity$1(exponent, "evaluate"));
372
+ return powQuantity(asQuantity(base, "evaluate"), asQuantity(exponent, "evaluate"));
375
373
  }
376
374
  throw new UnsupportedExpressionError("evaluate", `unknown operator '${node.operator}'`);
377
375
  }
378
376
  function evaluateBinder(node, bindings, context) {
379
- const lower = asQuantity$1(evaluate(node.lower, bindings, context), `evaluate:${node.kind}`);
380
- const upper = asQuantity$1(evaluate(node.upper, bindings, context), `evaluate:${node.kind}`);
377
+ const lower = asQuantity(evaluate(node.lower, bindings, context), `evaluate:${node.kind}`);
378
+ const upper = asQuantity(evaluate(node.upper, bindings, context), `evaluate:${node.kind}`);
381
379
  if (!isDimensionless(lower.dimension) || !isDimensionless(upper.dimension)) throw new IncompatibleDimensionsError(`math:${node.kind}`, lower.dimension, upper.dimension, "binder bounds must be dimensionless");
382
380
  if (!Number.isInteger(lower.magnitude) || !Number.isInteger(upper.magnitude)) throw new UnsupportedExpressionError(`evaluate:${node.kind}`, "binder bounds must evaluate to integers");
383
381
  let accumulator = node.kind === "sum" ? quantity(0, {}) : quantity(1, {});
@@ -386,7 +384,7 @@ function evaluateBinder(node, bindings, context) {
386
384
  ...bindings,
387
385
  [node.binder]: quantity(i, {})
388
386
  };
389
- const bodyValue = asQuantity$1(evaluate(node.body, bodyBindings, context), `evaluate:${node.kind}`);
387
+ const bodyValue = asQuantity(evaluate(node.body, bodyBindings, context), `evaluate:${node.kind}`);
390
388
  accumulator = node.kind === "sum" ? addQuantities(accumulator, bodyValue) : multiplyQuantities(accumulator, bodyValue);
391
389
  }
392
390
  return accumulator;
@@ -430,7 +428,7 @@ function bisection(f, bracket, tolerance, maxIterations) {
430
428
  const mid = (low + high) / 2;
431
429
  const fMid = f(mid);
432
430
  if (Math.abs(fMid) < tolerance) return mid;
433
- if (fMid > 0 === fLow > 0) {
431
+ if (Math.sign(fMid) === Math.sign(fLow)) {
434
432
  low = mid;
435
433
  fLow = fMid;
436
434
  } else high = mid;
@@ -445,9 +443,7 @@ function newton(f, initialGuess, tolerance, maxIterations, h) {
445
443
  if (Math.abs(fx) < tolerance) return x;
446
444
  const derivative = (f(x + h) - f(x - h)) / (2 * h);
447
445
  if (!Number.isFinite(derivative) || Math.abs(derivative) < 1e-14) throw new NonConvergentSolveError("newton", i, `the numeric derivative vanished or diverged near x=${x}`);
448
- const next = x - fx / derivative;
449
- if (!Number.isFinite(next)) throw new NonConvergentSolveError("newton", i, `the iteration diverged to a non-finite value near x=${x}`);
450
- x = next;
446
+ x = x - fx / derivative;
451
447
  }
452
448
  throw new NonConvergentSolveError("newton", maxIterations, `residual still exceeds tolerance ${tolerance} after ${maxIterations} iterations`);
453
449
  }
@@ -471,19 +467,13 @@ function asEquality(expression) {
471
467
  function containsSymbol(expression) {
472
468
  switch (expression.kind) {
473
469
  case "sym": return true;
474
- case "num":
475
- case "qty":
476
- case "unparsed": return false;
477
470
  case "app": return expression.args.some(containsSymbol);
478
471
  case "sum":
479
472
  case "prod": return containsSymbol(expression.lower) || containsSymbol(expression.upper) || containsSymbol(expression.body);
480
473
  case "matrix": return expression.rows.some((row) => row.some(containsSymbol));
474
+ default: return false;
481
475
  }
482
476
  }
483
- function asQuantity(value) {
484
- if (isInterval(value)) throw new UnsupportedExpressionError("runWorkedExampleSequence", "this harness compares point-valued Quantity answers only; a symbol resolving to a range (Interval) has no stated-answer comparison defined yet");
485
- return value;
486
- }
487
477
  function gapFromError(error) {
488
478
  if (error instanceof UnboundSymbolError) return "unbound-symbol";
489
479
  if (error instanceof UnknownUnitError) return "unknown-unit";
@@ -491,7 +481,6 @@ function gapFromError(error) {
491
481
  if (error instanceof DivisionByZeroError) return "division-by-zero";
492
482
  if (error instanceof UnsupportedExpressionError) return "unsupported-construct";
493
483
  if (error instanceof NumericDomainError) return "numeric-domain";
494
- if (error instanceof NonConvergentSolveError) return "non-convergent-solve";
495
484
  return "other-evaluation-error";
496
485
  }
497
486
  function errorMessage(error) {
@@ -533,7 +522,7 @@ function runWorkedExampleSequence(formulas, symbolTable = EMPTY_SYMBOL_TABLE, op
533
522
  }
534
523
  let closedValue;
535
524
  try {
536
- closedValue = asQuantity(evaluate(rhs, EMPTY_BINDINGS, symbolTable));
525
+ closedValue = evaluateQuantity(rhs, EMPTY_BINDINGS, symbolTable);
537
526
  } catch (error) {
538
527
  outcomes.push({
539
528
  outcome: "gap",
@@ -548,7 +537,7 @@ function runWorkedExampleSequence(formulas, symbolTable = EMPTY_SYMBOL_TABLE, op
548
537
  pending = void 0;
549
538
  let actual;
550
539
  try {
551
- actual = asQuantity(evaluate(definitionRhs, bindings, symbolTable));
540
+ actual = evaluateQuantity(definitionRhs, bindings, symbolTable);
552
541
  } catch (error) {
553
542
  outcomes.push({
554
543
  outcome: "gap",
@@ -680,6 +669,7 @@ exports.divideIntervals = divideIntervals;
680
669
  exports.divideQuantities = divideQuantities;
681
670
  exports.divideRational = divideRational;
682
671
  exports.evaluate = evaluate;
672
+ exports.evaluateQuantity = evaluateQuantity;
683
673
  exports.formatCorpusReport = formatCorpusReport;
684
674
  exports.interval = interval;
685
675
  exports.isDimensionless = isDimensionless;
package/dist/index.d.cts CHANGED
@@ -82,6 +82,7 @@ declare function absInterval(a: Interval): Interval;
82
82
  type EvaluationResult = Quantity | Interval;
83
83
  declare function isInterval(value: EvaluationResult): value is Interval;
84
84
  declare function evaluate(expression: MathExpression, bindings: FormulaBindings, context?: SymbolTable): EvaluationResult;
85
+ declare function evaluateQuantity(expression: MathExpression, bindings: FormulaBindings, context?: SymbolTable): Quantity;
85
86
  //#endregion
86
87
  //#region src/compute/solve.d.ts
87
88
  type SolveMethod = "bisection" | "newton";
@@ -104,7 +105,7 @@ interface SolveForOptions {
104
105
  declare function solveFor(expression: MathExpression, targetValue: number, unknownSymbol: string, bindings: FormulaBindings, options?: SolveForOptions, context?: SymbolTable): number;
105
106
  //#endregion
106
107
  //#region src/harness/worked-example.d.ts
107
- type WorkedExampleGap = "unbound-symbol" | "unknown-unit" | "incompatible-dimensions" | "division-by-zero" | "unsupported-construct" | "numeric-domain" | "non-convergent-solve" | "other-evaluation-error";
108
+ type WorkedExampleGap = "unbound-symbol" | "unknown-unit" | "incompatible-dimensions" | "division-by-zero" | "unsupported-construct" | "numeric-domain" | "other-evaluation-error";
108
109
  interface WorkedExampleMatch {
109
110
  readonly outcome: "match";
110
111
  readonly targetSymbol: string;
@@ -165,4 +166,4 @@ interface CorpusReport {
165
166
  declare function runCorpus(documents: readonly CorpusDocument[], options?: WorkedExampleOptions): CorpusReport;
166
167
  declare function formatCorpusReport(report: CorpusReport): string;
167
168
  //#endregion
168
- export { CorpusDocument, CorpusDocumentReport, CorpusReport, DivisionByZeroError, EvaluationResult, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, Rational, SolveForOptions, SolveMethod, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, WorkedExampleGap, WorkedExampleGapResult, WorkedExampleMatch, WorkedExampleMismatch, WorkedExampleOptions, WorkedExampleOutcome, WorkedExampleReport, WorkedExampleUnresolved, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
169
+ export { CorpusDocument, CorpusDocumentReport, CorpusReport, DivisionByZeroError, EvaluationResult, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, Rational, SolveForOptions, SolveMethod, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, WorkedExampleGap, WorkedExampleGapResult, WorkedExampleMatch, WorkedExampleMismatch, WorkedExampleOptions, WorkedExampleOutcome, WorkedExampleReport, WorkedExampleUnresolved, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, evaluateQuantity, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
package/dist/index.d.ts CHANGED
@@ -82,6 +82,7 @@ declare function absInterval(a: Interval): Interval;
82
82
  type EvaluationResult = Quantity | Interval;
83
83
  declare function isInterval(value: EvaluationResult): value is Interval;
84
84
  declare function evaluate(expression: MathExpression, bindings: FormulaBindings, context?: SymbolTable): EvaluationResult;
85
+ declare function evaluateQuantity(expression: MathExpression, bindings: FormulaBindings, context?: SymbolTable): Quantity;
85
86
  //#endregion
86
87
  //#region src/compute/solve.d.ts
87
88
  type SolveMethod = "bisection" | "newton";
@@ -104,7 +105,7 @@ interface SolveForOptions {
104
105
  declare function solveFor(expression: MathExpression, targetValue: number, unknownSymbol: string, bindings: FormulaBindings, options?: SolveForOptions, context?: SymbolTable): number;
105
106
  //#endregion
106
107
  //#region src/harness/worked-example.d.ts
107
- type WorkedExampleGap = "unbound-symbol" | "unknown-unit" | "incompatible-dimensions" | "division-by-zero" | "unsupported-construct" | "numeric-domain" | "non-convergent-solve" | "other-evaluation-error";
108
+ type WorkedExampleGap = "unbound-symbol" | "unknown-unit" | "incompatible-dimensions" | "division-by-zero" | "unsupported-construct" | "numeric-domain" | "other-evaluation-error";
108
109
  interface WorkedExampleMatch {
109
110
  readonly outcome: "match";
110
111
  readonly targetSymbol: string;
@@ -165,4 +166,4 @@ interface CorpusReport {
165
166
  declare function runCorpus(documents: readonly CorpusDocument[], options?: WorkedExampleOptions): CorpusReport;
166
167
  declare function formatCorpusReport(report: CorpusReport): string;
167
168
  //#endregion
168
- export { CorpusDocument, CorpusDocumentReport, CorpusReport, DivisionByZeroError, EvaluationResult, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, Rational, SolveForOptions, SolveMethod, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, WorkedExampleGap, WorkedExampleGapResult, WorkedExampleMatch, WorkedExampleMismatch, WorkedExampleOptions, WorkedExampleOutcome, WorkedExampleReport, WorkedExampleUnresolved, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
169
+ export { CorpusDocument, CorpusDocumentReport, CorpusReport, DivisionByZeroError, EvaluationResult, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, Rational, SolveForOptions, SolveMethod, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, WorkedExampleGap, WorkedExampleGapResult, WorkedExampleMatch, WorkedExampleMismatch, WorkedExampleOptions, WorkedExampleOutcome, WorkedExampleReport, WorkedExampleUnresolved, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, evaluateQuantity, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
package/dist/index.js CHANGED
@@ -10,20 +10,17 @@ function toRational(value) {
10
10
  };
11
11
  }
12
12
  function gcd(a, b) {
13
- let x = a < 0n ? -a : a;
14
- let y = b;
13
+ let x = b;
14
+ let y = (a % b + b) % b;
15
15
  while (y !== 0n) [x, y] = [y, x % y];
16
16
  return x;
17
17
  }
18
18
  function reduce(n, d) {
19
19
  if (d === 0n) throw new RangeError("rational.ts: denominator must not be zero");
20
- const sign = d < 0n ? -1n : 1n;
21
- const num = n * sign;
22
- const den = d * sign;
23
- const g = gcd(num, den);
20
+ const g = gcd(n, d);
24
21
  return {
25
- n: num / g,
26
- d: den / g
22
+ n: n / g,
23
+ d: d / g
27
24
  };
28
25
  }
29
26
  function toExactRational(value) {
@@ -266,9 +263,7 @@ function negateInterval(a) {
266
263
  return interval(-a.max, -a.min, a.dimension);
267
264
  }
268
265
  function absInterval(a) {
269
- if (a.min >= 0) return a;
270
- if (a.max <= 0) return negateInterval(a);
271
- return interval(0, Math.max(-a.min, a.max), a.dimension);
266
+ return interval(Math.max(0, a.min, -a.max), Math.max(-a.min, a.max), a.dimension);
272
267
  }
273
268
  //#endregion
274
269
  //#region src/compute/evaluate.ts
@@ -282,7 +277,7 @@ function isInterval(value) {
282
277
  function toInterval(value) {
283
278
  return isInterval(value) ? value : pointInterval(value.magnitude, value.dimension);
284
279
  }
285
- function asQuantity$1(value, context) {
280
+ function asQuantity(value, context) {
286
281
  if (isInterval(value)) throw new UnsupportedExpressionError(context, "this position requires a plain Quantity, not an Interval");
287
282
  return value;
288
283
  }
@@ -334,6 +329,9 @@ function evaluate(expression, bindings, context = EMPTY_SYMBOL_TABLE$2) {
334
329
  case "unparsed": throw new UnsupportedExpressionError("evaluate", `this node is source LaTeX ("${expression.latex}") document-schema.js's lowering could not represent structurally, so there is nothing to evaluate`);
335
330
  }
336
331
  }
332
+ function evaluateQuantity(expression, bindings, context = EMPTY_SYMBOL_TABLE$2) {
333
+ return asQuantity(evaluate(expression, bindings, context), "evaluateQuantity");
334
+ }
337
335
  function evaluateQty(node, context) {
338
336
  const unit = context.units.find((entry) => entry.id === node.unit);
339
337
  if (unit === void 0) throw new UnknownUnitError(node.unit);
@@ -370,13 +368,13 @@ function evaluateApp(node, bindings, context) {
370
368
  }
371
369
  if (node.operator === "math:pow") {
372
370
  const [base, exponent] = expectTwoArgs(args, "'math:pow'");
373
- return powQuantity(asQuantity$1(base, "evaluate"), asQuantity$1(exponent, "evaluate"));
371
+ return powQuantity(asQuantity(base, "evaluate"), asQuantity(exponent, "evaluate"));
374
372
  }
375
373
  throw new UnsupportedExpressionError("evaluate", `unknown operator '${node.operator}'`);
376
374
  }
377
375
  function evaluateBinder(node, bindings, context) {
378
- const lower = asQuantity$1(evaluate(node.lower, bindings, context), `evaluate:${node.kind}`);
379
- const upper = asQuantity$1(evaluate(node.upper, bindings, context), `evaluate:${node.kind}`);
376
+ const lower = asQuantity(evaluate(node.lower, bindings, context), `evaluate:${node.kind}`);
377
+ const upper = asQuantity(evaluate(node.upper, bindings, context), `evaluate:${node.kind}`);
380
378
  if (!isDimensionless(lower.dimension) || !isDimensionless(upper.dimension)) throw new IncompatibleDimensionsError(`math:${node.kind}`, lower.dimension, upper.dimension, "binder bounds must be dimensionless");
381
379
  if (!Number.isInteger(lower.magnitude) || !Number.isInteger(upper.magnitude)) throw new UnsupportedExpressionError(`evaluate:${node.kind}`, "binder bounds must evaluate to integers");
382
380
  let accumulator = node.kind === "sum" ? quantity(0, {}) : quantity(1, {});
@@ -385,7 +383,7 @@ function evaluateBinder(node, bindings, context) {
385
383
  ...bindings,
386
384
  [node.binder]: quantity(i, {})
387
385
  };
388
- const bodyValue = asQuantity$1(evaluate(node.body, bodyBindings, context), `evaluate:${node.kind}`);
386
+ const bodyValue = asQuantity(evaluate(node.body, bodyBindings, context), `evaluate:${node.kind}`);
389
387
  accumulator = node.kind === "sum" ? addQuantities(accumulator, bodyValue) : multiplyQuantities(accumulator, bodyValue);
390
388
  }
391
389
  return accumulator;
@@ -429,7 +427,7 @@ function bisection(f, bracket, tolerance, maxIterations) {
429
427
  const mid = (low + high) / 2;
430
428
  const fMid = f(mid);
431
429
  if (Math.abs(fMid) < tolerance) return mid;
432
- if (fMid > 0 === fLow > 0) {
430
+ if (Math.sign(fMid) === Math.sign(fLow)) {
433
431
  low = mid;
434
432
  fLow = fMid;
435
433
  } else high = mid;
@@ -444,9 +442,7 @@ function newton(f, initialGuess, tolerance, maxIterations, h) {
444
442
  if (Math.abs(fx) < tolerance) return x;
445
443
  const derivative = (f(x + h) - f(x - h)) / (2 * h);
446
444
  if (!Number.isFinite(derivative) || Math.abs(derivative) < 1e-14) throw new NonConvergentSolveError("newton", i, `the numeric derivative vanished or diverged near x=${x}`);
447
- const next = x - fx / derivative;
448
- if (!Number.isFinite(next)) throw new NonConvergentSolveError("newton", i, `the iteration diverged to a non-finite value near x=${x}`);
449
- x = next;
445
+ x = x - fx / derivative;
450
446
  }
451
447
  throw new NonConvergentSolveError("newton", maxIterations, `residual still exceeds tolerance ${tolerance} after ${maxIterations} iterations`);
452
448
  }
@@ -470,19 +466,13 @@ function asEquality(expression) {
470
466
  function containsSymbol(expression) {
471
467
  switch (expression.kind) {
472
468
  case "sym": return true;
473
- case "num":
474
- case "qty":
475
- case "unparsed": return false;
476
469
  case "app": return expression.args.some(containsSymbol);
477
470
  case "sum":
478
471
  case "prod": return containsSymbol(expression.lower) || containsSymbol(expression.upper) || containsSymbol(expression.body);
479
472
  case "matrix": return expression.rows.some((row) => row.some(containsSymbol));
473
+ default: return false;
480
474
  }
481
475
  }
482
- function asQuantity(value) {
483
- if (isInterval(value)) throw new UnsupportedExpressionError("runWorkedExampleSequence", "this harness compares point-valued Quantity answers only; a symbol resolving to a range (Interval) has no stated-answer comparison defined yet");
484
- return value;
485
- }
486
476
  function gapFromError(error) {
487
477
  if (error instanceof UnboundSymbolError) return "unbound-symbol";
488
478
  if (error instanceof UnknownUnitError) return "unknown-unit";
@@ -490,7 +480,6 @@ function gapFromError(error) {
490
480
  if (error instanceof DivisionByZeroError) return "division-by-zero";
491
481
  if (error instanceof UnsupportedExpressionError) return "unsupported-construct";
492
482
  if (error instanceof NumericDomainError) return "numeric-domain";
493
- if (error instanceof NonConvergentSolveError) return "non-convergent-solve";
494
483
  return "other-evaluation-error";
495
484
  }
496
485
  function errorMessage(error) {
@@ -532,7 +521,7 @@ function runWorkedExampleSequence(formulas, symbolTable = EMPTY_SYMBOL_TABLE, op
532
521
  }
533
522
  let closedValue;
534
523
  try {
535
- closedValue = asQuantity(evaluate(rhs, EMPTY_BINDINGS, symbolTable));
524
+ closedValue = evaluateQuantity(rhs, EMPTY_BINDINGS, symbolTable);
536
525
  } catch (error) {
537
526
  outcomes.push({
538
527
  outcome: "gap",
@@ -547,7 +536,7 @@ function runWorkedExampleSequence(formulas, symbolTable = EMPTY_SYMBOL_TABLE, op
547
536
  pending = void 0;
548
537
  let actual;
549
538
  try {
550
- actual = asQuantity(evaluate(definitionRhs, bindings, symbolTable));
539
+ actual = evaluateQuantity(definitionRhs, bindings, symbolTable);
551
540
  } catch (error) {
552
541
  outcomes.push({
553
542
  outcome: "gap",
@@ -657,4 +646,4 @@ function formatCorpusReport(report) {
657
646
  return lines.join("\n");
658
647
  }
659
648
  //#endregion
660
- export { DivisionByZeroError, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
649
+ export { DivisionByZeroError, IncompatibleDimensionsError, NonConvergentSolveError, NumericDomainError, UnboundSymbolError, UnknownUnitError, UnsupportedExpressionError, absInterval, absQuantity, addIntervals, addQuantities, addRational, collectFormulas, cosQuantity, dimensionExponent, dimensionToString, dimensionsEqual, divideDimensions, divideIntervals, divideQuantities, divideRational, evaluate, evaluateQuantity, formatCorpusReport, interval, isDimensionless, isInterval, multiplyDimensions, multiplyIntervals, multiplyQuantities, multiplyRational, negateInterval, negateQuantity, pointInterval, powQuantity, quantity, rationalToNumber, runCorpus, runWorkedExampleSequence, scaleDimension, sinQuantity, solveFor, sqrtQuantity, subtractIntervals, subtractQuantities, subtractRational, tanQuantity, toExactRational, toRational };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-compute.js",
3
- "version": "1.5.8",
3
+ "version": "1.5.9",
4
4
  "description": "Units-typed, tree-walking evaluator for document-schema.js's MathExpression -- exact-rational unit conversion, interval arithmetic, and bisection/Newton numeric solve-for, the compute package for the documents.js family.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -79,7 +79,7 @@
79
79
  "@stryker-mutator/typescript-checker": "10.0.0",
80
80
  "@stryker-mutator/vitest-runner": "10.0.0",
81
81
  "@types/node": "26.2.0",
82
- "documents.js": "7.20.5",
82
+ "documents.js": "7.20.6",
83
83
  "eslint": "10.8.1",
84
84
  "husky": "9.1.7",
85
85
  "markdown-codec": "6.7.1",