forked from profectus/Profectus
Formulas implementation (incomplete)
This commit is contained in:
parent
b3b042c271
commit
c8283a7043
4 changed files with 1529 additions and 15 deletions
|
@ -48,7 +48,7 @@
|
||||||
"jsdom": "^20.0.0",
|
"jsdom": "^20.0.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"typescript": "^4.7.4",
|
"typescript": "^4.7.4",
|
||||||
"vitest": "^0.17.1",
|
"vitest": "^0.26.3",
|
||||||
"vue-tsc": "^0.38.1"
|
"vue-tsc": "^0.38.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
1136
src/game/formulas.ts
Normal file
1136
src/game/formulas.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -344,16 +344,16 @@ export type DecimalSource = Decimal | number | string;
|
||||||
* The Decimal's value is simply mantissa * 10^exponent.
|
* The Decimal's value is simply mantissa * 10^exponent.
|
||||||
*/
|
*/
|
||||||
export default class Decimal {
|
export default class Decimal {
|
||||||
public static readonly dZero = FC_NN(0, 0, 0);
|
public static dZero: Decimal;
|
||||||
public static readonly dOne = FC_NN(1, 0, 1);
|
public static dOne: Decimal;
|
||||||
public static readonly dNegOne = FC_NN(-1, 0, 1);
|
public static dNegOne: Decimal;
|
||||||
public static readonly dTwo = FC_NN(1, 0, 2);
|
public static dTwo: Decimal;
|
||||||
public static readonly dTen = FC_NN(1, 0, 10);
|
public static dTen: Decimal;
|
||||||
public static readonly dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN);
|
public static dNaN: Decimal;
|
||||||
public static readonly dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
public static dInf: Decimal;
|
||||||
public static readonly dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
|
public static dNegInf: Decimal;
|
||||||
public static readonly dNumberMax = FC(1, 0, Number.MAX_VALUE);
|
public static dNumberMax: Decimal;
|
||||||
public static readonly dNumberMin = FC(1, 0, Number.MIN_VALUE);
|
public static dNumberMin: Decimal;
|
||||||
|
|
||||||
private static fromStringCache = new LRUCache<string, Decimal>(DEFAULT_FROM_STRING_CACHE_SIZE);
|
private static fromStringCache = new LRUCache<string, Decimal>(DEFAULT_FROM_STRING_CACHE_SIZE);
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@ export default class Decimal {
|
||||||
public static eq_tolerance(
|
public static eq_tolerance(
|
||||||
value: DecimalSource,
|
value: DecimalSource,
|
||||||
other: DecimalSource,
|
other: DecimalSource,
|
||||||
tolerance: number
|
tolerance?: number
|
||||||
): boolean {
|
): boolean {
|
||||||
return D(value).eq_tolerance(other, tolerance);
|
return D(value).eq_tolerance(other, tolerance);
|
||||||
}
|
}
|
||||||
|
@ -713,7 +713,7 @@ export default class Decimal {
|
||||||
public static equals_tolerance(
|
public static equals_tolerance(
|
||||||
value: DecimalSource,
|
value: DecimalSource,
|
||||||
other: DecimalSource,
|
other: DecimalSource,
|
||||||
tolerance: number
|
tolerance?: number
|
||||||
): boolean {
|
): boolean {
|
||||||
return D(value).eq_tolerance(other, tolerance);
|
return D(value).eq_tolerance(other, tolerance);
|
||||||
}
|
}
|
||||||
|
@ -858,7 +858,7 @@ export default class Decimal {
|
||||||
return D(value).layeradd10(diff);
|
return D(value).layeradd10(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static layeradd(value: DecimalSource, diff: number, base = 10): Decimal {
|
public static layeradd(value: DecimalSource, diff: number, base: DecimalSource = 10): Decimal {
|
||||||
return D(value).layeradd(diff, base);
|
return D(value).layeradd(diff, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2037,7 +2037,7 @@ export default class Decimal {
|
||||||
* For example, if you put in 1e-9, then any number closer to the
|
* For example, if you put in 1e-9, then any number closer to the
|
||||||
* larger number than (larger number)*1e-9 will be considered equal.
|
* larger number than (larger number)*1e-9 will be considered equal.
|
||||||
*/
|
*/
|
||||||
public eq_tolerance(value: DecimalSource, tolerance: number): boolean {
|
public eq_tolerance(value: DecimalSource, tolerance?: number): boolean {
|
||||||
const decimal = D(value); // https://stackoverflow.com/a/33024979
|
const decimal = D(value); // https://stackoverflow.com/a/33024979
|
||||||
if (tolerance == null) {
|
if (tolerance == null) {
|
||||||
tolerance = 1e-7;
|
tolerance = 1e-7;
|
||||||
|
@ -2961,6 +2961,19 @@ export default class Decimal {
|
||||||
// return Decimal;
|
// return Decimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign these after the Decimal is assigned because vitest had issues otherwise
|
||||||
|
// If we can figure out why, we can make these readonly properties instead
|
||||||
|
Decimal.dZero = FC_NN(0, 0, 0);
|
||||||
|
Decimal.dOne = FC_NN(1, 0, 1);
|
||||||
|
Decimal.dNegOne = FC_NN(-1, 0, 1);
|
||||||
|
Decimal.dTwo = FC_NN(1, 0, 2);
|
||||||
|
Decimal.dTen = FC_NN(1, 0, 10);
|
||||||
|
Decimal.dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN);
|
||||||
|
Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
||||||
|
Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
|
||||||
|
Decimal.dNumberMax = FC(1, 0, Number.MAX_VALUE);
|
||||||
|
Decimal.dNumberMin = FC(1, 0, Number.MIN_VALUE);
|
||||||
|
|
||||||
// return Decimal;
|
// return Decimal;
|
||||||
|
|
||||||
// Optimise Decimal aliases.
|
// Optimise Decimal aliases.
|
||||||
|
|
365
tests/game/formulas.test.ts
Normal file
365
tests/game/formulas.test.ts
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
import Formula, { InvertibleFormula } from "game/formulas";
|
||||||
|
import Decimal, { DecimalSource } from "util/bignum";
|
||||||
|
import { beforeAll, describe, expect, test } from "vitest";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
type FormulaFunctions = keyof Formula & keyof typeof Formula & keyof typeof Decimal;
|
||||||
|
|
||||||
|
interface FixedLengthArray<T, L extends number> extends ArrayLike<T> {
|
||||||
|
length: L;
|
||||||
|
}
|
||||||
|
|
||||||
|
function compare_tolerance(value: DecimalSource) {
|
||||||
|
return (other: DecimalSource) => Decimal.eq_tolerance(value, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testConstant(
|
||||||
|
desc: string,
|
||||||
|
formulaFunc: () => InvertibleFormula,
|
||||||
|
expectedValue: DecimalSource = 10
|
||||||
|
) {
|
||||||
|
describe(desc, () => {
|
||||||
|
let formula: Formula;
|
||||||
|
beforeAll(() => {
|
||||||
|
formula = formulaFunc();
|
||||||
|
});
|
||||||
|
test("evaluates correctly", () => expect(formula.evaluate()).toEqual(expectedValue));
|
||||||
|
test("inverts correctly", () => expect(formula.invert(10)).toEqual(expectedValue));
|
||||||
|
test("is invertible", () => expect(formula.invertible).toBe(true));
|
||||||
|
test("is not marked as having a variable", () => expect(formula.hasVariable).toBe(false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function that will test all the different
|
||||||
|
// It's a lot of tests, but I'd rather be exhaustive
|
||||||
|
function testFormula<T extends FormulaFunctions>(
|
||||||
|
functionNames: readonly T[],
|
||||||
|
args: Readonly<FixedLengthArray<number, Parameters<typeof Formula[T]>["length"]>>,
|
||||||
|
invertible = true
|
||||||
|
) {
|
||||||
|
let value: Decimal;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
value = testValueFormulas[args[0]].evaluate();
|
||||||
|
});
|
||||||
|
|
||||||
|
functionNames.forEach(name => {
|
||||||
|
let testName = name + "(";
|
||||||
|
for (let i = 0; i < args.length; i++) {
|
||||||
|
if (i !== 0) {
|
||||||
|
testName += ", ";
|
||||||
|
}
|
||||||
|
testName += testValues[args[i]];
|
||||||
|
}
|
||||||
|
testName += ")";
|
||||||
|
describe(testName, () => {
|
||||||
|
let expectedEvaluation: Decimal | undefined;
|
||||||
|
let formulaArgs: Formula[];
|
||||||
|
let staticFormula: Formula;
|
||||||
|
let instanceFormula: Formula;
|
||||||
|
beforeAll(() => {
|
||||||
|
for (let i = 0; i < args.length; i++) {
|
||||||
|
formulaArgs.push(testValueFormulas[args[i]]);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
staticFormula = Formula[name](...formulaArgs);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
instanceFormula = formulaArgs[0][name](...formulaArgs.slice(1));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
expectedEvaluation = Decimal[name](...args);
|
||||||
|
} catch {
|
||||||
|
// If this is an invalid Decimal operation, then ignore this test case
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Static formula is not marked as having a variable", () =>
|
||||||
|
expect(staticFormula.hasVariable).toBe(false));
|
||||||
|
test("Static function evaluates correctly", () =>
|
||||||
|
expectedEvaluation != null &&
|
||||||
|
expect(staticFormula.evaluate()).toSatisfy(compare_tolerance(expectedEvaluation)));
|
||||||
|
test("Static function invertible", () =>
|
||||||
|
expect(staticFormula.invertible).toBe(invertible));
|
||||||
|
if (invertible) {
|
||||||
|
test("Static function inverts correctly", () =>
|
||||||
|
expectedEvaluation != null &&
|
||||||
|
!Decimal.isNaN(expectedEvaluation) &&
|
||||||
|
expect(staticFormula.invert(expectedEvaluation)).toSatisfy(
|
||||||
|
compare_tolerance(value)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do those tests again but for non-static methods
|
||||||
|
test("Instance formula is not marked as having a variable", () =>
|
||||||
|
expect(instanceFormula.hasVariable).toBe(false));
|
||||||
|
test("Instance function evaluates correctly", () =>
|
||||||
|
expectedEvaluation != null &&
|
||||||
|
expect(instanceFormula.evaluate()).toSatisfy(
|
||||||
|
compare_tolerance(expectedEvaluation)
|
||||||
|
));
|
||||||
|
test("Instance function invertible", () =>
|
||||||
|
expect(instanceFormula.invertible).toBe(invertible));
|
||||||
|
if (invertible) {
|
||||||
|
test("Instance function inverts correctly", () =>
|
||||||
|
expectedEvaluation != null &&
|
||||||
|
!Decimal.isNaN(expectedEvaluation) &&
|
||||||
|
expect(instanceFormula.invert(expectedEvaluation)).toSatisfy(
|
||||||
|
compare_tolerance(value)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const testValues = [-2.5, -1, -0.1, 0, 0.1, 1, 2.5] as const;
|
||||||
|
let testValueFormulas: InvertibleFormula[] = [];
|
||||||
|
|
||||||
|
const invertibleZeroParamFunctionNames = [
|
||||||
|
["neg", "negate", "negated"],
|
||||||
|
["recip", "reciprocal", "reciprocate"],
|
||||||
|
["log10"],
|
||||||
|
["log2"],
|
||||||
|
["ln"],
|
||||||
|
["pow10"],
|
||||||
|
["exp"],
|
||||||
|
["sqr"],
|
||||||
|
["sqrt"],
|
||||||
|
["cube"],
|
||||||
|
["cbrt"],
|
||||||
|
["lambertw"],
|
||||||
|
["ssqrt"],
|
||||||
|
["sin"],
|
||||||
|
["cos"],
|
||||||
|
["tan"],
|
||||||
|
["asin"],
|
||||||
|
["acos"],
|
||||||
|
["atan"],
|
||||||
|
["sinh"],
|
||||||
|
["cosh"],
|
||||||
|
["tanh"],
|
||||||
|
["asinh"],
|
||||||
|
["acosh"],
|
||||||
|
["atanh"]
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const nonInvertibleZeroParamFunctionNames = [
|
||||||
|
["abs"],
|
||||||
|
["sign", "sgn"],
|
||||||
|
["round"],
|
||||||
|
["floor"],
|
||||||
|
["ceil"],
|
||||||
|
["trunc"],
|
||||||
|
["pLog10"],
|
||||||
|
["absLog10"],
|
||||||
|
["factorial"],
|
||||||
|
["gamma"],
|
||||||
|
["lngamma"]
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const invertibleOneParamFunctionNames = [
|
||||||
|
["add", "plus"],
|
||||||
|
["sub", "subtract", "minus"],
|
||||||
|
["mul", "multiply", "times"],
|
||||||
|
["div", "divide"],
|
||||||
|
["log", "logarithm"],
|
||||||
|
["pow"],
|
||||||
|
["root"],
|
||||||
|
["slog"]
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const nonInvertibleOneParamFunctionNames = [
|
||||||
|
["max"],
|
||||||
|
["min"],
|
||||||
|
["maxabs"],
|
||||||
|
["minabs"],
|
||||||
|
["clampMin"],
|
||||||
|
["clampMax"],
|
||||||
|
["layeradd10"]
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const invertibleTwoParamFunctionNames = [["tetrate"]] as const;
|
||||||
|
|
||||||
|
const nonInvertibleTwoParamFunctionNames = [
|
||||||
|
["clamp"],
|
||||||
|
["iteratedexp"],
|
||||||
|
["iteratedlog"],
|
||||||
|
["layeradd"],
|
||||||
|
["pentate"]
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
describe("Creating Formulas", () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
testValueFormulas = testValues.map(v => Formula.constant(v));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Constants", () => {
|
||||||
|
testConstant("number", () => Formula.constant(10));
|
||||||
|
testConstant("string", () => Formula.constant("10"));
|
||||||
|
testConstant("formula", () => Formula.constant(Formula.constant(10)));
|
||||||
|
testConstant("decimal", () => Formula.constant(new Decimal("1e400")), "1e400");
|
||||||
|
testConstant("ref", () => Formula.constant(ref(10)));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Invertible 0-param", () => {
|
||||||
|
invertibleZeroParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
testFormula(names, [i] as const);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("Non-Invertible 0-param", () => {
|
||||||
|
nonInvertibleZeroParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
testFormula(names, [i] as const, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("Invertible 1-param", () => {
|
||||||
|
invertibleOneParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
for (let j = 0; j < testValues.length; j++) {
|
||||||
|
testFormula(names, [i, j] as const);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("Non-Invertible 1-param", () => {
|
||||||
|
nonInvertibleOneParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
for (let j = 0; j < testValues.length; j++) {
|
||||||
|
testFormula(names, [i, j] as const, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("Invertible 2-param", () => {
|
||||||
|
invertibleTwoParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
for (let j = 0; j < testValues.length; j++) {
|
||||||
|
for (let k = 0; k < testValues.length; k++) {
|
||||||
|
testFormula(names, [i, j, k] as const);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("Non-Invertible 2-param", () => {
|
||||||
|
nonInvertibleTwoParamFunctionNames.forEach(names => {
|
||||||
|
for (let i = 0; i < testValues.length; i++) {
|
||||||
|
for (let j = 0; j < testValues.length; j++) {
|
||||||
|
for (let k = 0; k < testValues.length; k++) {
|
||||||
|
testFormula(names, [i, j, k] as const, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Variables", () => {
|
||||||
|
let variable: Formula;
|
||||||
|
let constant: Formula;
|
||||||
|
beforeAll(() => {
|
||||||
|
variable = Formula.variable(10);
|
||||||
|
constant = Formula.constant(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Created variable is marked as a variable", () =>
|
||||||
|
expect(variable.hasVariable).toBe(true));
|
||||||
|
test("Evaluate() returns variable's value", () =>
|
||||||
|
expect(variable.evaluate()).toSatisfy(compare_tolerance(10)));
|
||||||
|
test("Invert() is pass-through", () =>
|
||||||
|
expect(variable.invert(100)).toSatisfy(compare_tolerance(100)));
|
||||||
|
|
||||||
|
test("Nested variable is marked as having a variable", () =>
|
||||||
|
expect(variable.add(10).div(3).pow(2).hasVariable).toBe(false));
|
||||||
|
test("Nested non-variable is marked as not having a variable", () =>
|
||||||
|
expect(constant.add(10).div(3).pow(2).hasVariable).toBe(false));
|
||||||
|
|
||||||
|
describe("Invertible Formulas correctly calculate when they contain a variable", () => {
|
||||||
|
function checkFormula(formula: Formula, expectedBool = true) {
|
||||||
|
expect(formula.invertible).toBe(expectedBool);
|
||||||
|
expect(formula.hasVariable).toBe(expectedBool);
|
||||||
|
}
|
||||||
|
invertibleZeroParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
invertibleOneParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var, const) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant)));
|
||||||
|
test(`${name}(const, var) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable)));
|
||||||
|
test(`${name}(var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable), false));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
invertibleTwoParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var, const, const) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant, constant)));
|
||||||
|
test(`${name}(const, var, const) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable, constant)));
|
||||||
|
test(`${name}(const, const, var) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, constant, variable)));
|
||||||
|
test(`${name}(var, var, const) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable, constant), false));
|
||||||
|
test(`${name}(var, const, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant, variable), false));
|
||||||
|
test(`${name}(const, var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable, variable), false));
|
||||||
|
test(`${name}(var, var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable, variable), false));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Non-Invertible Formulas never marked as having a variable", () => {
|
||||||
|
function checkFormula(formula: Formula) {
|
||||||
|
expect(formula.invertible).toBe(false);
|
||||||
|
expect(formula.hasVariable).toBe(false);
|
||||||
|
}
|
||||||
|
nonInvertibleZeroParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
nonInvertibleOneParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var, const) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant)));
|
||||||
|
test(`${name}(const, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable)));
|
||||||
|
test(`${name}(var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
nonInvertibleTwoParamFunctionNames.flat().forEach(name => {
|
||||||
|
describe(name, () => {
|
||||||
|
test(`${name}(var, const, const) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant, constant)));
|
||||||
|
test(`${name}(const, var, const) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable, constant)));
|
||||||
|
test(`${name}(const, const, var) is marked as invertible and having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, constant, variable)));
|
||||||
|
test(`${name}(var, var, const) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable, constant)));
|
||||||
|
test(`${name}(var, const, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, constant, variable)));
|
||||||
|
test(`${name}(const, var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](constant, variable, variable)));
|
||||||
|
test(`${name}(var, var, var) is marked as not invertible and not having a variable`, () =>
|
||||||
|
checkFormula(Formula[name](variable, variable, variable)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue