-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatrix.html
More file actions
359 lines (338 loc) · 21.9 KB
/
Copy pathmatrix.html
File metadata and controls
359 lines (338 loc) · 21.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Matrix Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="math.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body class="bg-gray-800 text-gray-300 font-sans">
<div class="container mx-auto p-4">
<div class="text-center mb-4">
<a href="index.html" class="text-blue-400 hover:text-blue-300">← Back to home</a>
</div>
<h1 class="text-3xl font-bold text-center mb-8 text-white">Matrix Calculator</h1>
<div class="grid grid-cols-1 md:grid-cols-12 gap-8">
<!-- Left Menu Placeholder -->
<div class="md:col-span-3">
<h2 class="text-xl font-semibold mb-4 text-white">Operations</h2>
<ul class="space-y-2">
<li><a href="#" class="hover:text-white">Matrix Operations ✓</a></li>
</ul>
</div>
<!-- Main Content -->
<div class="md:col-span-9 grid grid-cols-1 xl:grid-cols-11 gap-4">
<!-- Matrix A -->
<div class="xl:col-span-5 bg-gray-700 p-4 rounded-lg">
<h2 class="text-xl font-semibold mb-4 text-center text-white">Matrix A</h2>
<div class="flex justify-center items-center">
<div class="matrix-container">
<div id="matrix-input-A" class="grid gap-2 justify-center"></div>
</div>
</div>
<div class="flex justify-center items-center flex-wrap gap-4 mt-4">
<span>Cells</span>
<input type="number" id="rowsA" value="3" min="1" class="w-16 p-1 bg-gray-800 border border-gray-600 rounded text-center">
<input type="number" id="colsA" value="3" min="1" class="w-16 p-1 bg-gray-800 border border-gray-600 rounded text-center">
</div>
<div id="unary-operations" class="grid grid-cols-2 gap-2 mt-4">
<button data-action="det" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">Determinant</button>
<button data-action="inv" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">Inverse Matrix</button>
<button data-action="transpose" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">Transpose Matrix</button>
<div class="flex">
<button data-action="scalar-mult" class="flex-grow px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded-l hover:bg-gray-700">Multiply by</button>
<input type="number" id="scalar-mult-value" value="2" class="w-12 p-1 bg-gray-800 border border-gray-600 rounded-r text-center">
</div>
<button data-action="triangular" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">Triangular Matrix</button>
<button data-action="diag" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">Diagonalization</button>
<div class="flex">
<button data-action="power" class="flex-grow px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded-l hover:bg-gray-700">Raise to the power</button>
<input type="number" id="power-value" value="5" class="w-12 p-1 bg-gray-800 border border-gray-600 rounded-r text-center">
</div>
<button data-action="lu" class="px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">LU Decomposition</button>
</div>
</div>
<!-- Operation Buttons -->
<div id="matrix-action-buttons" class="xl:col-span-1 flex flex-col items-center justify-center gap-4">
<button data-action="multiply" class="w-20 px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">A × B</button>
<button data-action="add" class="w-20 px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">A + B</button>
<button data-action="subtract" class="w-20 px-4 py-2 bg-gray-900 text-white border border-gray-600 rounded hover:bg-gray-700">A - B</button>
</div>
<!-- Matrix B -->
<div class="xl:col-span-5 bg-gray-700 p-4 rounded-lg">
<h2 class="text-xl font-semibold mb-4 text-center text-white">Matrix B</h2>
<div class="flex justify-center items-center">
<div class="matrix-container">
<div id="matrix-input-B" class="grid gap-2 justify-center"></div>
</div>
</div>
<div class="flex justify-center items-center gap-4 mt-4">
<span>Cells</span>
<input type="number" id="rowsB" value="3" min="1" class="w-16 p-1 bg-gray-800 border border-gray-600 rounded text-center">
<input type="number" id="colsB" value="3" min="1" class="w-16 p-1 bg-gray-800 border border-gray-600 rounded text-center">
</div>
</div>
</div>
</div>
<!-- Result Zone -->
<div id="result-zone" class="bg-gray-700 p-6 border-t border-gray-600 mt-8 rounded-lg">
<h2 class="text-xl font-semibold mb-4 text-white">Details</h2>
<div id="demonstration-output" class="text-lg font-mono mb-6 text-gray-300 overflow-x-auto"></div>
<h2 class="text-xl font-semibold mb-4 text-white">Result</h2>
<div id="result-output" class="text-2xl font-mono text-center text-white"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const rowsA_input = document.getElementById('rowsA');
const colsA_input = document.getElementById('colsA');
const rowsB_input = document.getElementById('rowsB');
const colsB_input = document.getElementById('colsB');
const matrixA_container = document.getElementById('matrix-input-A');
const matrixB_container = document.getElementById('matrix-input-B');
const matrixActionButtons = document.getElementById('matrix-action-buttons');
const unaryOperations = document.getElementById('unary-operations');
const resultOutput = document.getElementById('result-output');
const demonstrationOutput = document.getElementById('demonstration-output');
function generateSpecificMatrix(matrixName, rows, cols, container) {
container.innerHTML = '';
container.style.gridTemplateColumns = `repeat(${cols}, 50px)`;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
const input = document.createElement('input');
input.type = 'text';
input.className = 'w-12 h-12 p-1 bg-gray-800 border border-gray-600 rounded text-center text-white';
input.setAttribute('data-matrix', matrixName);
input.setAttribute('data-row', i);
input.setAttribute('data-col', j);
input.value = Math.floor(Math.random() * 10);
container.appendChild(input);
}
}
}
function getMatrix(matrixName, rows, cols, container) {
const matrix = [];
for (let i = 0; i < rows; i++) {
const row = [];
for (let j = 0; j < cols; j++) {
const input = container.querySelector(`[data-row='${i}'][data-col='${j}']`);
const value = parseFloat(input.value) || 0;
row.push(value);
}
matrix.push(row);
}
return math.matrix(matrix);
}
function formatMatrix(matrix) {
let arr = matrix.toArray();
let table = '<table class="inline-block align-middle">';
for(let i=0; i < arr.length; i++) {
table += '<tr>';
for(let j=0; j < arr[i].length; j++) {
table += `<td class="px-2 py-1 text-center">${math.format(arr[i][j], {precision: 4})}</td>`;
}
table += '</tr>';
}
table += '</table>';
return `<div class="result-matrix">${table}</div>`;
}
function showDemonstration(op, matrixA, matrixB = null, result = null, scalar = null) {
let demo = '';
const a = matrixA.toArray();
if (op === 'det') {
const size = matrixA.size();
if (size[0] === 2 && size[1] === 2) {
demo = `det(A) = (a * d) - (b * c)<br/>`;
demo += `det(A) = (${a[0][0]} * ${a[1][1]}) - (${a[0][1]} * ${a[1][0]})`;
} else if (size[0] === 3 && size[1] === 3) {
demo = `Sarrus' rule:<br/>`;
demo += `det(A) = (a(ei - fh) - b(di - fg) + c(dh - eg))<br/><br/>`;
demo += `Term 1: ${a[0][0]} * ((${a[1][1]} * ${a[2][2]}) - (${a[1][2]} * ${a[2][1]})) = ${a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1])}<br/>`;
demo += `Term 2: -${a[0][1]} * ((${a[1][0]} * ${a[2][2]}) - (${a[1][2]} * ${a[2][0]})) = ${-a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0])}<br/>`;
demo += `Term 3: ${a[0][2]} * ((${a[1][0]} * ${a[2][1]}) - (${a[1][1]} * ${a[2][0]})) = ${a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0])}<br/>`;
} else {
demo = "The determinant demonstration is only displayed for 2x2 and 3x3 matrices.";
}
} else if (op === '+' || op === '-') {
const b = matrixB.toArray();
for(let i=0; i<a.length; i++) {
for(let j=0; j<a[0].length; j++) {
demo += `C<sub>${i+1},${j+1}</sub> = A<sub>${i+1},${j+1}</sub> ${op} B<sub>${i+1},${j+1}</sub> = ${a[i][j]} ${op} ${b[i][j]} = ${op === '+' ? a[i][j]+b[i][j] : a[i][j]-b[i][j]}<br/>`;
}
}
} else if (op === '*') {
const b = matrixB.toArray();
demo = 'Matrix product: rows of the first matrix are multiplied by columns of the second matrix.<br/><br/>';
for (let i = 0; i < a.length; i++) {
for (let j = 0; j < b[0].length; j++) {
let sum = 0;
let formula = `C<sub>${i+1},${j+1}</sub> = `;
let values = ` = `;
for (let k = 0; k < a[0].length; k++) {
sum += a[i][k] * b[k][j];
formula += `A<sub>${i+1},${k+1}</sub>×B<sub>${k+1},${j+1}</sub> ${k < a[0].length - 1 ? '+ ' : ''}`;
values += `${a[i][k]}×${b[k][j]} ${k < a[0].length - 1 ? '+ ' : ''}`;
}
demo += `<div>${formula}${values} = ${sum}</div>`;
}
}
} else if (op === 'inv') {
demo = "The inverse of a matrix A is A<sup>-1</sup>. It is calculated as follows:<br/>";
demo += "A<sup>-1</sup> = (1/det(A)) * adj(A)<br/>";
demo += "Where det(A) is the determinant of A and adj(A) is the adjugate of A (the transpose of the cofactor matrix).";
} else if (op === 'transpose') {
demo = "The transpose of a matrix is obtained by swapping its rows and columns.<br/>";
demo += "(A<sup>T</sup>)<sub>ij</sub> = A<sub>ji</sub>";
} else if (op === 'rank') {
demo = "The rank of a matrix is the number of linearly independent rows or columns. It is the dimension of the vector space spanned by its columns (or rows).";
} else if (op === 'scalar-mult') {
demo = `Each element of the matrix is multiplied by the scalar ${scalar}.<br/>`;
demo += `(k * A)<sub>ij</sub> = k * A<sub>ij</sub><br/>`;
const res = result.toArray();
for(let i=0; i<a.length; i++) {
if (i > 2) {
demo += '... etc.<br/>';
break;
}
for(let j=0; j<a[0].length; j++) {
demo += `(${scalar} * ${a[i][j]}) = ${res[i][j]}<br/>`;
if (j > 2) {
demo += '... etc.<br/>';
break;
}
}
}
} else if (op === 'triangular' || op === 'lu') {
demo = "The LU decomposition factors a matrix into the product of a lower triangular matrix (L) and an upper triangular matrix (U).<br/> A = LU";
} else if (op === 'diag') {
demo = "A diagonal matrix is a matrix where the entries outside the main diagonal are all zero.";
} else if (op === 'power') {
demo = `The matrix is multiplied by itself ${scalar} times.<br/>A<sup>${scalar}</sup> = A * A * ... * A`;
} else if (op === 'cholesky') {
demo = "The Cholesky factorization is a decomposition of a symmetric, positive-definite matrix into the product of a lower triangular matrix (L) and its transpose (L<sup>T</sup>).<br/> A = LL<sup>T</sup>";
}
demonstrationOutput.innerHTML = `<div>${demo}</div>`;
}
rowsA_input.addEventListener('change', () => generateSpecificMatrix('A', parseInt(rowsA_input.value), parseInt(colsA_input.value), matrixA_container));
colsA_input.addEventListener('change', () => generateSpecificMatrix('A', parseInt(rowsA_input.value), parseInt(colsA_input.value), matrixA_container));
rowsB_input.addEventListener('change', () => generateSpecificMatrix('B', parseInt(rowsB_input.value), parseInt(colsB_input.value), matrixB_container));
colsB_input.addEventListener('change', () => generateSpecificMatrix('B', parseInt(rowsB_input.value), parseInt(colsB_input.value), matrixB_container));
matrixActionButtons.addEventListener('click', (e) => {
if (e.target.tagName !== 'BUTTON') return;
const action = e.target.dataset.action;
const matrixA = getMatrix('A', parseInt(rowsA_input.value), parseInt(colsA_input.value), matrixA_container);
const matrixB = getMatrix('B', parseInt(rowsB_input.value), parseInt(colsB_input.value), matrixB_container);
let result;
resultOutput.innerHTML = '';
demonstrationOutput.innerHTML = '';
try {
let opSymbol = '';
switch (action) {
case 'add': result = math.add(matrixA, matrixB); opSymbol = '+'; break;
case 'subtract': result = math.subtract(matrixA, matrixB); opSymbol = '-'; break;
case 'multiply': result = math.multiply(matrixA, matrixB); opSymbol = '×'; break;
}
showDemonstration(action === 'multiply' ? '*' : opSymbol, matrixA, matrixB);
resultOutput.innerHTML = `${formatMatrix(matrixA)} <span class="op-symbol">${opSymbol}</span> ${formatMatrix(matrixB)} <span class="op-symbol">=</span> ${formatMatrix(result)}`;
} catch (error) {
resultOutput.innerHTML = `<span class="text-red-400">${error.message}</span>`;
}
});
unaryOperations.addEventListener('click', (e) => {
if (e.target.tagName !== 'BUTTON') return;
const action = e.target.dataset.action;
const matrixA = getMatrix('A', parseInt(rowsA_input.value), parseInt(colsA_input.value), matrixA_container);
let result;
resultOutput.innerHTML = '';
demonstrationOutput.innerHTML = '';
try {
switch(action) {
case 'det':
{
const size = matrixA.size();
if(size[0] !== size[1]) {
resultOutput.innerHTML = `<span class="text-red-400">The determinant can only be calculated for a square matrix.</span>`;
return;
}
result = math.det(matrixA);
showDemonstration('det', matrixA);
resultOutput.innerHTML = `det(A) = <span class="font-bold text-xl">${result}</span>`;
}
break;
case 'inv':
result = math.inv(matrixA);
showDemonstration('inv', matrixA);
resultOutput.innerHTML = `inv(A) = ${formatMatrix(result)}`;
break;
case 'transpose':
result = math.transpose(matrixA);
showDemonstration('transpose', matrixA);
resultOutput.innerHTML = `transpose(A) = ${formatMatrix(result)}`;
break;
case 'rank':
resultOutput.innerHTML = `<span class="text-red-400">Rank function not available.</span>`;
break;
case 'scalar-mult':
{
const scalar = parseFloat(document.getElementById('scalar-mult-value').value);
result = math.multiply(matrixA, scalar);
showDemonstration('scalar-mult', matrixA, null, result, scalar);
resultOutput.innerHTML = `${scalar} * A = ${formatMatrix(result)}`;
}
break;
case 'triangular':
{
const lup = math.lup(matrixA);
const L = lup.L;
const U = lup.U;
showDemonstration('triangular', matrixA);
// P matrix is also available if needed: const P = lup.P
resultOutput.innerHTML = `Lower Triangular Matrix (L): ${formatMatrix(L)} <br/><br/> Upper Triangular Matrix (U): ${formatMatrix(U)}`;
}
break;
case 'diag':
result = math.diag(math.diag(matrixA));
showDemonstration('diag', matrixA);
resultOutput.innerHTML = `diag(A) = ${formatMatrix(result)}`;
break;
case 'power':
{
const power = parseInt(document.getElementById('power-value').value);
result = math.pow(matrixA, power);
showDemonstration('power', matrixA, null, result, power);
resultOutput.innerHTML = `A^${power} = ${formatMatrix(result)}`;
}
break;
case 'lu':
{
const lup = math.lup(matrixA);
const L = lup.L;
const U = lup.U;
showDemonstration('lu', matrixA);
resultOutput.innerHTML = `LU Decomposition: <br/>L = ${formatMatrix(L)} <br/>U = ${formatMatrix(U)}`;
}
break;
case 'cholesky':
{
try {
result = math.cholesky(matrixA);
showDemonstration('cholesky', matrixA);
resultOutput.innerHTML = `Cholesky factorization (L): ${formatMatrix(result)} where A = L * L<sup>T</sup>`;
} catch (error) {
resultOutput.innerHTML = `<span class="text-red-400">Cholesky factorization requires a symmetric and positive-definite matrix.</span>`;
}
}
break;
}
} catch (error) {
resultOutput.innerHTML = `<span class="text-red-400">${error.message}</span>`;
}
});
generateSpecificMatrix('A', parseInt(rowsA_input.value), parseInt(colsA_input.value), matrixA_container);
generateSpecificMatrix('B', parseInt(rowsB_input.value), parseInt(colsB_input.value), matrixB_container);
});
</script>
</body>
</html>