diff --git a/packages/doenetml-worker/src/components/linearAlgebra/EigenDecomposition.js b/packages/doenetml-worker/src/components/linearAlgebra/EigenDecomposition.js
index c8f31d870..c0142983d 100644
--- a/packages/doenetml-worker/src/components/linearAlgebra/EigenDecomposition.js
+++ b/packages/doenetml-worker/src/components/linearAlgebra/EigenDecomposition.js
@@ -307,7 +307,8 @@ export default class EigenDecomposition extends BaseComponent {
let vectorMag = 0;
for (let j = 0; j < arraySize[0]; j++) {
let val =
- globalDependencyValues.decomposition.vectors[j][i];
+ globalDependencyValues.decomposition.eigenvectors[i]
+ .vector[j];
vector.push(val);
vectorMag += me.math.square(me.math.abs(val));
}
diff --git a/packages/doenetml-worker/src/test/linearAlgebra/eigenDecomposition.test.ts b/packages/doenetml-worker/src/test/linearAlgebra/eigenDecomposition.test.ts
new file mode 100644
index 000000000..bcd40c000
--- /dev/null
+++ b/packages/doenetml-worker/src/test/linearAlgebra/eigenDecomposition.test.ts
@@ -0,0 +1,614 @@
+import { describe, expect, it, vi } from "vitest";
+import { createTestCore, returnAllStateVariables } from "../utils/test-core";
+import me from "math-expressions";
+import Core from "../../Core";
+
+const Mock = vi.fn();
+vi.stubGlobal("postMessage", Mock);
+vi.mock("hyperformula");
+
+describe("EigenDecomposition Tag Tests", async () => {
+ function reviveComplex(num: number | { re: number; im: number }) {
+ if (typeof num === "number") {
+ return me.math.complex({ re: num, im: 0 });
+ } else {
+ return me.math.complex({ re: num.re, im: num.im });
+ }
+ }
+
+ it("2x2 matrices", async () => {
+ let core = await createTestCore({
+ doenetML: `
+
A =
+ B =
+
+
+ $A
+
+
+ $B
+
+
+ Eigenvalues of A:
+ 1st eigenvalue of A:
+ 2nd eigenvalue of A:
+
+ Eigenvectors of A:
+ 1st eigenvector of A:
+ 2nd eigenvector of A:
+ 1st component of 1st eigenvector of A:
+ 2nd component of 1st eigenvector of A:
+
+ Eigenvalues of B:
+ 1st eigenvalue of B:
+ 2nd eigenvalue of B:
+
+ Eigenvectors of B:
+ 1st eigenvector of B:
+ 2nd eigenvector of B:
+ 1st component of 1st eigenvector of B:
+ 2nd component of 1st eigenvector of B:
+
+ `,
+ });
+
+ let stateVariables = await returnAllStateVariables(core);
+ expect(stateVariables["/pAevs"].stateValues.text).eqls(
+ "Eigenvalues of A: -1, 3",
+ );
+ expect(stateVariables["/Aev1"].stateValues.value).eqls(-1);
+ expect(stateVariables["/Aev2"].stateValues.value).eqls(3);
+
+ expect(stateVariables["/pBevs"].stateValues.text).eqls(
+ "Eigenvalues of B: 1 + 2 i, 1 - 2 i",
+ );
+ expect(stateVariables["/Bev1"].stateValues.text).eqls("1 + 2 i");
+ expect(stateVariables["/Bev2"].stateValues.text).eqls("1 - 2 i");
+
+ expect(stateVariables["/Ad"].stateValues.eigenvalues).eqls([-1, 3]);
+ expect(stateVariables["/Aev1"].stateValues.value).eq(-1);
+ expect(stateVariables["/Aev1a"].stateValues.value).eq(-1);
+ expect(stateVariables["/Aev2"].stateValues.value).eq(3);
+ expect(stateVariables["/Aev2a"].stateValues.value).eq(3);
+
+ expect(
+ stateVariables["/Ad"].stateValues.eigenvectors[0][1] /
+ stateVariables["/Ad"].stateValues.eigenvectors[0][0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Ad"].stateValues.eigenvectors[1][1] /
+ stateVariables["/Ad"].stateValues.eigenvectors[1][0],
+ ).closeTo(1, 1e-14);
+
+ expect(
+ stateVariables["/Aevec1"].stateValues.displacement[1] /
+ stateVariables["/Aevec1"].stateValues.displacement[0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Aevec1a"].stateValues.displacement[1] /
+ stateVariables["/Aevec1a"].stateValues.displacement[0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Aevec2"].stateValues.displacement[1] /
+ stateVariables["/Aevec2"].stateValues.displacement[0],
+ ).closeTo(1, 1e-14);
+ expect(
+ stateVariables["/Aevec2a"].stateValues.displacement[1] /
+ stateVariables["/Aevec2a"].stateValues.displacement[0],
+ ).closeTo(1, 1e-14);
+ expect(
+ stateVariables["/Aevec1y"].stateValues.value /
+ stateVariables["/Aevec1x"].stateValues.value,
+ ).closeTo(-1, 1e-14);
+
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[0].re).closeTo(
+ 1,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[0].im).closeTo(
+ 2,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[1].re).closeTo(
+ 1,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[1].im).closeTo(
+ -2,
+ 1e-14,
+ );
+ expect(stateVariables["/Bev1"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev1"].stateValues.value.im).closeTo(2, 1e-14);
+ expect(stateVariables["/Bev1a"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev1a"].stateValues.value.im).closeTo(2, 1e-14);
+ expect(stateVariables["/Bev2"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev2"].stateValues.value.im).closeTo(-2, 1e-14);
+ expect(stateVariables["/Bev2a"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev2a"].stateValues.value.im).closeTo(
+ -2,
+ 1e-14,
+ );
+
+ let ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[0][1]),
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[0][0]),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+ ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[1][1]),
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[1][0]),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec1"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec1"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec1a"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec1a"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec2"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec2"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec2a"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec2a"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bevec1y"].stateValues.value),
+ reviveComplex(stateVariables["/Bevec1x"].stateValues.value),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+ });
+
+ it("2x2 matrices, fractions", async () => {
+ let core = await createTestCore({
+ doenetML: `
+ A =
+ B =
+
+
+ $A
+
+
+ $B
+
+
+ Eigenvalues of A:
+ 1st eigenvalue of A:
+ 2nd eigenvalue of A:
+
+ Eigenvectors of A:
+ 1st eigenvector of A:
+ 2nd eigenvector of A:
+ 1st component of 1st eigenvector of A:
+ 2nd component of 1st eigenvector of A:
+
+ Eigenvalues of B:
+ 1st eigenvalue of B:
+ 2nd eigenvalue of B:
+
+ Eigenvectors of B:
+ 1st eigenvector of B:
+ 2nd eigenvector of B:
+ 1st component of 1st eigenvector of B:
+ 2nd component of 1st eigenvector of B:
+ `,
+ });
+
+ let stateVariables = await returnAllStateVariables(core);
+ expect(stateVariables["/pAevs"].stateValues.text).eqls(
+ "Eigenvalues of A: -1, 3",
+ );
+ expect(stateVariables["/Aev1"].stateValues.value).eqls(-1);
+ expect(stateVariables["/Aev2"].stateValues.value).eqls(3);
+
+ expect(stateVariables["/pBevs"].stateValues.text).eqls(
+ "Eigenvalues of B: 1 + 2 i, 1 - 2 i",
+ );
+ expect(stateVariables["/Bev1"].stateValues.text).eqls("1 + 2 i");
+ expect(stateVariables["/Bev2"].stateValues.text).eqls("1 - 2 i");
+
+ expect(stateVariables["/Ad"].stateValues.eigenvalues).eqls([-1, 3]);
+ expect(stateVariables["/Aev1"].stateValues.value).eq(-1);
+ expect(stateVariables["/Aev1a"].stateValues.value).eq(-1);
+ expect(stateVariables["/Aev2"].stateValues.value).eq(3);
+ expect(stateVariables["/Aev2a"].stateValues.value).eq(3);
+
+ expect(
+ stateVariables["/Ad"].stateValues.eigenvectors[0][1] /
+ stateVariables["/Ad"].stateValues.eigenvectors[0][0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Ad"].stateValues.eigenvectors[1][1] /
+ stateVariables["/Ad"].stateValues.eigenvectors[1][0],
+ ).closeTo(1, 1e-14);
+
+ expect(
+ stateVariables["/Aevec1"].stateValues.displacement[1] /
+ stateVariables["/Aevec1"].stateValues.displacement[0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Aevec1a"].stateValues.displacement[1] /
+ stateVariables["/Aevec1a"].stateValues.displacement[0],
+ ).closeTo(-1, 1e-14);
+ expect(
+ stateVariables["/Aevec2"].stateValues.displacement[1] /
+ stateVariables["/Aevec2"].stateValues.displacement[0],
+ ).closeTo(1, 1e-14);
+ expect(
+ stateVariables["/Aevec2a"].stateValues.displacement[1] /
+ stateVariables["/Aevec2a"].stateValues.displacement[0],
+ ).closeTo(1, 1e-14);
+ expect(
+ stateVariables["/Aevec1y"].stateValues.value /
+ stateVariables["/Aevec1x"].stateValues.value,
+ ).closeTo(-1, 1e-14);
+
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[0].re).closeTo(
+ 1,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[0].im).closeTo(
+ 2,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[1].re).closeTo(
+ 1,
+ 1e-14,
+ );
+ expect(stateVariables["/Bd"].stateValues.eigenvalues[1].im).closeTo(
+ -2,
+ 1e-14,
+ );
+ expect(stateVariables["/Bev1"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev1"].stateValues.value.im).closeTo(2, 1e-14);
+ expect(stateVariables["/Bev1a"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev1a"].stateValues.value.im).closeTo(2, 1e-14);
+ expect(stateVariables["/Bev2"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev2"].stateValues.value.im).closeTo(-2, 1e-14);
+ expect(stateVariables["/Bev2a"].stateValues.value.re).closeTo(1, 1e-14);
+ expect(stateVariables["/Bev2a"].stateValues.value.im).closeTo(
+ -2,
+ 1e-14,
+ );
+
+ let ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[0][1]),
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[0][0]),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+ ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[1][1]),
+ reviveComplex(stateVariables["/Bd"].stateValues.eigenvectors[1][0]),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec1"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec1"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec1a"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec1a"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec2"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec2"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ me
+ .fromAst(stateVariables["/Bevec2a"].stateValues.displacement[1])
+ .evaluate_to_constant(),
+ me
+ .fromAst(stateVariables["/Bevec2a"].stateValues.displacement[0])
+ .evaluate_to_constant(),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(-1, 1e-14);
+
+ ratio = me.math.divide(
+ reviveComplex(stateVariables["/Bevec1y"].stateValues.value),
+ reviveComplex(stateVariables["/Bevec1x"].stateValues.value),
+ );
+ expect(ratio.re).closeTo(0, 1e-14);
+ expect(ratio.im).closeTo(1, 1e-14);
+ });
+
+ it("3x3 matrices with real eigenvectors", async () => {
+ let core = await createTestCore({
+ doenetML: `
+
+ 1 2 3
+ 4 5 6
+ 7 8 9
+
+$A
+ `,
+ });
+
+ const stateVariables = await returnAllStateVariables(core);
+ const eigvals = stateVariables["/eig"].stateValues.eigenvalues;
+ const eigvecs = stateVariables["/eig"].stateValues.eigenvectors;
+ expect(eigvals[0]).closeTo(0, 1e-14);
+ const ev0x = 1;
+ const ev0y = -2;
+ const ev0z = 1;
+ expect(eigvecs[0][0] / eigvecs[0][1]).closeTo(ev0x / ev0y, 1e-13);
+ expect(eigvecs[0][0] / eigvecs[0][2]).closeTo(ev0x / ev0z, 1e-13);
+
+ expect(eigvals[1]).closeTo((-3 / 2) * (Math.sqrt(33) - 5), 1e-14);
+ const ev1x = (1 / 22) * (-11 - 3 * Math.sqrt(33));
+ const ev1y = (1 / 44) * (11 - 3 * Math.sqrt(33));
+ const ev1z = 1;
+ expect(eigvecs[1][0] / eigvecs[1][1]).closeTo(ev1x / ev1y, 1e-13);
+ expect(eigvecs[1][0] / eigvecs[1][2]).closeTo(ev1x / ev1z, 1e-13);
+
+ expect(eigvals[2]).closeTo((3 / 2) * (5 + Math.sqrt(33)), 1e-14);
+ const ev2x = (1 / 22) * (-11 + 3 * Math.sqrt(33));
+ const ev2y = (1 / 44) * (11 + 3 * Math.sqrt(33));
+ const ev2z = 1;
+ expect(eigvecs[2][0] / eigvecs[2][1]).closeTo(ev2x / ev2y, 1e-13);
+ expect(eigvecs[2][0] / eigvecs[2][2]).closeTo(ev2x / ev2z, 1e-13);
+ });
+
+ async function check_eigendecomposition({
+ evecs,
+ evals,
+ core,
+ decompositionName,
+ }: {
+ evecs: any[][];
+ evals: any[];
+ core: Core;
+ decompositionName: string;
+ }) {
+ const stateVariables = await returnAllStateVariables(core);
+ const actualEvals =
+ stateVariables[decompositionName].stateValues.eigenvalues.map(
+ reviveComplex,
+ );
+ const actualEvecs = stateVariables[
+ decompositionName
+ ].stateValues.eigenvectors.map((v) => v.map(reviveComplex));
+ const n = evecs.length;
+ expect(actualEvals.length).eqls(n);
+ expect(actualEvecs.length).eqls(n);
+
+ for (let i = 0; i < n; i++) {
+ expect(actualEvals[i].re).closeTo(evals[i].re, 1e-12);
+ expect(actualEvals[i].im).closeTo(evals[i].im, 1e-12);
+
+ for (let j = 1; j < n; j++) {
+ let ratio = me.math.divide(evecs[i][0], evecs[i][j]);
+ let actualRatio = me.math.divide(
+ actualEvecs[i][0],
+ actualEvecs[i][j],
+ );
+ expect(actualRatio.re).closeTo(ratio.re, 1e-12);
+ expect(actualRatio.im).closeTo(ratio.im, 1e-12);
+ }
+ }
+ }
+
+ it("3x3 matrix, center and spirals", async () => {
+ let core = await createTestCore({
+ doenetML: `
+
+-9
+-4
+-8
+9
+-1
+-5
+
+-(2*$a11 *$a22 *$a33 +$a11 *$a22 *($a11 +$a22 )+$a11 *$a33 *($a11 +$a33 )+$a22 *$a33 *($a22 +$a33 ) - $a12 *$a23 *$a31 )
+$a31 *($a11 +$a33 )+$a12 *($a11 +$a22 )+$a23 *($a22 +$a33 )
+$b **3/27 + $c **2/4
+$b /(3*($c /2 + sqrt($sqrt_arg ))**(1/3)) - ($c /2 + sqrt($sqrt_arg ))**(1/3)
+
+$parCenter + 0.1
+$parCenter - 0.1
+
+
+$A_center
+
+
+$A_stableSpiral
+
+
+
+$A_unstableSpiral
+
+ `,
+ });
+
+ // Center
+ let evals = [me.math.complex({ re: 0, im: 14.78846823004614 })];
+ evals.push(me.math.conj(evals[0]));
+ evals.push(me.math.complex({ re: -22, im: 0 }));
+
+ let evecs = [
+ [
+ me.math.complex({
+ re: -0.426486035260864,
+ im: -0.270682079730474,
+ }),
+ me.math.complex({ re: 0.627291349345459, im: 0 }),
+ me.math.complex({
+ re: -0.173343062597144,
+ im: 0.566832090769437,
+ }),
+ ],
+ ];
+ evecs.push(evecs[0].map((v) => me.math.conj(v)));
+ evecs.push(
+ [-0.725759948499824, -0.487701621853287, -0.485200603044974].map(
+ (v) => me.math.complex({ re: v, im: 0 }),
+ ),
+ );
+ await check_eigendecomposition({
+ evecs,
+ evals,
+ core,
+ decompositionName: "/Ad_center",
+ });
+
+ // Stable spiral
+ evals = [
+ me.math.complex({ re: -0.048287227932923, im: 14.703099997319454 }),
+ me.math.complex({
+ re: -0.048287227932923,
+ im: -14.703099997319454,
+ }),
+ me.math.complex({ re: -21.903425544134173, im: 0 }),
+ ];
+ evecs = [
+ [
+ me.math.complex({
+ re: -0.427048386266709,
+ im: -0.269189626634008,
+ }),
+ me.math.complex({ re: 0.627621340142377, im: 0 }),
+ me.math.complex({
+ re: -0.172635887510845,
+ im: 0.566969950209772,
+ }),
+ ],
+ ];
+ evecs.push(evecs[0].map((v) => me.math.conj(v)));
+ evecs.push(
+ [-0.726546459838247, -0.48712036969194, -0.484607044034337].map(
+ (v) => me.math.complex({ re: v, im: 0 }),
+ ),
+ );
+
+ await check_eigendecomposition({
+ evecs,
+ evals,
+ core,
+ decompositionName: "/Ad_stable",
+ });
+
+ // Unstable spiral
+ evals = [
+ me.math.complex({ re: 0.048306535292557, im: 14.873845525216694 }),
+ me.math.complex({ re: 0.048306535292557, im: -14.873845525216694 }),
+ me.math.complex({ re: -22.0966130705851, im: 0 }),
+ ];
+ evecs = [
+ [
+ me.math.complex({
+ re: -0.425927192657446,
+ im: -0.272156678632516,
+ }),
+ me.math.complex({ re: 0.626965239909586, im: 0 }),
+ me.math.complex({
+ re: -0.174042517907594,
+ im: 0.566692649269571,
+ }),
+ ],
+ ];
+ evecs.push(evecs[0].map((v) => me.math.conj(v)));
+ evecs.push(
+ [-0.724981295406814, -0.488275620239871, -0.485787031516515].map(
+ (v) => me.math.complex({ re: v, im: 0 }),
+ ),
+ );
+
+ await check_eigendecomposition({
+ evecs,
+ evals,
+ core,
+ decompositionName: "/Ad_unstable",
+ });
+ });
+});
diff --git a/packages/test-cypress/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js b/packages/test-cypress/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js
deleted file mode 100644
index d46fd850a..000000000
--- a/packages/test-cypress/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js
+++ /dev/null
@@ -1,503 +0,0 @@
-import me from "math-expressions";
-import { cesc } from "@doenet/utils";
-
-describe("EigenDecomposition Tag Tests", function () {
- beforeEach(() => {
- cy.clearIndexedDB();
- cy.visit("/");
- });
-
- it("2x2 matrices", () => {
- cy.window().then(async (win) => {
- win.postMessage(
- {
- doenetML: `
- a
- A =
- B =
-
-
- $A
-
-
- $B
-
-
- Eigenvalues of A:
- 1st eigenvalue of A:
- 2nd eigenvalue of A:
-
- Eigenvectors of A:
- 1st eigenvector of A:
- 2nd eigenvector of A:
- 1st component of 1st eigenvector of A:
- 2nd component of 1st eigenvector of A:
-
- Eigenvalues of B:
- 1st eigenvalue of B:
- 2nd eigenvalue of B:
-
- Eigenvectors of B:
- 1st eigenvector of B:
- 2nd eigenvector of B:
- 1st component of 1st eigenvector of B:
- 2nd component of 1st eigenvector of B:
-
- `,
- },
- "*",
- );
- });
-
- cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
-
- cy.get(cesc("#\\/pAevs")).should(
- "have.text",
- "Eigenvalues of A: -1, 3",
- );
- cy.get(cesc("#\\/Aev1")).should("have.text", "-1");
- cy.get(cesc("#\\/Aev2")).should("have.text", "3");
-
- cy.get(cesc("#\\/pBevs")).should(
- "have.text",
- "Eigenvalues of B: 1 + 2 i, 1 - 2 i",
- );
- cy.get(cesc("#\\/Bev1")).should("have.text", "1 + 2 i");
- cy.get(cesc("#\\/Bev2")).should("have.text", "1 - 2 i");
-
- cy.window().then(async (win) => {
- let stateVariables = await win.returnAllStateVariables1();
- expect(stateVariables["/Ad"].stateValues.eigenvalues).eqls([-1, 3]);
- expect(stateVariables["/Aev1"].stateValues.value).eq(-1);
- expect(stateVariables["/Aev1a"].stateValues.value).eq(-1);
- expect(stateVariables["/Aev2"].stateValues.value).eq(3);
- expect(stateVariables["/Aev2a"].stateValues.value).eq(3);
-
- expect(
- stateVariables["/Ad"].stateValues.eigenvectors[0][1] /
- stateVariables["/Ad"].stateValues.eigenvectors[0][0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Ad"].stateValues.eigenvectors[1][1] /
- stateVariables["/Ad"].stateValues.eigenvectors[1][0],
- ).closeTo(1, 1e-14);
-
- expect(
- stateVariables["/Aevec1"].stateValues.displacement[1] /
- stateVariables["/Aevec1"].stateValues.displacement[0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Aevec1a"].stateValues.displacement[1] /
- stateVariables["/Aevec1a"].stateValues.displacement[0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Aevec2"].stateValues.displacement[1] /
- stateVariables["/Aevec2"].stateValues.displacement[0],
- ).closeTo(1, 1e-14);
- expect(
- stateVariables["/Aevec2a"].stateValues.displacement[1] /
- stateVariables["/Aevec2a"].stateValues.displacement[0],
- ).closeTo(1, 1e-14);
- expect(
- stateVariables["/Aevec1y"].stateValues.value /
- stateVariables["/Aevec1x"].stateValues.value,
- ).closeTo(-1, 1e-14);
-
- expect(stateVariables["/Bd"].stateValues.eigenvalues[0].re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[0].im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[1].re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[1].im).closeTo(
- -2,
- 1e-14,
- );
- expect(stateVariables["/Bev1"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev1"].stateValues.value.im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bev1a"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev1a"].stateValues.value.im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bev2"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev2"].stateValues.value.im).closeTo(
- -2,
- 1e-14,
- );
- expect(stateVariables["/Bev2a"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev2a"].stateValues.value.im).closeTo(
- -2,
- 1e-14,
- );
-
- let ratio = me.math.divide(
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[0][1],
- ),
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[0][0],
- ),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
- ratio = me.math.divide(
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[1][1],
- ),
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[1][0],
- ),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec1"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec1"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec1a"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec1a"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec2"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec2"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec2a"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec2a"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- reviveComplex(stateVariables["/Bevec1y"].stateValues.value),
- reviveComplex(stateVariables["/Bevec1x"].stateValues.value),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
- });
- });
-
- it("2x2 matrices, fractions", () => {
- cy.window().then(async (win) => {
- win.postMessage(
- {
- doenetML: `
- a
- A =
- B =
-
-
- $A
-
-
- $B
-
-
- Eigenvalues of A:
- 1st eigenvalue of A:
- 2nd eigenvalue of A:
-
- Eigenvectors of A:
- 1st eigenvector of A:
- 2nd eigenvector of A:
- 1st component of 1st eigenvector of A:
- 2nd component of 1st eigenvector of A:
-
- Eigenvalues of B:
- 1st eigenvalue of B:
- 2nd eigenvalue of B:
-
- Eigenvectors of B:
- 1st eigenvector of B:
- 2nd eigenvector of B:
- 1st component of 1st eigenvector of B:
- 2nd component of 1st eigenvector of B:
-
- `,
- },
- "*",
- );
- });
-
- cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
-
- cy.get(cesc("#\\/pAevs")).should(
- "have.text",
- "Eigenvalues of A: -1, 3",
- );
- cy.get(cesc("#\\/Aev1")).should("have.text", "-1");
- cy.get(cesc("#\\/Aev2")).should("have.text", "3");
-
- cy.get(cesc("#\\/pBevs")).should(
- "have.text",
- "Eigenvalues of B: 1 + 2 i, 1 - 2 i",
- );
- cy.get(cesc("#\\/Bev1")).should("have.text", "1 + 2 i");
- cy.get(cesc("#\\/Bev2")).should("have.text", "1 - 2 i");
-
- cy.window().then(async (win) => {
- let stateVariables = await win.returnAllStateVariables1();
- expect(stateVariables["/Ad"].stateValues.eigenvalues).eqls([-1, 3]);
- expect(stateVariables["/Aev1"].stateValues.value).eq(-1);
- expect(stateVariables["/Aev1a"].stateValues.value).eq(-1);
- expect(stateVariables["/Aev2"].stateValues.value).eq(3);
- expect(stateVariables["/Aev2a"].stateValues.value).eq(3);
-
- expect(
- stateVariables["/Ad"].stateValues.eigenvectors[0][1] /
- stateVariables["/Ad"].stateValues.eigenvectors[0][0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Ad"].stateValues.eigenvectors[1][1] /
- stateVariables["/Ad"].stateValues.eigenvectors[1][0],
- ).closeTo(1, 1e-14);
-
- expect(
- stateVariables["/Aevec1"].stateValues.displacement[1] /
- stateVariables["/Aevec1"].stateValues.displacement[0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Aevec1a"].stateValues.displacement[1] /
- stateVariables["/Aevec1a"].stateValues.displacement[0],
- ).closeTo(-1, 1e-14);
- expect(
- stateVariables["/Aevec2"].stateValues.displacement[1] /
- stateVariables["/Aevec2"].stateValues.displacement[0],
- ).closeTo(1, 1e-14);
- expect(
- stateVariables["/Aevec2a"].stateValues.displacement[1] /
- stateVariables["/Aevec2a"].stateValues.displacement[0],
- ).closeTo(1, 1e-14);
- expect(
- stateVariables["/Aevec1y"].stateValues.value /
- stateVariables["/Aevec1x"].stateValues.value,
- ).closeTo(-1, 1e-14);
-
- expect(stateVariables["/Bd"].stateValues.eigenvalues[0].re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[0].im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[1].re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bd"].stateValues.eigenvalues[1].im).closeTo(
- -2,
- 1e-14,
- );
- expect(stateVariables["/Bev1"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev1"].stateValues.value.im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bev1a"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev1a"].stateValues.value.im).closeTo(
- 2,
- 1e-14,
- );
- expect(stateVariables["/Bev2"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev2"].stateValues.value.im).closeTo(
- -2,
- 1e-14,
- );
- expect(stateVariables["/Bev2a"].stateValues.value.re).closeTo(
- 1,
- 1e-14,
- );
- expect(stateVariables["/Bev2a"].stateValues.value.im).closeTo(
- -2,
- 1e-14,
- );
-
- let ratio = me.math.divide(
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[0][1],
- ),
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[0][0],
- ),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
- ratio = me.math.divide(
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[1][1],
- ),
- reviveComplex(
- stateVariables["/Bd"].stateValues.eigenvectors[1][0],
- ),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec1"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec1"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec1a"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec1a"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec2"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec2"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- me
- .fromAst(
- stateVariables["/Bevec2a"].stateValues.displacement[1],
- )
- .evaluate_to_constant(),
- me
- .fromAst(
- stateVariables["/Bevec2a"].stateValues.displacement[0],
- )
- .evaluate_to_constant(),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(-1, 1e-14);
-
- ratio = me.math.divide(
- reviveComplex(stateVariables["/Bevec1y"].stateValues.value),
- reviveComplex(stateVariables["/Bevec1x"].stateValues.value),
- );
- expect(ratio.re).closeTo(0, 1e-14);
- expect(ratio.im).closeTo(1, 1e-14);
- });
- });
-});
-
-function reviveComplex(num) {
- return me.math.complex({ re: num.re, im: num.im });
-}