Fix some tests

This commit is contained in:
thepaperpilot 2023-02-14 01:12:11 -06:00
parent b3d61149c4
commit fd925071e5
2 changed files with 61 additions and 26 deletions

View file

@ -829,7 +829,9 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.internalInvertIntegral =
this.internalHasVariable && variable?.isIntegralInvertible() ? invert : undefined;
this.internalHasVariable && variable?.isIntegralInvertible()
? invertIntegral
: undefined;
}
/** Type predicate that this formula can be inverted. */
@ -847,7 +849,10 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
/** Type predicate that this formula has an integral function that can be inverted. */
isIntegralInvertible(): this is InvertibleIntegralFormula {
return this.internalHasVariable && this.internalInvertIntegral != null;
return (
this.internalHasVariable &&
(this.internalInvertIntegral != null || this.internalEvaluate == null)
);
}
/** Whether or not this formula has a singular variable inside it, which can be accessed via {@link innermostVariable}. */
@ -892,11 +897,12 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
* @see {@link isIntegrable}
*/
evaluateIntegral(variable?: DecimalSource): DecimalSource {
return (
this.internalIntegrate?.call(this, variable, ...this.inputs) ??
variable ??
unrefFormulaSource(this.inputs[0])
);
if (this.internalIntegrate) {
return this.internalIntegrate.call(this, variable, ...this.inputs);
} else if (this.inputs.length === 1 && this.internalHasVariable) {
return variable ?? unrefFormulaSource(this.inputs[0]);
}
throw "Cannot integrate formula without variable";
}
/**
@ -907,7 +913,12 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
invertIntegral(value: DecimalSource): DecimalSource {
// This is nearly completely non-functional
// Proper nesting will require somehow using integration by substitution or integration by parts
return this.internalInvertIntegral?.call(this, value, ...this.inputs) ?? value;
if (this.internalInvertIntegral) {
return this.internalInvertIntegral.call(this, value, ...this.inputs);
} else if (this.inputs.length === 1 && this.internalHasVariable) {
return value;
}
throw "Cannot invert integral of formula without invertible integral";
}
/**
@ -962,10 +973,12 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
public static step(
value: FormulaSource,
start: Computable<DecimalSource>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
): GenericFormula {
const lhsRef = ref<DecimalSource>(0);
const formula = formulaModifier(lhsRef);
const formula = formulaModifier(Formula.variable(lhsRef));
const processedStart = convertComputable(start);
function evalStep(lhs: DecimalSource) {
if (Decimal.lt(lhs, unref(processedStart))) {
@ -1002,10 +1015,12 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
public static if(
value: FormulaSource,
condition: Computable<boolean>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
): GenericFormula {
const lhsRef = ref<DecimalSource>(0);
const formula = formulaModifier(lhsRef);
const formula = formulaModifier(Formula.variable(lhsRef));
const processedCondition = convertComputable(condition);
function evalStep(lhs: DecimalSource) {
if (unref(processedCondition)) {
@ -1035,7 +1050,9 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
public static conditional(
value: FormulaSource,
condition: Computable<boolean>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
) {
return Formula.if(value, condition, formulaModifier);
}
@ -1632,20 +1649,26 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
public step(
start: Computable<DecimalSource>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
) {
return Formula.step(this, start, formulaModifier);
}
public if(
condition: Computable<boolean>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
) {
return Formula.if(this, condition, formulaModifier);
}
public conditional(
condition: Computable<boolean>,
formulaModifier: (value: Ref<DecimalSource>) => GenericFormula
formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula
) {
return Formula.if(this, condition, formulaModifier);
}

View file

@ -569,8 +569,8 @@ describe("Integrating", () => {
checkFormula(Formula[name](variable, constant)));
test(`${name}(const, var) is marked as integrable`, () =>
checkFormula(Formula[name](constant, variable)));
test(`${name}(var, var) is marked as integrable`, () =>
checkFormula(Formula[name](variable, variable)));
test(`${name}(var, var) is marked as not integrable`, () =>
expect(Formula[name](variable, variable).isIntegrable()).toBe(false));
});
});
});
@ -872,20 +872,29 @@ describe("Custom Formulas", () => {
describe("Formula with invert", () => {
test("Zero input inverts correctly", () =>
expect(
new Formula({ inputs: [], evaluate: () => 6, invert: value => value }).invert(10)
new Formula({
inputs: [],
evaluate: () => 6,
invert: value => value,
variable: ref(10)
}).invert(10)
).compare_tolerance(10));
test("One input inverts correctly", () =>
expect(
new Formula({ inputs: [1], evaluate: () => 10, invert: (value, v1) => v1 }).invert(
10
)
new Formula({
inputs: [1],
evaluate: () => 10,
invert: (value, v1) => v1,
variable: ref(10)
}).invert(10)
).compare_tolerance(1));
test("Two inputs inverts correctly", () =>
expect(
new Formula({
inputs: [1, 2],
evaluate: () => 10,
invert: (value, v1, v2) => v2
invert: (value, v1, v2) => v2,
variable: ref(10)
}).invert(10)
).compare_tolerance(2));
});
@ -923,7 +932,8 @@ describe("Custom Formulas", () => {
new Formula({
inputs: [],
evaluate: () => 10,
invertIntegral: () => 1
invertIntegral: () => 1,
variable: ref(10)
}).invertIntegral(8)
).compare_tolerance(1));
test("One input inverts integral correctly", () =>
@ -931,7 +941,8 @@ describe("Custom Formulas", () => {
new Formula({
inputs: [1],
evaluate: () => 10,
invertIntegral: val => 1
invertIntegral: val => 1,
variable: ref(10)
}).invertIntegral(8)
).compare_tolerance(1));
test("Two inputs inverts integral correctly", () =>
@ -939,7 +950,8 @@ describe("Custom Formulas", () => {
new Formula({
inputs: [1, 2],
evaluate: (v1, v2) => 10,
invertIntegral: (v1, v2) => 1
invertIntegral: (v1, v2) => 1,
variable: ref(10)
}).invertIntegral(8)
).compare_tolerance(1));
});