Published
Edited
Mar 5, 2018
Importers
1 star
Insert cell
Insert cell
class Matrix {
constructor(dims, fill = 0){
this.nrow = dims[0];
this.ncol = dims[1];
this.size = this.nrow*this.ncol;
const vec_fill = fill.length > 1;
if(vec_fill && (fill.length !== this.nrow*this.ncol)){
throw(`Expecting a fill vector of length ${this.size} but got a vector of length ${fill.length}`)
};
this.vals = Float32Array.from(
vec_fill ?
fill:
[...(new Array(this.nrow*this.ncol))].map(d => fill)
);
}
// internal helper function for finding position in 2d array
mat_pos(i,j){
return (this.ncol)*i + j
}
// given a row and col fill the place with a value, if inplace = false then
// returns a new matrix object with the given location filled.
set(i,j, val, inplace = true){
if(inplace){
this.vals[this.mat_pos(i,j)] = val
} else {
const newMat = new Matrix([this.nrow, this.ncol], [...this.vals]);
newMat.set(i,j, val);
return newMat
}
}
// returns a value at a given location
get(i,j){
return this.vals[this.mat_pos(i,j)]
}
// gives back a given row
row(i){
const row_res = new Float32Array(this.ncol);
for(let j=0; j<this.ncol; j++) row_res[j] = this.get(i,j);
return row_res;
}
// ...and a given column
col(j){
const col_res = new Float32Array(this.nrow);
for(let i=0; i<this.nrow; i++) col_res[i] = this.get(i,j);
return col_res;
}
// pretty print in a 2d array
pprint(){
return [...(new Array(this.nrow))].map(
(_,i) => [...(new Array(this.ncol))].map(
(_,j) => this.get(i,j) ))
}
}
Insert cell
Insert cell
new Matrix([2,3]).pprint()
Insert cell
Insert cell
// simplest possible
new Matrix([3,2]).pprint()
Insert cell
// constant fill
new Matrix([3,2], 5).pprint()
Insert cell
// vector fill
new Matrix([3,2], [1,2,3,4,5,6]).pprint()
Insert cell
// bad vector fill
new Matrix([4,2], [1,2,3,4,5,6,7])
Insert cell
Insert cell
// this starts as all zeros
test_mat = new Matrix([3,3])
Insert cell
// but has been mutated by the cell below so it now has a 5 and 6 in it.
test_mat.pprint()
Insert cell
// inplace mutation
{
test_mat.set(1,1,5)
test_mat.set(1,2,6)
}
Insert cell
// now immutable. If it was mutating the first object the element in the 1,2 position of test_mat would be 5
test_mat.set(1,2,5,false).pprint()
Insert cell
// checking to see it test_mat was mutated and it wasnt.
test_mat.pprint()
Insert cell
Insert cell
test_mat.get(1,2)
Insert cell
test_mat.get(1,1)
Insert cell
Insert cell
test_mat.row(1)
Insert cell
test_mat.col(2)
Insert cell
Insert cell
// take the dot product of two matrices
dot_prod = (vec_a, vec_b) => vec_a.reduce((sum, d, i) => sum + d*vec_b[i], 0)
Insert cell
// from arbitrary vectors
dot_prod([1,2,3], [4,5,6])
Insert cell
// taking rows and columns from a matrix
dot_prod(test_mat.row(1), test_mat.col(2))
Insert cell
Insert cell
Insert cell
mat = new Matrix([2,4], [1,2,3,4,5,6,7,8])
Insert cell
Insert cell
transpose(mat).pprint()
Insert cell
Insert cell
Insert cell
// with no fill set goes to the identity matrix
diag_mat(3).pprint()
Insert cell
// with a constant fill
diag_mat(3, 5).pprint()
Insert cell
// with a vector fill
diag_mat(5, [1,2,3,4,5]).pprint()
Insert cell
// with a bad vector fill
diag_mat(5, [1,2,3,4])
Insert cell
Insert cell
function mat_mult(mat_a, mat_b){
if(mat_a.ncol !== mat_b.nrow) throw("Make sure your inner dimensions match for multiplication");
const mat_res = new Matrix([mat_a.nrow, mat_b.ncol]);
for(let i=0; i<mat_a.nrow; i++){
for(let j=0; j<mat_b.ncol; j++){
mat_res.set(i,j, dot_prod(mat_a.row(i), mat_b.col(j)));
}
}
return mat_res
}
Insert cell
mat_a = new Matrix([3,2], [3,5,6,1,5,6])
Insert cell
mat_b = new Matrix([2,5], [4,5,2,5,6,7,2,4,6,7])
Insert cell
// standard
mat_mult(mat_a, mat_b).pprint()
Insert cell
// Make sure your inner dimensions match!
mat_mult(mat_b, mat_a)
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more