Created
September 7, 2010 12:24
-
-
Save bga/568247 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Goal of this test is find best data structure for store matrices, vectors and quaternions | |
In C/C++ we have ability to store same data different ways ie | |
union | |
{ | |
float m[9]; | |
struct | |
{ | |
float | |
m00, m01, m02 | |
, m10, m11, m12 | |
, m20, m21, m22 | |
; | |
}; | |
} | |
In javascipt we have only or array or hash. | |
Also this test try to use typed array and have 2 version of matrices multiply algorithm(with or w/o caching data from structure) | |
*/ | |
var $G = this; | |
var Mat33Hash = function( | |
m00, m01, m02 | |
, m10, m11, m12 | |
, m20, m21, m22 | |
) | |
{ | |
this.m00 = m00; this.m01 = m01; this.m02 = m02; | |
this.m10 = m10; this.m11 = m11; this.m12 = m12; | |
this.m20 = m20; this.m21 = m21; this.m22 = m22; | |
}; | |
Mat33Hash.prototype._identity = function() | |
{ | |
this.m00 = 1; this.m01 = 0; this.m02 = 0; | |
this.m10 = 0; this.m11 = 1; this.m12 = 0; | |
this.m20 = 0; this.m21 = 0; this.m22 = 1; | |
}; | |
Mat33Hash.prototype._mul = function(m) | |
{ | |
return new Mat33Hash( | |
this.m00*m.m00 + this.m01*m.m10 + this.m02*m.m20 | |
, this.m00*m.m01 + this.m01*m.m11 + this.m02*m.m21 | |
, this.m00*m.m02 + this.m01*m.m12 + this.m02*m.m22 | |
, this.m10*m.m00 + this.m11*m.m10 + this.m12*m.m20 | |
, this.m10*m.m01 + this.m11*m.m11 + this.m12*m.m21 | |
, this.m10*m.m02 + this.m11*m.m12 + this.m12*m.m22 | |
, this.m20*m.m00 + this.m21*m.m10 + this.m22*m.m20 | |
, this.m20*m.m01 + this.m21*m.m11 + this.m22*m.m21 | |
, this.m20*m.m02 + this.m21*m.m12 + this.m22*m.m22 | |
); | |
}; | |
Mat33Hash.prototype._mulCache = function(m) | |
{ | |
var | |
tm00 = this.m00, tm01 = this.m01, tm02 = this.m02 | |
, tm10 = this.m10, tm11 = this.m11, tm12 = this.m12 | |
, tm20 = this.m20, tm21 = this.m21, tm22 = this.m22 | |
, mm00 = m.m00, mm01 = m.m01, mm02 = m.m02 | |
, mm10 = m.m10, mm11 = m.m11, mm12 = m.m12 | |
, mm20 = m.m20, mm21 = m.m21, mm22 = m.m22 | |
; | |
return new Mat33Hash( | |
tm00*mm00 + tm01*mm10 + tm02*mm20 | |
, tm00*mm01 + tm01*mm11 + tm02*mm21 | |
, tm00*mm02 + tm01*mm12 + tm02*mm22 | |
, tm10*mm00 + tm11*mm10 + tm12*mm20 | |
, tm10*mm01 + tm11*mm11 + tm12*mm21 | |
, tm10*mm02 + tm11*mm12 + tm12*mm22 | |
, tm20*mm00 + tm21*mm10 + tm22*mm20 | |
, tm20*mm01 + tm21*mm11 + tm22*mm21 | |
, tm20*mm02 + tm21*mm12 + tm22*mm22 | |
); | |
}; | |
var Mat33Array = function(m) | |
{ | |
this.m = m || new Array(9); | |
}; | |
Mat33Array.prototype._identity = function() | |
{ | |
this.m = | |
[ | |
1, 0, 0 | |
, 0, 1, 0 | |
, 0, 0, 1 | |
]; | |
}; | |
Mat33Array.prototype._mul = function(a) | |
{ | |
var t = this.m, m = a.m; | |
return new Mat33Array( | |
[ | |
t[0]*m[0] + t[1]*m[3] + t[2]*m[6] | |
, t[0]*m[1] + t[1]*m[4] + t[2]*m[7] | |
, t[0]*m[2] + t[1]*m[5] + t[2]*m[8] | |
, t[3]*m[0] + t[4]*m[3] + t[5]*m[6] | |
, t[3]*m[1] + t[4]*m[4] + t[5]*m[7] | |
, t[3]*m[2] + t[4]*m[5] + t[5]*m[8] | |
, t[6]*m[0] + t[7]*m[3] + t[8]*m[6] | |
, t[6]*m[1] + t[7]*m[4] + t[8]*m[7] | |
, t[6]*m[2] + t[7]*m[5] + t[8]*m[8] | |
] | |
); | |
}; | |
Mat33Array.prototype._mulCache = function(a) | |
{ | |
var t = this.m, m = a.m; | |
var | |
t0 = t[0], t1 = t[1], t2 = t[2] | |
, t3 = t[3], t4 = t[4], t5 = t[5] | |
, t6 = t[6], t7 = t[7], t8 = t[8] | |
, m0 = m[0], m1 = m[1], m2 = m[2] | |
, m3 = m[3], m4 = m[4], m5 = m[5] | |
, m6 = m[6], m7 = m[7], m8 = m[8] | |
; | |
return new Mat33Array( | |
[ | |
t0*m0 + t1*m3 + t2*m6 | |
, t0*m1 + t1*m4 + t2*m7 | |
, t0*m2 + t1*m5 + t2*m8 | |
, t3*m0 + t4*m3 + t5*m6 | |
, t3*m1 + t4*m4 + t5*m7 | |
, t3*m2 + t4*m5 + t5*m8 | |
, t6*m0 + t7*m3 + t8*m6 | |
, t6*m1 + t7*m4 + t8*m7 | |
, t6*m2 + t7*m5 + t8*m8 | |
] | |
); | |
}; | |
var F32Array = $G.Float32Array || $G.WebGLFloatArray || $G.CanvasFloatArray || Array; | |
var Mat33TypedArray = function(m) | |
{ | |
this.m = m || new F32Array(9); | |
}; | |
Mat33TypedArray.prototype._identity = function() | |
{ | |
this.m = new F32Array( | |
[ | |
1, 0, 0 | |
, 0, 1, 0 | |
, 0, 0, 1 | |
]); | |
}; | |
Mat33TypedArray.prototype._mul = function(a) | |
{ | |
var t = this.m, m = a.m; | |
return new Mat33TypedArray( | |
new F32Array([ | |
t[0]*m[0] + t[1]*m[3] + t[2]*m[6] | |
, t[0]*m[1] + t[1]*m[4] + t[2]*m[7] | |
, t[0]*m[2] + t[1]*m[5] + t[2]*m[8] | |
, t[3]*m[0] + t[4]*m[3] + t[5]*m[6] | |
, t[3]*m[1] + t[4]*m[4] + t[5]*m[7] | |
, t[3]*m[2] + t[4]*m[5] + t[5]*m[8] | |
, t[6]*m[0] + t[7]*m[3] + t[8]*m[6] | |
, t[6]*m[1] + t[7]*m[4] + t[8]*m[7] | |
, t[6]*m[2] + t[7]*m[5] + t[8]*m[8] | |
]) | |
); | |
}; | |
Mat33TypedArray.prototype._mulCache = function(a) | |
{ | |
var t = this.m, m = a.m; | |
var | |
t0 = t[0], t1 = t[1], t2 = t[2] | |
, t3 = t[3], t4 = t[4], t5 = t[5] | |
, t6 = t[6], t7 = t[7], t8 = t[8] | |
, m0 = m[0], m1 = m[1], m2 = m[2] | |
, m3 = m[3], m4 = m[4], m5 = m[5] | |
, m6 = m[6], m7 = m[7], m8 = m[8] | |
; | |
return new Mat33TypedArray( | |
new F32Array([ | |
t0*m0 + t1*m3 + t2*m6 | |
, t0*m1 + t1*m4 + t2*m7 | |
, t0*m2 + t1*m5 + t2*m8 | |
, t3*m0 + t4*m3 + t5*m6 | |
, t3*m1 + t4*m4 + t5*m7 | |
, t3*m2 + t4*m5 + t5*m8 | |
, t6*m0 + t7*m3 + t8*m6 | |
, t6*m1 + t7*m4 + t8*m7 | |
, t6*m2 + t7*m5 + t8*m8 | |
]) | |
); | |
}; | |
var Mat33TypedArray2 = function(m) | |
{ | |
this.m = m || new F32Array(9); | |
}; | |
Mat33TypedArray2.prototype._identity = function() | |
{ | |
this.m = new F32Array( | |
[ | |
1, 0, 0 | |
, 0, 1, 0 | |
, 0, 0, 1 | |
]); | |
}; | |
Mat33TypedArray2.prototype._mul = function(a) | |
{ | |
var t = this.m, m = a.m; | |
var s = new F32Array(9); | |
s[0] = t[0]*m[0] + t[1]*m[3] + t[2]*m[6]; | |
s[1] = t[0]*m[1] + t[1]*m[4] + t[2]*m[7]; | |
s[2] = t[0]*m[2] + t[1]*m[5] + t[2]*m[8]; | |
s[3] = t[3]*m[0] + t[4]*m[3] + t[5]*m[6]; | |
s[4] = t[3]*m[1] + t[4]*m[4] + t[5]*m[7]; | |
s[5] = t[3]*m[2] + t[4]*m[5] + t[5]*m[8]; | |
s[6] = t[6]*m[0] + t[7]*m[3] + t[8]*m[6]; | |
s[7] = t[6]*m[1] + t[7]*m[4] + t[8]*m[7]; | |
s[8] = t[6]*m[2] + t[7]*m[5] + t[8]*m[8]; | |
return new Mat33TypedArray2(s); | |
}; | |
Mat33TypedArray2.prototype._mulCache = function(a) | |
{ | |
var t = this.m, m = a.m; | |
var | |
t0 = t[0], t1 = t[1], t2 = t[2] | |
, t3 = t[3], t4 = t[4], t5 = t[5] | |
, t6 = t[6], t7 = t[7], t8 = t[8] | |
, m0 = m[0], m1 = m[1], m2 = m[2] | |
, m3 = m[3], m4 = m[4], m5 = m[5] | |
, m6 = m[6], m7 = m[7], m8 = m[8] | |
; | |
var s = new F32Array(9); | |
s[0] = t0*m0 + t1*m3 + t2*m6 | |
s[1] = t0*m1 + t1*m4 + t2*m7 | |
s[2] = t0*m2 + t1*m5 + t2*m8 | |
s[3] = t3*m0 + t4*m3 + t5*m6 | |
s[4] = t3*m1 + t4*m4 + t5*m7 | |
s[5] = t3*m2 + t4*m5 + t5*m8 | |
s[6] = t6*m0 + t7*m3 + t8*m6 | |
s[7] = t6*m1 + t7*m4 + t8*m7 | |
s[8] = t6*m2 + t7*m5 + t8*m8 | |
return new Mat33TypedArray2(s); | |
}; | |
var _fTest = function(Class) | |
{ | |
return function(n) | |
{ | |
var a = new Class(); | |
a._identity(); | |
var i = n; while(i--) | |
{ | |
a = a._mul(a); | |
} | |
}; | |
}; | |
var _fTestCache = function(Class) | |
{ | |
return function(n) | |
{ | |
var a = new Class(); | |
a._identity(); | |
var i = n; while(i--) | |
{ | |
a = a._mulCache(a); | |
} | |
}; | |
}; | |
var tests = | |
[ | |
_fTest(Mat33Hash) // 0 | |
, _fTestCache(Mat33Hash) // 1 | |
, _fTest(Mat33Array) // 2 | |
, _fTestCache(Mat33Array) //3 | |
]; | |
if(F32Array !== Array) | |
{ | |
tests.push( | |
_fTest(Mat33TypedArray) // 4 | |
, _fTestCache(Mat33TypedArray) // 5 | |
, _fTest(Mat33TypedArray2) // 6 | |
, _fTestCache(Mat33TypedArray2) // 7 | |
); | |
} | |
_speedTest( | |
tests | |
, 200000 | |
); | |
/* | |
ie7 200000/10 | |
0: 1592 ms | |
1: 922 ms | |
2: 1592 ms | |
3: 921 ms | |
chrome7 200000 | |
0: 542 ms | |
1: 204 ms | |
2: 719 ms | |
3: 312 ms | |
4: 4502 ms | |
5: 4007 ms | |
6: 3249 ms | |
7: 2992 ms | |
opera10.60 200000 | |
0: 328 ms | |
1: 212 ms | |
2: 471 ms | |
3: 350 ms | |
ff3.6 200000/5 | |
0: 3483 ms | |
1: 1553 ms | |
2: 3909 ms | |
3: 1836 ms | |
ff4b3 200000 | |
0: 1446 ms | |
1: 712 ms | |
2: 1227 ms | |
3: 563 ms | |
4: 1206 ms | |
5: 1401 ms | |
6: 669 ms | |
7: 910 ms | |
*/ | |
/* | |
As we can see hash currently is best solution. With caching. In future may be Mat33TypedArray2 will be best(see ff4b3). | |
Thanks to http://code.google.com/p/glmatrix/ for idea, but it uses slow solution :) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment