PDA

View Full Version : matrix implementation in JS


hittman
06-04-2004, 03:41 PM
This is my implementation of an n x m matrix in JS:

var n=parseInt(prompt("n:",1));
var m=parseInt(prompt("m:",1));
function array(){
this.length=m+1;
for (var i=1;i<=m;i++)
this[i]=0;
}
function matrix(){
this.length=n+1;
for (var i=1;i<=n;i++)
this[i]=new array;
}
var a = new matrix();

enjoy it!!!

A1ien51
06-04-2004, 03:44 PM
a 2d array? IMO...not a big deal plus you should not name your function array...

Garadon
06-04-2004, 05:01 PM
This does the same. can make 2d and 3d arrays.

arr=new Array();
Array.prototype.makeMultidimensional=function(){
if(arguments.length<2)return;
this.length=arguments[0];
for(i=0;i<arguments[0];i++)
{
this[i]=new Array();
this[i].length=arguments[1];
for(j=0;j<arguments[1];j++)
{
if(arguments.length>2)
this[i][j]=new Array(arguments[2]);
}
}
}
arr.makeMultidimensional(2,2,4);

Alex Vincent
06-04-2004, 11:00 PM
Where's Trinity? :cool:

(Sorry, I couldn't resist.)

allida77
06-04-2004, 11:19 PM
hehe that is what I thought of when I saw this thread.

hittman
06-05-2004, 01:10 AM
a 2d array? IMO...not a big deal plus you should not name your function array...
Java Script is case sensitive, so array is not the same as Array......, i don't believe that "array" is a reserved word....

hittman
06-05-2004, 01:19 AM
Garadon, just compare the codes (mine has a mistake, i'll award the one that finds it).

Garadon
06-05-2004, 07:55 AM
well you making new array insted of new array() not sure if it breaks on that, your index starts a 1 which mean you have an empty col at 0 and a row at 0.

hittman
06-05-2004, 12:22 PM
new array is the mistake, i forgot to put the paratheses when i changed the name of the function so i should have typed there new array(), and it's easier to work with an array from 1 to n instead of 0 to n-1, but if someone preferes to have his array from 0 to n-1 he should change the for: for (i=0;i<n;i++) etc. and this.length should be n. bla bla bla.....

caldasgsm
06-18-2004, 02:25 AM
the proposed solution in this thread, works well and provides a clean code..
but creating an array of arrays in script can be time consuming.. if you have a 10x10x10 matrix.. it can take its time because ou are creating a 1000 arrays.. and if you have to create 10 the user will notice the delay...

next I present a class that I made that actualy uses just one array.. and manages the dimentions with offsets...
much like, it really happens in assembly...
and suports n dimentions

function CMatrix(nSizes)
{
if(!nSizes)throw new Error('Matrix must have at least one dimention');

//private properties******
this.nDepth = 0;
this.nLength = 1;
this.pDimensions = new Array();
this.pOffsets = new Array();
this.pMatrix = new Array();
this.pStack = new Array();

//public methods******

//returns a array with the size of the dimentions
this.getSizes = function(){return this.pDimensions.concat();}
//returns a CItem Object
this.item = function(nIndexs){this.buildStack(arguments);return this.getElement();}
//returns a CDimention object
this.baseDim = function(nIndex){return new this.CDimension(0,0,nIndex,this);}
//fills all elements of the matrix with the specified value
this.fill = function(value){for(var i = 0; i < this.nLength;i++)this.pMatrix[i] = value;}
//copies the possible values from another CMatrix
this.copyFrom = function(pMatrix){if(!(pMatrix instanceof CMatrix))throw new Error('Copy source is not a CMatrix Object');this.pStack = new Array();this.copy(pMatrix)}
//returns the matrix as an array
this.valueOf = function(){return this.pMatrix};
//returns a string decribing the matrix
this.toString = function(){return 'Dimensions Length:['+this.pDimensions+']\r\nData:|' + this.pMatrix.join('|') + '|';}

//private methods******
//dimension interface object
this.CDimension = function(nBaseOffset,nDimension,nIndex,pMatrix)
{
this.nOffSet = nBaseOffset + (pMatrix.pOffsets[nDimension] * nIndex);
this.pMatrix = pMatrix;
this.nDimension = nDimension;
this.bEndPoint = (nDimension == pMatrix.nDepth -1)
this.nextDim = function(nIndex)
{
if(this.bEndPoint)throw new Error('No more dimentions available');
return new this.pMatrix.CDimension(this.nOffSet,this.nDimension+1,nIndex,this.pMatrix)
}
this.get = function()
{
if(!this.bEndPoint)throw new Error('Not and end-point dimention');
return this.pMatrix[this.nOffSet]
}
this.set = function(newValue)
{
if(!this.bEndPoint)throw new Error('Not and end-point dimention');
this.pMatrix.pMatrix[this.nOffSet] = newValue;
}
}
//builds a interface for the element
this.buildItemInterface = function(nOffset)
{
var oInterface = new Function('newVal','arguments.callee.pMatrix[arguments.callee.nOffset] = newVal;return this;');
oInterface.pMatrix = this.pMatrix;
oInterface.nOffset = nOffset;
oInterface.set = function(newVal){this.pMatrix[this.nOffset] = newVal;return this;}
oInterface.get = function(){return this.pMatrix[this.nOffset];}
oInterface.toString = function(){return new String(this.pMatrix[this.nOffset]);}
oInterface.valueOf = function(){return this.pMatrix[this.nOffset];}
return oInterface;
}
//builds a parameter stack for recursive funtions
this.buildStack = function(oArgs)
{
if(oArgs.length != this.nDepth)throw new Error('Function parameters do not match matrix dimentions')
this.pStack = new Array();
for(var i = 0; i < oArgs.length; i++)
{
if(parseInt(oArgs[i]) >= this.pDimensions[i])throw new Error('Indexs are out on Range')
this.pStack.push(parseInt(oArgs[i]))
}
}
//returns a element interface pointer
this.getElement = function()
{
var nOffset = 0;
for(var i = 0 ; i < this.pStack.length; i++)
nOffset = nOffset + this.pOffsets[i] * this.pStack[i]

return this.buildItemInterface(nOffset);
};
//copy data from another Matrix
this.copy = function(orMatrix)
{
if(this.pStack.length < this.nDepth && this.pStack.length < orMatrix.nDepth)
{
for(var i = 0; i < orMatrix.pDimensions[this.pStack.length] && i < this.pDimensions[this.pStack.length];i++)
{
this.pStack.push(i);
this.copy(orMatrix);
this.pStack.pop()
}
}
else
{
var nOrOffset = 0;
for(var j = 0 ; j < this.pStack.length; j++)
nOrOffset = nOrOffset + orMatrix.pOffsets[j] * this.pStack[j]

var nTrOffset = 0;
for(var j = 0 ; j < this.pStack.length; j++)
nTrOffset = nTrOffset + this.pOffsets[j] * this.pStack[j]

this.pMatrix[nTrOffset] = orMatrix.pMatrix[nOrOffset]
}
}

//constructor*******
if(nSizes instanceof CMatrix)
{
this.nDepth = nSizes.nDepth
this.nLength = nSizes.nLength
this.pDimensions = nSizes.pDimensions.concat();
this.pOffsets = nSizes.pOffsets.concat();
this.pMatrix = new Array(nSizes.pMatrix.length);
this.pStack = new Array();
this.copy(nSizes);
}
else
{
this.nDepth = arguments.length;
for(var i = 0; i < this.nDepth; i++)
{
this.nLength = this.nLength * parseInt(arguments[i])
this.pDimensions.push(parseInt(arguments[i]))
var nOffSet = 1;
for(var j = i+1 ; j < this.nDepth; j++)
nOffSet = nOffSet * parseInt(arguments[j])
this.pOffsets.push(nOffSet);
}
this.pMatrix = new Array(this.nLength);
}
}




the usage is easy.. not so straight forward like a normal array but is not a big deal


EX:
var mat = new CMatrix(10,10,10); //create matrix or
var mat2 = new CMatrix(mat); //pass a existing one in the constructor

mat.fill(0); //fill all with 0 or
mat.copyFrom(mat2)// copies for another matrix

mat.item(2,2,2).set('str') //set a value or
mat.item(2,2,2)('str') //works alsow (implemented for better code style)

var a = mat.item(2,2,2).get() //get a value or
var a = mat.item(2,2,2) //works alsow (because this function returns a Function object that encapsulates the true value)

var a = mat.item(2,2,2).get() + 5 //get a value and increment 5 or
var a = mat.item(2,2,2) - 8 //works alsow


//iterate for all elements

for(var i = 0 ; i < 10; i++)
for(var j = 0 ; j < 10; j++)
for(var k = 0 ; k < 10; k++)
mat.item(i,j,k)(i+'.'+j+'.'+k)

/*but the offset calculation can be time consuming if the matrix as many
dimentions so there is a alternate way to get the item wich is by accessing
a dimentions at a time, thus caching the offset... like this*/

for(var i = 0 ; i < 10; i++)
{
var dim1 = mat.baseDim(i); //get base dimention
for(var j = 0 ; j < 10; j++)
{
var dim2 = dim1.nextDim(j) // get the next
for(var k = 0 ; k < 10; k++)
{
dim2.nextDim(k).set(i+'.'+j+'.'+k)
}
}
}
/*but it is not necessary to use this unless you have a big array and a
intense processing*/


have fun