/**
* Copyright imo_ ( http://wonderfl.net/user/imo_ )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/fegi
*/
package {
import flash.text.TextFormat;
import flash.text.TextField;
import flash.display.Sprite;
import com.bit101.components.*;
public class GenInvMat extends Sprite {
private var ta:TextArea;
public function GenInvMat() {
Style.embedFonts = false;
Style.fontName = "Courier New";
Style.fontSize = 12;
ta = new TextArea(this, 0, 0, "");
ta.editable = false;
ta.width = 465;
ta.height = 465;
calc();
}
private function join(...nums:Array):String {
var len:int = nums.length;
var txt:String = "| ";
for (var i:int = 0; i < len; i++) {
if (i != 0) txt += " ";
txt += Number(nums[i]).toFixed(4);
}
txt += " |";
return txt;
}
private function log(txt:Object):void {
if (txt is Mat) {
var m:Mat = Mat(txt);
log(join(m.e00, m.e01, m.e02, m.e03));
log(join(m.e10, m.e11, m.e12, m.e13));
log(join(m.e20, m.e21, m.e22, m.e23));
log(join(m.e30, m.e31, m.e32, m.e33));
return;
}
ta.text += txt + "\n";
}
private function calc():void {
log("General Inverse Matrix Calculation Test");
log("");
var mat:Mat = new Mat(); // a matrix whose det = 0
mat.e00 = 2; mat.e01 = 1; mat.e02 = 1; mat.e03 = 0;
mat.e10 = 1; mat.e11 = 2; mat.e12 = 0; mat.e13 = 1;
mat.e20 = 1; mat.e21 = 0; mat.e22 = 2; mat.e23 = 1;
mat.e30 = 0; mat.e31 = 1; mat.e32 = 1; mat.e33 = 2;
var invMat:Mat = calcMain(mat);
var tmp:Mat = new Mat();
log("M: ");
log(mat);
log("");
log("M+: ");
log(invMat);
log("");
log("MM+ (= (MM+)*): ");
tmp.mul(mat, invMat);
log(tmp);
log("");
log("M+M (= (M+M)*): ");
tmp.mul(invMat, mat);
log(tmp);
log("");
log("MM+M (= M): ");
tmp.mul(mat, invMat);
tmp.mul(tmp, mat);
log(tmp);
log("");
log("M+MM+ (= M+): ");
tmp.mul(invMat, mat);
tmp.mul(tmp, invMat);
log(tmp);
log("");
}
private function calcMain(m:Mat):Mat {
log("calculating...");
var inv:Mat = new Mat();
step1(m, inv);
step2(m, inv);
step3(m, inv);
step4(m, inv);
log("done.");
log("");
return inv;
}
private function step1(m:Mat, inv:Mat):void {
log(" step 1:");
// calc A1+
var len:Number = m.e00 * m.e00 + m.e10 * m.e10 + m.e20 * m.e20 + m.e30 * m.e30;
if (len > 1e-10) len = 1 / len;
inv.e00 = m.e00 * len;
inv.e01 = m.e10 * len;
inv.e02 = m.e20 * len;
inv.e03 = m.e30 * len;
log(" A1+: " + join(inv.e00, inv.e01, inv.e02, inv.e03));
}
private function step2(m:Mat, inv:Mat):void {
log(" step 2:");
// calc d2
var d0:Number = inv.e00 * m.e01 + inv.e01 * m.e11 + inv.e02 * m.e21 + inv.e03 * m.e31;
log(" d2: " + join(d0));
// calc c2
var c0:Number = m.e01 - m.e00 * d0;
var c1:Number = m.e11 - m.e10 * d0;
var c2:Number = m.e21 - m.e20 * d0;
var c3:Number = m.e31 - m.e30 * d0;
log(" c2: " + join(c0, c1, c2, c3));
// calc b2
var len:Number = c0 * c0 + c1 * c1 + c2 * c2 + c3 * c3;
var b0:Number;
var b1:Number;
var b2:Number;
var b3:Number;
if (len > 1e-10) { // c != 0
len = 1 / len;
b0 = c0 * len;
b1 = c1 * len;
b2 = c2 * len;
b3 = c3 * len;
} else { // c == 0
len = 1 / (1 + d0 * d0);
b0 = d0 * inv.e00 * len;
b1 = d0 * inv.e01 * len;
b2 = d0 * inv.e02 * len;
b3 = d0 * inv.e03 * len;
}
log(" b2: " + join(b0, b1, b2, b3));
// calc A2+
inv.e00 -= d0 * b0;
inv.e01 -= d0 * b1;
inv.e02 -= d0 * b2;
inv.e03 -= d0 * b3;
inv.e10 = b0;
inv.e11 = b1;
inv.e12 = b2;
inv.e13 = b3;
log(" A2+: " + join(inv.e00, inv.e01, inv.e02, inv.e03));
log(" " + join(inv.e10, inv.e11, inv.e12, inv.e13));
}
private function step3(m:Mat, inv:Mat):void {
log(" step 3:");
// calc d3
var d0:Number = inv.e00 * m.e02 + inv.e01 * m.e12 + inv.e02 * m.e22 + inv.e03 * m.e32;
var d1:Number = inv.e10 * m.e02 + inv.e11 * m.e12 + inv.e12 * m.e22 + inv.e13 * m.e32;
log(" d3: " + join(d0, d1));
// calc c3
var c0:Number = m.e02 - m.e00 * d0 - m.e01 * d1;
var c1:Number = m.e12 - m.e10 * d0 - m.e11 * d1;
var c2:Number = m.e22 - m.e20 * d0 - m.e21 * d1;
var c3:Number = m.e32 - m.e30 * d0 - m.e31 * d1;
log(" c3: " + join(c0, c1, c2, c3));
// calc b3
var len:Number = c0 * c0 + c1 * c1 + c2 * c2 + c3 * c3;
var b0:Number;
var b1:Number;
var b2:Number;
var b3:Number;
if (len > 1e-10) { // c != 0
len = 1 / len;
b0 = c0 * len;
b1 = c1 * len;
b2 = c2 * len;
b3 = c3 * len;
} else { // c == 0
len = 1 / (1 + d0 * d0 + d1 * d1);
b0 = (d0 * inv.e00 + d1 * inv.e10) * len;
b1 = (d0 * inv.e01 + d1 * inv.e11) * len;
b2 = (d0 * inv.e02 + d1 * inv.e12) * len;
b3 = (d0 * inv.e03 + d1 * inv.e13) * len;
}
log(" b3: " + join(b0, b1, b2, b3));
// calc A3+
inv.e00 -= d0 * b0;
inv.e01 -= d0 * b1;
inv.e02 -= d0 * b2;
inv.e03 -= d0 * b3;
inv.e10 -= d1 * b0;
inv.e11 -= d1 * b1;
inv.e12 -= d1 * b2;
inv.e13 -= d1 * b3;
inv.e20 = b0;
inv.e21 = b1;
inv.e22 = b2;
inv.e23 = b3;
log(" A3+: " + join(inv.e00, inv.e01, inv.e02, inv.e03));
log(" " + join(inv.e10, inv.e11, inv.e12, inv.e13));
log(" " + join(inv.e20, inv.e21, inv.e22, inv.e23));
}
private function step4(m:Mat, inv:Mat):void {
log(" step 4:");
// calc d4
var d0:Number = inv.e00 * m.e03 + inv.e01 * m.e13 + inv.e02 * m.e23 + inv.e03 * m.e33;
var d1:Number = inv.e10 * m.e03 + inv.e11 * m.e13 + inv.e12 * m.e23 + inv.e13 * m.e33;
var d2:Number = inv.e20 * m.e03 + inv.e21 * m.e13 + inv.e22 * m.e23 + inv.e23 * m.e33;
log(" d4: " + join(d0, d1, d2));
// calc c4
var c0:Number = m.e03 - m.e00 * d0 - m.e01 * d1 - m.e02 * d2;
var c1:Number = m.e13 - m.e10 * d0 - m.e11 * d1 - m.e12 * d2;
var c2:Number = m.e23 - m.e20 * d0 - m.e21 * d1 - m.e22 * d2;
var c3:Number = m.e33 - m.e30 * d0 - m.e31 * d1 - m.e32 * d2;
log(" c4: " + join(c0, c1, c2, c3));
// calc b4
var len:Number = c0 * c0 + c1 * c1 + c2 * c2 + c3 * c3;
var b0:Number;
var b1:Number;
var b2:Number;
var b3:Number;
if (len > 1e-10) { // c != 0
len = 1 / len;
b0 = c0 * len;
b1 = c1 * len;
b2 = c2 * len;
b3 = c3 * len;
} else { // c == 0
len = 1 / (1 + d0 * d0 + d1 * d1 + d2 * d2);
b0 = (d0 * inv.e00 + d1 * inv.e10 + d2 * inv.e20) * len;
b1 = (d0 * inv.e01 + d1 * inv.e11 + d2 * inv.e21) * len;
b2 = (d0 * inv.e02 + d1 * inv.e12 + d2 * inv.e22) * len;
b3 = (d0 * inv.e03 + d1 * inv.e13 + d2 * inv.e23) * len;
}
log(" b4: " + join(b0, b1, b2, b3));
// calc A4+
inv.e00 -= d0 * b0;
inv.e01 -= d0 * b1;
inv.e02 -= d0 * b2;
inv.e03 -= d0 * b3;
inv.e10 -= d1 * b0;
inv.e11 -= d1 * b1;
inv.e12 -= d1 * b2;
inv.e13 -= d1 * b3;
inv.e20 -= d2 * b0;
inv.e21 -= d2 * b1;
inv.e22 -= d2 * b2;
inv.e23 -= d2 * b3;
inv.e30 = b0;
inv.e31 = b1;
inv.e32 = b2;
inv.e33 = b3;
log(" A4+: " + join(inv.e00, inv.e01, inv.e02, inv.e03));
log(" " + join(inv.e10, inv.e11, inv.e12, inv.e13));
log(" " + join(inv.e20, inv.e21, inv.e22, inv.e23));
log(" " + join(inv.e30, inv.e31, inv.e32, inv.e33));
}
}
}
class Mat {
public var e00:Number;
public var e01:Number;
public var e02:Number;
public var e03:Number;
public var e10:Number;
public var e11:Number;
public var e12:Number;
public var e13:Number;
public var e20:Number;
public var e21:Number;
public var e22:Number;
public var e23:Number;
public var e30:Number;
public var e31:Number;
public var e32:Number;
public var e33:Number;
public function Mat() {
e00 = 1; e01 = 0; e02 = 0; e03 = 0;
e10 = 0; e11 = 1; e12 = 0; e13 = 0;
e20 = 0; e21 = 0; e22 = 1; e23 = 0;
e30 = 0; e31 = 0; e32 = 0; e33 = 1;
}
public function mul(m1:Mat, m2:Mat):void {
var t00:Number = m1.e00 * m2.e00 + m1.e01 * m2.e10 + m1.e02 * m2.e20 + m1.e03 * m2.e30;
var t01:Number = m1.e00 * m2.e01 + m1.e01 * m2.e11 + m1.e02 * m2.e21 + m1.e03 * m2.e31;
var t02:Number = m1.e00 * m2.e02 + m1.e01 * m2.e12 + m1.e02 * m2.e22 + m1.e03 * m2.e32;
var t03:Number = m1.e00 * m2.e03 + m1.e01 * m2.e13 + m1.e02 * m2.e23 + m1.e03 * m2.e33;
var t10:Number = m1.e10 * m2.e00 + m1.e11 * m2.e10 + m1.e12 * m2.e20 + m1.e13 * m2.e30;
var t11:Number = m1.e10 * m2.e01 + m1.e11 * m2.e11 + m1.e12 * m2.e21 + m1.e13 * m2.e31;
var t12:Number = m1.e10 * m2.e02 + m1.e11 * m2.e12 + m1.e12 * m2.e22 + m1.e13 * m2.e32;
var t13:Number = m1.e10 * m2.e03 + m1.e11 * m2.e13 + m1.e12 * m2.e23 + m1.e13 * m2.e33;
var t20:Number = m1.e20 * m2.e00 + m1.e21 * m2.e10 + m1.e22 * m2.e20 + m1.e23 * m2.e30;
var t21:Number = m1.e20 * m2.e01 + m1.e21 * m2.e11 + m1.e22 * m2.e21 + m1.e23 * m2.e31;
var t22:Number = m1.e20 * m2.e02 + m1.e21 * m2.e12 + m1.e22 * m2.e22 + m1.e23 * m2.e32;
var t23:Number = m1.e20 * m2.e03 + m1.e21 * m2.e13 + m1.e22 * m2.e23 + m1.e23 * m2.e33;
var t30:Number = m1.e30 * m2.e00 + m1.e31 * m2.e10 + m1.e32 * m2.e20 + m1.e33 * m2.e30;
var t31:Number = m1.e30 * m2.e01 + m1.e31 * m2.e11 + m1.e32 * m2.e21 + m1.e33 * m2.e31;
var t32:Number = m1.e30 * m2.e02 + m1.e31 * m2.e12 + m1.e32 * m2.e22 + m1.e33 * m2.e32;
var t33:Number = m1.e30 * m2.e03 + m1.e31 * m2.e13 + m1.e32 * m2.e23 + m1.e33 * m2.e33;
e00 = t00;
e01 = t01;
e02 = t02;
e03 = t03;
e10 = t10;
e11 = t11;
e12 = t12;
e13 = t13;
e20 = t20;
e21 = t21;
e22 = t22;
e23 = t23;
e30 = t30;
e31 = t31;
e32 = t32;
e33 = t33;
}
}