Improve error handling
This commit is contained in:
parent
500e412fdb
commit
ab3b180db8
12 changed files with 426 additions and 156 deletions
21
src/App.vue
21
src/App.vue
|
@ -1,4 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div v-if="appErrors.length > 0" class="error-container" :style="theme"><Error :errors="appErrors" /></div>
|
||||||
|
<template v-else>
|
||||||
<div id="modal-root" :style="theme" />
|
<div id="modal-root" :style="theme" />
|
||||||
<div class="app" :style="theme" :class="{ useHeader }">
|
<div class="app" :style="theme" :class="{ useHeader }">
|
||||||
<Nav v-if="useHeader" />
|
<Nav v-if="useHeader" />
|
||||||
|
@ -8,11 +10,16 @@
|
||||||
<NaNScreen />
|
<NaNScreen />
|
||||||
<component :is="gameComponent" />
|
<component :is="gameComponent" />
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
|
import "@fontsource/roboto-mono";
|
||||||
|
import Error from "components/Error.vue";
|
||||||
import { jsx } from "features/feature";
|
import { jsx } from "features/feature";
|
||||||
|
import state from "game/state";
|
||||||
import { coerceComponent, render } from "util/vue";
|
import { coerceComponent, render } from "util/vue";
|
||||||
|
import { CSSProperties, watch } from "vue";
|
||||||
import { computed, toRef, unref } from "vue";
|
import { computed, toRef, unref } from "vue";
|
||||||
import Game from "./components/Game.vue";
|
import Game from "./components/Game.vue";
|
||||||
import GameOverScreen from "./components/GameOverScreen.vue";
|
import GameOverScreen from "./components/GameOverScreen.vue";
|
||||||
|
@ -23,12 +30,11 @@ import projInfo from "./data/projInfo.json";
|
||||||
import themes from "./data/themes";
|
import themes from "./data/themes";
|
||||||
import settings, { gameComponents } from "./game/settings";
|
import settings, { gameComponents } from "./game/settings";
|
||||||
import "./main.css";
|
import "./main.css";
|
||||||
import "@fontsource/roboto-mono";
|
|
||||||
import type { CSSProperties } from "vue";
|
|
||||||
|
|
||||||
const useHeader = projInfo.useHeader;
|
const useHeader = projInfo.useHeader;
|
||||||
const theme = computed(() => themes[settings.theme].variables as CSSProperties);
|
const theme = computed(() => themes[settings.theme].variables as CSSProperties);
|
||||||
const showTPS = toRef(settings, "showTPS");
|
const showTPS = toRef(settings, "showTPS");
|
||||||
|
const appErrors = toRef(state, "errors");
|
||||||
|
|
||||||
const gameComponent = computed(() => {
|
const gameComponent = computed(() => {
|
||||||
return coerceComponent(jsx(() => (<>{gameComponents.map(render)}</>)));
|
return coerceComponent(jsx(() => (<>{gameComponents.map(render)}</>)));
|
||||||
|
@ -51,4 +57,15 @@ const gameComponent = computed(() => {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-container {
|
||||||
|
background: var(--background);
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-container > .error {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
103
src/components/Error.vue
Normal file
103
src/components/Error.vue
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
<template>
|
||||||
|
<div class="error">
|
||||||
|
<h1 class="error-title">{{ firstError.name }}: {{ firstError.message }}</h1>
|
||||||
|
<div class="error-details" style="margin-top: -10px">
|
||||||
|
<div v-if="firstError.cause">
|
||||||
|
<div v-for="row in causes[0]" :key="row">{{ row }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="firstError.stack" :style="firstError.cause ? 'margin-top: 10px' : ''">
|
||||||
|
<div v-for="row in stacks[0]" :key="row">{{ row }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="instructions">
|
||||||
|
Check the console for more details, and consider sharing it with the developers on
|
||||||
|
<a :href="projInfo.discordLink || 'https://discord.gg/yJ4fjnjU54'" class="discord-link"
|
||||||
|
>discord</a
|
||||||
|
>!<br />
|
||||||
|
<div v-if="errors.length > 1" style="margin-top: 20px"><h3>Other errors</h3></div>
|
||||||
|
<div v-for="(error, i) in errors.slice(1)" :key="i" style="margin-top: 20px">
|
||||||
|
<details class="error-details">
|
||||||
|
<summary>{{ error.name }}: {{ error.message }}</summary>
|
||||||
|
<div v-if="error.cause" style="margin-top: 10px">
|
||||||
|
<div v-for="row in causes[i + 1]" :key="row">{{ row }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="error.stack" style="margin-top: 10px">
|
||||||
|
<div v-for="row in stacks[i + 1]" :key="row">{{ row }}</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import projInfo from "data/projInfo.json";
|
||||||
|
import player from "game/player";
|
||||||
|
import { computed, onMounted } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
errors: Error[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const firstError = computed(() => props.errors[0]);
|
||||||
|
const stacks = computed(() =>
|
||||||
|
props.errors.map(error => (error.stack == null ? [] : error.stack.split("\n")))
|
||||||
|
);
|
||||||
|
const causes = computed(() =>
|
||||||
|
props.errors.map(error =>
|
||||||
|
error.cause == null
|
||||||
|
? []
|
||||||
|
: (typeof error.cause === "string" ? error.cause : JSON.stringify(error.cause)).split(
|
||||||
|
"\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
player.autosave = false;
|
||||||
|
player.devSpeed = 0;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.error {
|
||||||
|
border: solid 10px var(--danger);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: left;
|
||||||
|
min-height: calc(100% - 20px);
|
||||||
|
text-align: left;
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-title {
|
||||||
|
background: var(--danger);
|
||||||
|
color: var(--feature-foreground);
|
||||||
|
display: block;
|
||||||
|
margin: -10px 0 10px 0;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-details {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: var(--raised-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discord-link {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="layer-container" :style="{ '--layer-color': unref(color) }">
|
<ErrorVue v-if="errors.length > 0" :errors="errors" />
|
||||||
|
<div class="layer-container" :style="{ '--layer-color': unref(color) }" v-bind="$attrs" v-else>
|
||||||
<button v-if="showGoBack" class="goBack" @click="goBack">❌</button>
|
<button v-if="showGoBack" class="goBack" @click="goBack">❌</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
@ -28,12 +29,12 @@ import type { CoercableComponent } from "features/feature";
|
||||||
import type { FeatureNode } from "game/layers";
|
import type { FeatureNode } from "game/layers";
|
||||||
import player from "game/player";
|
import player from "game/player";
|
||||||
import { computeComponent, computeOptionalComponent, processedPropType, unwrapRef } from "util/vue";
|
import { computeComponent, computeOptionalComponent, processedPropType, unwrapRef } from "util/vue";
|
||||||
import type { PropType, Ref } from "vue";
|
import { PropType, Ref, computed, defineComponent, onErrorCaptured, ref, toRefs, unref } from "vue";
|
||||||
import { computed, defineComponent, toRefs, unref } from "vue";
|
|
||||||
import Context from "./Context.vue";
|
import Context from "./Context.vue";
|
||||||
|
import ErrorVue from "./Error.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { Context },
|
components: { Context, ErrorVue },
|
||||||
props: {
|
props: {
|
||||||
index: {
|
index: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -77,13 +78,23 @@ export default defineComponent({
|
||||||
props.nodes.value = nodes;
|
props.nodes.value = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errors = ref<Error[]>([]);
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
console.warn(`Error caught in "${props.name}" layer`, err, instance, info);
|
||||||
|
errors.value.push(
|
||||||
|
err instanceof Error ? (err as Error) : new Error(JSON.stringify(err))
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component,
|
component,
|
||||||
minimizedComponent,
|
minimizedComponent,
|
||||||
showGoBack,
|
showGoBack,
|
||||||
updateNodes,
|
updateNodes,
|
||||||
unref,
|
unref,
|
||||||
goBack
|
goBack,
|
||||||
|
errors
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -459,7 +459,7 @@ export function createFormulaPreview(
|
||||||
const processedShowPreview = convertComputable(showPreview);
|
const processedShowPreview = convertComputable(showPreview);
|
||||||
const processedPreviewAmount = convertComputable(previewAmount);
|
const processedPreviewAmount = convertComputable(previewAmount);
|
||||||
if (!formula.hasVariable()) {
|
if (!formula.hasVariable()) {
|
||||||
throw new Error("Cannot create formula preview if the formula does not have a variable");
|
console.error("Cannot create formula preview if the formula does not have a variable");
|
||||||
}
|
}
|
||||||
return jsx(() => {
|
return jsx(() => {
|
||||||
if (unref(processedShowPreview)) {
|
if (unref(processedShowPreview)) {
|
||||||
|
|
|
@ -151,8 +151,7 @@ export function createTabFamily<T extends TabFamilyOptions>(
|
||||||
optionsFunc?: OptionsFunc<T, BaseTabFamily, GenericTabFamily>
|
optionsFunc?: OptionsFunc<T, BaseTabFamily, GenericTabFamily>
|
||||||
): TabFamily<T> {
|
): TabFamily<T> {
|
||||||
if (Object.keys(tabs).length === 0) {
|
if (Object.keys(tabs).length === 0) {
|
||||||
console.warn("Cannot create tab family with 0 tabs");
|
console.error("Cannot create tab family with 0 tabs");
|
||||||
throw new Error("Cannot create tab family with 0 tabs");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = persistent(Object.keys(tabs)[0], false);
|
const selected = persistent(Object.keys(tabs)[0], false);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Resource } from "features/resources/resource";
|
||||||
import { NonPersistent } from "game/persistence";
|
import { NonPersistent } from "game/persistence";
|
||||||
import Decimal, { DecimalSource, format } from "util/bignum";
|
import Decimal, { DecimalSource, format } from "util/bignum";
|
||||||
import { Computable, ProcessedComputable, convertComputable } from "util/computed";
|
import { Computable, ProcessedComputable, convertComputable } from "util/computed";
|
||||||
import { ComputedRef, Ref, computed, ref, unref } from "vue";
|
import { Ref, computed, ref, unref } from "vue";
|
||||||
import * as ops from "./operations";
|
import * as ops from "./operations";
|
||||||
import type {
|
import type {
|
||||||
EvaluateFunction,
|
EvaluateFunction,
|
||||||
|
@ -104,7 +104,7 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
||||||
|
|
||||||
private setupConstant({ inputs }: { inputs: [FormulaSource] }): InternalFormulaProperties<T> {
|
private setupConstant({ inputs }: { inputs: [FormulaSource] }): InternalFormulaProperties<T> {
|
||||||
if (inputs.length !== 1) {
|
if (inputs.length !== 1) {
|
||||||
throw new Error("Evaluate function is required if inputs is not length 1");
|
console.error("Evaluate function is required if inputs is not length 1");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
inputs: inputs as T,
|
inputs: inputs as T,
|
||||||
|
@ -250,7 +250,8 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
||||||
}
|
}
|
||||||
return lhs.invert(value);
|
return lhs.invert(value);
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return new Formula({
|
return new Formula({
|
||||||
inputs: [value],
|
inputs: [value],
|
||||||
|
@ -294,7 +295,8 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
||||||
!formula.isInvertible() ||
|
!formula.isInvertible() ||
|
||||||
(elseFormula != null && !elseFormula.isInvertible())
|
(elseFormula != null && !elseFormula.isInvertible())
|
||||||
) {
|
) {
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (unref(processedCondition)) {
|
if (unref(processedCondition)) {
|
||||||
return lhs.invert(formula.invert(value));
|
return lhs.invert(formula.invert(value));
|
||||||
|
@ -1260,7 +1262,8 @@ export default class Formula<
|
||||||
} else if (this.inputs.length === 1 && this.hasVariable()) {
|
} else if (this.inputs.length === 1 && this.hasVariable()) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
throw new Error("Cannot invert non-invertible formula");
|
console.error("Cannot invert non-invertible formula");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1270,7 +1273,8 @@ export default class Formula<
|
||||||
*/
|
*/
|
||||||
evaluateIntegral(variable?: DecimalSource): DecimalSource {
|
evaluateIntegral(variable?: DecimalSource): DecimalSource {
|
||||||
if (!this.isIntegrable()) {
|
if (!this.isIntegrable()) {
|
||||||
throw new Error("Cannot evaluate integral of formula without integral");
|
console.error("Cannot evaluate integral of formula without integral");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return this.getIntegralFormula().evaluate(variable);
|
return this.getIntegralFormula().evaluate(variable);
|
||||||
}
|
}
|
||||||
|
@ -1282,7 +1286,8 @@ export default class Formula<
|
||||||
*/
|
*/
|
||||||
invertIntegral(value: DecimalSource): DecimalSource {
|
invertIntegral(value: DecimalSource): DecimalSource {
|
||||||
if (!this.isIntegrable() || !this.getIntegralFormula().isInvertible()) {
|
if (!this.isIntegrable() || !this.getIntegralFormula().isInvertible()) {
|
||||||
throw new Error("Cannot invert integral of formula without invertible integral");
|
console.error("Cannot invert integral of formula without invertible integral");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return (this.getIntegralFormula() as InvertibleFormula).invert(value);
|
return (this.getIntegralFormula() as InvertibleFormula).invert(value);
|
||||||
}
|
}
|
||||||
|
@ -1309,7 +1314,8 @@ export default class Formula<
|
||||||
// We're the complex operation of this formula
|
// We're the complex operation of this formula
|
||||||
stack = [];
|
stack = [];
|
||||||
if (this.internalIntegrate == null) {
|
if (this.internalIntegrate == null) {
|
||||||
throw new Error("Cannot integrate formula with non-integrable operation");
|
console.error("Cannot integrate formula with non-integrable operation");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
let value = this.internalIntegrate.call(this, stack, ...this.inputs);
|
let value = this.internalIntegrate.call(this, stack, ...this.inputs);
|
||||||
stack.forEach(func => (value = func(value)));
|
stack.forEach(func => (value = func(value)));
|
||||||
|
@ -1329,14 +1335,15 @@ export default class Formula<
|
||||||
) {
|
) {
|
||||||
this.integralFormula = this;
|
this.integralFormula = this;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Cannot integrate formula without variable");
|
console.error("Cannot integrate formula without variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.integralFormula;
|
return this.integralFormula;
|
||||||
} else {
|
} else {
|
||||||
// "Inner" part of the formula
|
// "Inner" part of the formula
|
||||||
if (this.applySubstitution == null) {
|
if (this.applySubstitution == null) {
|
||||||
throw new Error("Cannot have two complex operations in an integrable formula");
|
console.error("Cannot have two complex operations in an integrable formula");
|
||||||
}
|
}
|
||||||
stack.push((variable: GenericFormula) =>
|
stack.push((variable: GenericFormula) =>
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
@ -1353,7 +1360,8 @@ export default class Formula<
|
||||||
) {
|
) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Cannot integrate formula without variable");
|
console.error("Cannot integrate formula without variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1428,15 +1436,17 @@ export function calculateMaxAffordable(
|
||||||
let affordable: DecimalSource = 0;
|
let affordable: DecimalSource = 0;
|
||||||
if (Decimal.gt(maxBulkAmount, directSum)) {
|
if (Decimal.gt(maxBulkAmount, directSum)) {
|
||||||
if (!formula.isInvertible()) {
|
if (!formula.isInvertible()) {
|
||||||
throw new Error(
|
console.error(
|
||||||
"Cannot calculate max affordable of non-invertible formula with more maxBulkAmount than directSum"
|
"Cannot calculate max affordable of non-invertible formula with more maxBulkAmount than directSum"
|
||||||
);
|
);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (cumulativeCost) {
|
if (cumulativeCost) {
|
||||||
if (!formula.isIntegralInvertible()) {
|
if (!formula.isIntegralInvertible()) {
|
||||||
throw new Error(
|
console.error(
|
||||||
"Cannot calculate max affordable of formula with non-invertible integral"
|
"Cannot calculate max affordable of formula with non-invertible integral"
|
||||||
);
|
);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
affordable = Decimal.floor(
|
affordable = Decimal.floor(
|
||||||
formula.invertIntegral(Decimal.add(resource.value, formula.evaluateIntegral()))
|
formula.invertIntegral(Decimal.add(resource.value, formula.evaluateIntegral()))
|
||||||
|
@ -1517,13 +1527,15 @@ export function calculateCost(
|
||||||
// Indirect sum
|
// Indirect sum
|
||||||
if (Decimal.gt(amountToBuy, directSum)) {
|
if (Decimal.gt(amountToBuy, directSum)) {
|
||||||
if (!formula.isInvertible()) {
|
if (!formula.isInvertible()) {
|
||||||
throw new Error("Cannot calculate cost with indirect sum of non-invertible formula");
|
console.error("Cannot calculate cost with indirect sum of non-invertible formula");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (cumulativeCost) {
|
if (cumulativeCost) {
|
||||||
if (!formula.isIntegrable()) {
|
if (!formula.isIntegrable()) {
|
||||||
throw new Error(
|
console.error(
|
||||||
"Cannot calculate cost with cumulative cost of non-integrable formula"
|
"Cannot calculate cost with cumulative cost of non-integrable formula"
|
||||||
);
|
);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
cost = Decimal.sub(formula.evaluateIntegral(newValue), formula.evaluateIntegral());
|
cost = Decimal.sub(formula.evaluateIntegral(newValue), formula.evaluateIntegral());
|
||||||
if (targetValue.gt(1e308)) {
|
if (targetValue.gt(1e308)) {
|
||||||
|
|
|
@ -12,17 +12,20 @@ export function invertNeg(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.neg(value));
|
return lhs.invert(Decimal.neg(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateNeg(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateNeg(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
return Formula.neg(lhs.getIntegralFormula(stack));
|
return Formula.neg(lhs.getIntegralFormula(stack));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applySubstitutionNeg(value: GenericFormula) {
|
export function applySubstitutionNeg(value: GenericFormula) {
|
||||||
|
@ -35,24 +38,28 @@ export function invertAdd(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.sub(value, unrefFormulaSource(lhs)));
|
return rhs.invert(Decimal.sub(value, unrefFormulaSource(lhs)));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAdd(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateAdd(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.times(rhs, lhs.innermostVariable ?? 0).add(x);
|
return Formula.times(rhs, lhs.innermostVariable ?? 0).add(x);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.times(lhs, rhs.innermostVariable ?? 0).add(x);
|
return Formula.times(lhs, rhs.innermostVariable ?? 0).add(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateInnerAdd(
|
export function integrateInnerAdd(
|
||||||
|
@ -62,18 +69,21 @@ export function integrateInnerAdd(
|
||||||
) {
|
) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.add(x, rhs);
|
return Formula.add(x, rhs);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.add(x, lhs);
|
return Formula.add(x, lhs);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -82,24 +92,28 @@ export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.sub(unrefFormulaSource(lhs), value));
|
return rhs.invert(Decimal.sub(unrefFormulaSource(lhs), value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateSub(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateSub(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.sub(x, Formula.times(rhs, lhs.innermostVariable ?? 0));
|
return Formula.sub(x, Formula.times(rhs, lhs.innermostVariable ?? 0));
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.times(lhs, rhs.innermostVariable ?? 0).sub(x);
|
return Formula.times(lhs, rhs.innermostVariable ?? 0).sub(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateInnerSub(
|
export function integrateInnerSub(
|
||||||
|
@ -109,18 +123,21 @@ export function integrateInnerSub(
|
||||||
) {
|
) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.sub(x, rhs);
|
return Formula.sub(x, rhs);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.sub(x, lhs);
|
return Formula.sub(x, lhs);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -129,24 +146,28 @@ export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.div(value, unrefFormulaSource(lhs)));
|
return rhs.invert(Decimal.div(value, unrefFormulaSource(lhs)));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateMul(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateMul(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.times(x, rhs);
|
return Formula.times(x, rhs);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.times(x, lhs);
|
return Formula.times(x, lhs);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applySubstitutionMul(
|
export function applySubstitutionMul(
|
||||||
|
@ -159,7 +180,8 @@ export function applySubstitutionMul(
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return Formula.div(value, lhs);
|
return Formula.div(value, lhs);
|
||||||
}
|
}
|
||||||
throw new Error("Could not apply substitution due to no input being a variable");
|
console.error("Could not apply substitution due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -168,24 +190,28 @@ export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.div(unrefFormulaSource(lhs), value));
|
return rhs.invert(Decimal.div(unrefFormulaSource(lhs), value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateDiv(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateDiv(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.div(x, rhs);
|
return Formula.div(x, rhs);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.div(lhs, x);
|
return Formula.div(lhs, x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applySubstitutionDiv(
|
export function applySubstitutionDiv(
|
||||||
|
@ -198,32 +224,37 @@ export function applySubstitutionDiv(
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return Formula.mul(value, lhs);
|
return Formula.mul(value, lhs);
|
||||||
}
|
}
|
||||||
throw new Error("Could not apply substitution due to no input being a variable");
|
console.error("Could not apply substitution due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertRecip(value: DecimalSource, lhs: FormulaSource) {
|
export function invertRecip(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.recip(value));
|
return lhs.invert(Decimal.recip(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateRecip(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateRecip(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.ln(x);
|
return Formula.ln(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertLog10(value: DecimalSource, lhs: FormulaSource) {
|
export function invertLog10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.pow10(value));
|
return lhs.invert(Decimal.pow10(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function internalIntegrateLog10(lhs: DecimalSource) {
|
function internalIntegrateLog10(lhs: DecimalSource) {
|
||||||
|
@ -235,13 +266,15 @@ function internalInvertIntegralLog10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
const numerator = ln10.times(value);
|
const numerator = ln10.times(value);
|
||||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateLog10(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateLog10(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
return new Formula({
|
return new Formula({
|
||||||
inputs: [lhs.getIntegralFormula(stack)],
|
inputs: [lhs.getIntegralFormula(stack)],
|
||||||
|
@ -249,7 +282,8 @@ export function integrateLog10(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
invert: internalInvertIntegralLog10
|
invert: internalInvertIntegralLog10
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -258,7 +292,8 @@ export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function internalIntegrateLog(lhs: DecimalSource, rhs: DecimalSource) {
|
function internalIntegrateLog(lhs: DecimalSource, rhs: DecimalSource) {
|
||||||
|
@ -270,13 +305,15 @@ function internalInvertIntegralLog(value: DecimalSource, lhs: FormulaSource, rhs
|
||||||
const numerator = Decimal.ln(unrefFormulaSource(rhs)).times(value);
|
const numerator = Decimal.ln(unrefFormulaSource(rhs)).times(value);
|
||||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateLog(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateLog(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
return new Formula({
|
return new Formula({
|
||||||
inputs: [lhs.getIntegralFormula(stack), rhs],
|
inputs: [lhs.getIntegralFormula(stack), rhs],
|
||||||
|
@ -284,14 +321,16 @@ export function integrateLog(stack: SubstitutionStack, lhs: FormulaSource, rhs:
|
||||||
invert: internalInvertIntegralLog
|
invert: internalInvertIntegralLog
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertLog2(value: DecimalSource, lhs: FormulaSource) {
|
export function invertLog2(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.pow(2, value));
|
return lhs.invert(Decimal.pow(2, value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function internalIntegrateLog2(lhs: DecimalSource) {
|
function internalIntegrateLog2(lhs: DecimalSource) {
|
||||||
|
@ -303,13 +342,15 @@ function internalInvertIntegralLog2(value: DecimalSource, lhs: FormulaSource) {
|
||||||
const numerator = Decimal.ln(2).times(value);
|
const numerator = Decimal.ln(2).times(value);
|
||||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateLog2(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateLog2(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
return new Formula({
|
return new Formula({
|
||||||
inputs: [lhs.getIntegralFormula(stack)],
|
inputs: [lhs.getIntegralFormula(stack)],
|
||||||
|
@ -317,14 +358,16 @@ export function integrateLog2(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
invert: internalInvertIntegralLog2
|
invert: internalInvertIntegralLog2
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertLn(value: DecimalSource, lhs: FormulaSource) {
|
export function invertLn(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.exp(value));
|
return lhs.invert(Decimal.exp(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function internalIntegrateLn(lhs: DecimalSource) {
|
function internalIntegrateLn(lhs: DecimalSource) {
|
||||||
|
@ -335,13 +378,15 @@ function internalInvertIntegralLn(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.div(value, Decimal.div(value, Math.E).lambertw()));
|
return lhs.invert(Decimal.div(value, Decimal.div(value, Math.E).lambertw()));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateLn(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateLn(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
return new Formula({
|
return new Formula({
|
||||||
inputs: [lhs.getIntegralFormula(stack)],
|
inputs: [lhs.getIntegralFormula(stack)],
|
||||||
|
@ -349,7 +394,8 @@ export function integrateLn(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
invert: internalInvertIntegralLn
|
invert: internalInvertIntegralLn
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -358,43 +404,50 @@ export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(lhs))));
|
return rhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(lhs))));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integratePow(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integratePow(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
const pow = Formula.add(rhs, 1);
|
const pow = Formula.add(rhs, 1);
|
||||||
return Formula.pow(x, pow).div(pow);
|
return Formula.pow(x, pow).div(pow);
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
return Formula.pow(lhs, x).div(Formula.ln(lhs));
|
return Formula.pow(lhs, x).div(Formula.ln(lhs));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertPow10(value: DecimalSource, lhs: FormulaSource) {
|
export function invertPow10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.root(value, 10));
|
return lhs.invert(Decimal.root(value, 10));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integratePow10(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integratePow10(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.pow10(x).div(Formula.ln(10));
|
return Formula.pow10(x).div(Formula.ln(10));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -403,25 +456,29 @@ export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: For
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integratePowBase(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integratePowBase(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.pow(rhs, x).div(Formula.ln(rhs));
|
return Formula.pow(rhs, x).div(Formula.ln(rhs));
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
if (!rhs.isIntegrable()) {
|
if (!rhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = rhs.getIntegralFormula(stack);
|
const x = rhs.getIntegralFormula(stack);
|
||||||
const denominator = Formula.add(lhs, 1);
|
const denominator = Formula.add(lhs, 1);
|
||||||
return Formula.pow(x, denominator).div(denominator);
|
return Formula.pow(x, denominator).div(denominator);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
@ -430,36 +487,42 @@ export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: Formul
|
||||||
} else if (hasVariable(rhs)) {
|
} else if (hasVariable(rhs)) {
|
||||||
return rhs.invert(Decimal.ln(unrefFormulaSource(lhs)).div(Decimal.ln(value)));
|
return rhs.invert(Decimal.ln(unrefFormulaSource(lhs)).div(Decimal.ln(value)));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateRoot(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
export function integrateRoot(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.pow(x, Formula.recip(rhs).add(1)).times(rhs).div(Formula.add(rhs, 1));
|
return Formula.pow(x, Formula.recip(rhs).add(1)).times(rhs).div(Formula.add(rhs, 1));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertExp(value: DecimalSource, lhs: FormulaSource) {
|
export function invertExp(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.ln(value));
|
return lhs.invert(Decimal.ln(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateExp(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateExp(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.exp(x);
|
return Formula.exp(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tetrate(
|
export function tetrate(
|
||||||
|
@ -481,7 +544,8 @@ export function invertTetrate(
|
||||||
return base.invert(Decimal.ssqrt(value));
|
return base.invert(Decimal.ssqrt(value));
|
||||||
}
|
}
|
||||||
// Other params can't be inverted ATM
|
// Other params can't be inverted ATM
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function iteratedexp(
|
export function iteratedexp(
|
||||||
|
@ -509,7 +573,8 @@ export function invertIteratedExp(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Other params can't be inverted ATM
|
// Other params can't be inverted ATM
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function iteratedLog(
|
export function iteratedLog(
|
||||||
|
@ -533,7 +598,8 @@ export function invertSlog(value: DecimalSource, lhs: FormulaSource, rhs: Formul
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Other params can't be inverted ATM
|
// Other params can't be inverted ATM
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function layeradd(value: DecimalSource, diff: DecimalSource, base: DecimalSource) {
|
export function layeradd(value: DecimalSource, diff: DecimalSource, base: DecimalSource) {
|
||||||
|
@ -556,21 +622,24 @@ export function invertLayeradd(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Other params can't be inverted ATM
|
// Other params can't be inverted ATM
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertLambertw(value: DecimalSource, lhs: FormulaSource) {
|
export function invertLambertw(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.pow(Math.E, value).times(value));
|
return lhs.invert(Decimal.pow(Math.E, value).times(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertSsqrt(value: DecimalSource, lhs: FormulaSource) {
|
export function invertSsqrt(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.tetrate(value, 2));
|
return lhs.invert(Decimal.tetrate(value, 2));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pentate(value: DecimalSource, height: DecimalSource, payload: DecimalSource) {
|
export function pentate(value: DecimalSource, height: DecimalSource, payload: DecimalSource) {
|
||||||
|
@ -582,226 +651,262 @@ export function invertSin(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.asin(value));
|
return lhs.invert(Decimal.asin(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateSin(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateSin(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.cos(x).neg();
|
return Formula.cos(x).neg();
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertCos(value: DecimalSource, lhs: FormulaSource) {
|
export function invertCos(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.acos(value));
|
return lhs.invert(Decimal.acos(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateCos(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateCos(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.sin(x);
|
return Formula.sin(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertTan(value: DecimalSource, lhs: FormulaSource) {
|
export function invertTan(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.atan(value));
|
return lhs.invert(Decimal.atan(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateTan(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateTan(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.cos(x).ln().neg();
|
return Formula.cos(x).ln().neg();
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAsin(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAsin(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.sin(value));
|
return lhs.invert(Decimal.sin(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAsin(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAsin(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.asin(x)
|
return Formula.asin(x)
|
||||||
.times(x)
|
.times(x)
|
||||||
.add(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
.add(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAcos(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAcos(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.cos(value));
|
return lhs.invert(Decimal.cos(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAcos(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAcos(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.acos(x)
|
return Formula.acos(x)
|
||||||
.times(x)
|
.times(x)
|
||||||
.sub(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
.sub(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAtan(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAtan(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.tan(value));
|
return lhs.invert(Decimal.tan(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAtan(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAtan(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.atan(x)
|
return Formula.atan(x)
|
||||||
.times(x)
|
.times(x)
|
||||||
.sub(Formula.ln(Formula.pow(x, 2).add(1)).div(2));
|
.sub(Formula.ln(Formula.pow(x, 2).add(1)).div(2));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertSinh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertSinh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.asinh(value));
|
return lhs.invert(Decimal.asinh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateSinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateSinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.cosh(x);
|
return Formula.cosh(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertCosh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertCosh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.acosh(value));
|
return lhs.invert(Decimal.acosh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateCosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateCosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.sinh(x);
|
return Formula.sinh(x);
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertTanh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertTanh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.atanh(value));
|
return lhs.invert(Decimal.atanh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateTanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateTanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.cosh(x).ln();
|
return Formula.cosh(x).ln();
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAsinh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAsinh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.sinh(value));
|
return lhs.invert(Decimal.sinh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAsinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAsinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.asinh(x).times(x).sub(Formula.pow(x, 2).add(1).sqrt());
|
return Formula.asinh(x).times(x).sub(Formula.pow(x, 2).add(1).sqrt());
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAcosh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAcosh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.cosh(value));
|
return lhs.invert(Decimal.cosh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAcosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAcosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.acosh(x)
|
return Formula.acosh(x)
|
||||||
.times(x)
|
.times(x)
|
||||||
.sub(Formula.add(x, 1).sqrt().times(Formula.sub(x, 1).sqrt()));
|
.sub(Formula.add(x, 1).sqrt().times(Formula.sub(x, 1).sqrt()));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invertAtanh(value: DecimalSource, lhs: FormulaSource) {
|
export function invertAtanh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
return lhs.invert(Decimal.tanh(value));
|
return lhs.invert(Decimal.tanh(value));
|
||||||
}
|
}
|
||||||
throw new Error("Could not invert due to no input being a variable");
|
console.error("Could not invert due to no input being a variable");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integrateAtanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
export function integrateAtanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||||
if (hasVariable(lhs)) {
|
if (hasVariable(lhs)) {
|
||||||
if (!lhs.isIntegrable()) {
|
if (!lhs.isIntegrable()) {
|
||||||
throw new Error("Could not integrate due to variable not being integrable");
|
console.error("Could not integrate due to variable not being integrable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
const x = lhs.getIntegralFormula(stack);
|
const x = lhs.getIntegralFormula(stack);
|
||||||
return Formula.atanh(x)
|
return Formula.atanh(x)
|
||||||
.times(x)
|
.times(x)
|
||||||
.add(Formula.sub(1, Formula.pow(x, 2)).ln().div(2));
|
.add(Formula.sub(1, Formula.pow(x, 2)).ln().div(2));
|
||||||
}
|
}
|
||||||
throw new Error("Could not integrate due to no input being a variable");
|
console.error("Could not integrate due to no input being a variable");
|
||||||
|
return Formula.constant(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPassthroughBinaryFormula(
|
export function createPassthroughBinaryFormula(
|
||||||
|
|
|
@ -225,7 +225,9 @@ export function createLayer<T extends LayerOptions>(
|
||||||
addingLayers[addingLayers.length - 1] == null ||
|
addingLayers[addingLayers.length - 1] == null ||
|
||||||
addingLayers[addingLayers.length - 1] !== id
|
addingLayers[addingLayers.length - 1] !== id
|
||||||
) {
|
) {
|
||||||
throw `Adding layers stack in invalid state. This should not happen\nStack: ${addingLayers}\nTrying to pop ${layer.id}`;
|
throw new Error(
|
||||||
|
`Adding layers stack in invalid state. This should not happen\nStack: ${addingLayers}\nTrying to pop ${layer.id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
addingLayers.pop();
|
addingLayers.pop();
|
||||||
|
|
||||||
|
|
|
@ -116,12 +116,7 @@ function checkNaNAndWrite<T extends State>(persistent: Persistent<T>, value: T)
|
||||||
state.NaNPath = persistent[SaveDataPath];
|
state.NaNPath = persistent[SaveDataPath];
|
||||||
state.NaNPersistent = persistent as Persistent<DecimalSource>;
|
state.NaNPersistent = persistent as Persistent<DecimalSource>;
|
||||||
}
|
}
|
||||||
console.error(
|
console.error(`Attempted to save NaN value to ${persistent[SaveDataPath]?.join(".")}`);
|
||||||
`Attempted to save NaN value to`,
|
|
||||||
persistent[SaveDataPath]?.join("."),
|
|
||||||
persistent
|
|
||||||
);
|
|
||||||
throw new Error("Attempted to set NaN value. See above for details");
|
|
||||||
}
|
}
|
||||||
persistent[PersistentState].value = value;
|
persistent[PersistentState].value = value;
|
||||||
}
|
}
|
||||||
|
@ -292,8 +287,8 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
||||||
"."
|
"."
|
||||||
)}\` when it's already present at \`${value[SaveDataPath].join(
|
)}\` when it's already present at \`${value[SaveDataPath].join(
|
||||||
"."
|
"."
|
||||||
)}\`. This can cause unexpected behavior when loading saves between updates.`,
|
)}\`.`,
|
||||||
value
|
"This can cause unexpected behavior when loading saves between updates."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
value[SaveDataPath] = newPath;
|
value[SaveDataPath] = newPath;
|
||||||
|
@ -368,9 +363,9 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.error(
|
console.error(
|
||||||
`Created persistent ref in ${layer.id} without registering it to the layer! Make sure to include everything persistent in the returned object`,
|
`Created persistent ref in ${layer.id} without registering it to the layer!`,
|
||||||
persistent,
|
"Make sure to include everything persistent in the returned object.\n\nCreated at:\n" +
|
||||||
"\nCreated at:\n" + persistent[StackTrace]
|
persistent[StackTrace]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
persistentRefs[layer.id].clear();
|
persistentRefs[layer.id].clear();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { DecimalSource } from "util/bignum";
|
import type { DecimalSource } from "util/bignum";
|
||||||
import { shallowReactive } from "vue";
|
import { reactive, shallowReactive } from "vue";
|
||||||
import type { Persistent } from "./persistence";
|
import type { Persistent } from "./persistence";
|
||||||
|
|
||||||
/** An object of global data that is not persistent. */
|
/** An object of global data that is not persistent. */
|
||||||
|
@ -12,6 +12,8 @@ export interface Transient {
|
||||||
NaNPath?: string[];
|
NaNPath?: string[];
|
||||||
/** The ref that was being set to NaN. */
|
/** The ref that was being set to NaN. */
|
||||||
NaNPersistent?: Persistent<DecimalSource>;
|
NaNPersistent?: Persistent<DecimalSource>;
|
||||||
|
/** List of errors that have occurred, to show the user. */
|
||||||
|
errors: Error[];
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -24,5 +26,6 @@ declare global {
|
||||||
export default window.state = shallowReactive<Transient>({
|
export default window.state = shallowReactive<Transient>({
|
||||||
lastTenTicks: [],
|
lastTenTicks: [],
|
||||||
hasNaN: false,
|
hasNaN: false,
|
||||||
NaNPath: []
|
NaNPath: [],
|
||||||
|
errors: reactive([])
|
||||||
});
|
});
|
||||||
|
|
27
src/main.ts
27
src/main.ts
|
@ -2,6 +2,7 @@ import "@fontsource/material-icons";
|
||||||
import App from "App.vue";
|
import App from "App.vue";
|
||||||
import projInfo from "data/projInfo.json";
|
import projInfo from "data/projInfo.json";
|
||||||
import "game/notifications";
|
import "game/notifications";
|
||||||
|
import state from "game/state";
|
||||||
import { load } from "util/save";
|
import { load } from "util/save";
|
||||||
import { useRegisterSW } from "virtual:pwa-register/vue";
|
import { useRegisterSW } from "virtual:pwa-register/vue";
|
||||||
import type { App as VueApp } from "vue";
|
import type { App as VueApp } from "vue";
|
||||||
|
@ -23,11 +24,30 @@ declare global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const error = console.error;
|
||||||
|
console.error = function (...args) {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
state.errors.push(new Error(args[0], { cause: args[1] }));
|
||||||
|
}
|
||||||
|
error(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onerror = function (event, source, lineno, colno, error) {
|
||||||
|
state.errors.push(error instanceof Error ? error : new Error(JSON.stringify(error)));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
window.onunhandledrejection = function (event) {
|
||||||
|
state.errors.push(
|
||||||
|
event.reason instanceof Error ? event.reason : new Error(JSON.stringify(event.reason))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
document.title = projInfo.title;
|
document.title = projInfo.title;
|
||||||
window.projInfo = projInfo;
|
window.projInfo = projInfo;
|
||||||
if (projInfo.id === "") {
|
if (projInfo.id === "") {
|
||||||
throw new Error(
|
console.error(
|
||||||
"Project ID is empty! Please select a unique ID for this project in /src/data/projInfo.json"
|
"Project ID is empty!",
|
||||||
|
"Please select a unique ID for this project in /src/data/projInfo.json"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +63,9 @@ requestAnimationFrame(async () => {
|
||||||
|
|
||||||
// Create Vue
|
// Create Vue
|
||||||
const vue = (window.vue = createApp(App));
|
const vue = (window.vue = createApp(App));
|
||||||
|
vue.config.errorHandler = function (err, instance, info) {
|
||||||
|
console.error(err, info, instance);
|
||||||
|
};
|
||||||
globalBus.emit("setupVue", vue);
|
globalBus.emit("setupVue", vue);
|
||||||
vue.mount("#app");
|
vue.mount("#app");
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ export function createLazyProxy<T extends object, S extends T>(
|
||||||
function calculateObj(): T {
|
function calculateObj(): T {
|
||||||
if (!calculated) {
|
if (!calculated) {
|
||||||
if (calculating) {
|
if (calculating) {
|
||||||
throw new Error("Cyclical dependency detected. Cannot evaluate lazy proxy.");
|
console.error("Cyclical dependency detected. Cannot evaluate lazy proxy.");
|
||||||
}
|
}
|
||||||
calculating = true;
|
calculating = true;
|
||||||
Object.assign(obj, objectFunc.call(obj, obj));
|
Object.assign(obj, objectFunc.call(obj, obj));
|
||||||
|
|
Loading…
Reference in a new issue