//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * 4×4行列テスト実装
 * @author Junpee
 */

#include "Test/stdafx.h"
#include "Core/Primitive/Matrix44Test.h"
#include "Core/Primitive/Matrix44.h"
#include "Core/Primitive/Matrix33.h"
#include "Core/Primitive/Matrix34.h"
#include "Core/Primitive/Quaternion.h"

//------------------------------------------------------------------------------
// コンストラクタ
Matrix44Test::Matrix44Test(String name) : TestCase(name){
}
//------------------------------------------------------------------------------
// テストスィートの取得
Test* Matrix44Test::suite(){
	TestSuite* suite = new TestSuite("Matrix44Test");
	suite->addTest(new TestCaller(Matrix44Test, testConstructor));
	suite->addTest(new TestCaller(Matrix44Test, testFixedNumber));
	suite->addTest(new TestCaller(Matrix44Test, testSetValue));
	suite->addTest(new TestCaller(Matrix44Test, testScale));
	suite->addTest(new TestCaller(Matrix44Test, testRotation));
	suite->addTest(new TestCaller(Matrix44Test, testQuaternion));
	suite->addTest(new TestCaller(Matrix44Test, testThreeAxisRotation));
	suite->addTest(new TestCaller(Matrix44Test, testTranslation));
	suite->addTest(new TestCaller(Matrix44Test, testTransformation));
	suite->addTest(new TestCaller(Matrix44Test, testMul));
	suite->addTest(new TestCaller(Matrix44Test, testMatrixOperation));
	suite->addTest(new TestCaller(Matrix44Test, testLogicalOperation));
	suite->addTest(new TestCaller(Matrix44Test, testToString));
	return suite;
}
//------------------------------------------------------------------------------
// コンストラクタテスト
void Matrix44Test::testConstructor(){
	TestEquals(64, (int)sizeof(Matrix44));
	Matrix44 mtx0(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	float source[] = {
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f};
	Matrix44 mtx1(source);
	TestAssert(mtx0 == mtx1);
	TestEquals( 0.f, mtx0.m00);
	TestEquals( 1.f, mtx0.m01);
	TestEquals( 2.f, mtx0.m02);
	TestEquals( 3.f, mtx0.m03);
	TestEquals(10.f, mtx0.m10);
	TestEquals(11.f, mtx0.m11);
	TestEquals(12.f, mtx0.m12);
	TestEquals(13.f, mtx0.m13);
	TestEquals(20.f, mtx0.m20);
	TestEquals(21.f, mtx0.m21);
	TestEquals(22.f, mtx0.m22);
	TestEquals(23.f, mtx0.m23);
	TestEquals(30.f, mtx0.m30);
	TestEquals(31.f, mtx0.m31);
	TestEquals(32.f, mtx0.m32);
	TestEquals(33.f, mtx0.m33);
	TestEquals( 0.f, mtx0.m[0][0]);
	TestEquals( 1.f, mtx0.m[0][1]);
	TestEquals( 2.f, mtx0.m[0][2]);
	TestEquals( 3.f, mtx0.m[0][3]);
	TestEquals(10.f, mtx0.m[1][0]);
	TestEquals(11.f, mtx0.m[1][1]);
	TestEquals(12.f, mtx0.m[1][2]);
	TestEquals(13.f, mtx0.m[1][3]);
	TestEquals(20.f, mtx0.m[2][0]);
	TestEquals(21.f, mtx0.m[2][1]);
	TestEquals(22.f, mtx0.m[2][2]);
	TestEquals(23.f, mtx0.m[2][3]);
	TestEquals(30.f, mtx0.m[3][0]);
	TestEquals(31.f, mtx0.m[3][1]);
	TestEquals(32.f, mtx0.m[3][2]);
	TestEquals(33.f, mtx0.m[3][3]);
	TestEquals( 0.f, mtx0.array[ 0]);
	TestEquals( 1.f, mtx0.array[ 1]);
	TestEquals( 2.f, mtx0.array[ 2]);
	TestEquals( 3.f, mtx0.array[ 3]);
	TestEquals(10.f, mtx0.array[ 4]);
	TestEquals(11.f, mtx0.array[ 5]);
	TestEquals(12.f, mtx0.array[ 6]);
	TestEquals(13.f, mtx0.array[ 7]);
	TestEquals(20.f, mtx0.array[ 8]);
	TestEquals(21.f, mtx0.array[ 9]);
	TestEquals(22.f, mtx0.array[10]);
	TestEquals(23.f, mtx0.array[11]);
	TestEquals(30.f, mtx0.array[12]);
	TestEquals(31.f, mtx0.array[13]);
	TestEquals(32.f, mtx0.array[14]);
	TestEquals(33.f, mtx0.array[15]);
}
//------------------------------------------------------------------------------
// 定数テスト
void Matrix44Test::testFixedNumber(){
	Matrix44 mtx0(
		0.f, 0.f, 0.f, 0.f,
		0.f, 0.f, 0.f, 0.f,
		0.f, 0.f, 0.f, 0.f,
		0.f, 0.f, 0.f, 0.f);
	TestAssert(mtx0 == Matrix44::zero);
	Matrix44 mtx1(
		1.f, 0.f, 0.f, 0.f,
		0.f, 1.f, 0.f, 0.f,
		0.f, 0.f, 1.f, 0.f,
		0.f, 0.f, 0.f, 1.f);
	TestAssert(mtx1 == Matrix44::unit);
}
//------------------------------------------------------------------------------
// 値の設定テスト
void Matrix44Test::testSetValue(){
	Matrix44 mtx0(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	Matrix44 mtx1;
	mtx1.set(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	TestAssert(mtx0 == mtx1);
	Matrix44 mtx2;
	float source[] = {
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f};
	mtx2.set(source);
	TestAssert(mtx0 == mtx2);
	Matrix44 mtx3;
	mtx3.setZero();
	TestAssert(Matrix44::zero == mtx3);
	Matrix44 mtx4;
	mtx4.setUnit();
	TestAssert(Matrix44::unit == mtx4);
	// 行列の設定
	Matrix44 mtx44;
	Matrix33 mtx33(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f);
	mtx44.set(mtx33);
	for(int i = 0;i < 3;i++){
		for(int j = 0;j < 3;j++){
			TestEquals(mtx33.m[i][j], mtx44.m[i][j]);
		}
		TestEquals(0.f, mtx44.m[i][3]);
		TestEquals(0.f, mtx44.m[3][i]);
	}
	TestEquals(1.f, mtx44.m[3][3]);
	Matrix34 mtx43(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f);
	mtx44.set(mtx43);
	for(int i = 0;i < 3;i++){
		for(int j = 0;j < 4;j++){
			TestEquals(mtx44.m[i][j], mtx43.m[i][j]);
		}
	}
	TestEquals(0.f, mtx44.m[3][0]);
	TestEquals(0.f, mtx44.m[3][1]);
	TestEquals(0.f, mtx44.m[3][2]);
	TestEquals(1.f, mtx44.m[3][3]);
}
//------------------------------------------------------------------------------
// スケールテスト
void Matrix44Test::testScale(){
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	Matrix44 mtx0;
	// 設定
	D3DXMatrixScaling(&d3dMtx, 1.f, 2.f, 3.f);
	mtx0.setScale(1.f, 2.f, 3.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	mtx0.setScale(Vector3(1.f, 2.f, 3.f));
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// 追加
	mtx0.setUnit();
	mtx0.addScale(1.f, 2.f, 3.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	mtx0.setUnit();
	mtx0.addScale(Vector3(1.f, 2.f, 3.f));
	TestAssert(d3dEquals(d3dMtx, mtx0));
}
//------------------------------------------------------------------------------
// 回転テスト
void Matrix44Test::testRotation(){
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	Matrix44 mtx0;
	// X軸回転設定
	D3DXMatrixRotationX(&d3dMtx, 1.f);
	mtx0.setRotationX(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// X軸回転追加
	mtx0.setUnit();
	mtx0.addRotationX(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// Y軸回転設定
	D3DXMatrixRotationY(&d3dMtx, 1.f);
	mtx0.setRotationY(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// Y軸回転追加
	mtx0.setUnit();
	mtx0.addRotationY(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// Z軸回転設定
	D3DXMatrixRotationZ(&d3dMtx, 1.f);
	mtx0.setRotationZ(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// Z軸回転追加
	mtx0.setUnit();
	mtx0.addRotationZ(1.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// 任意軸回転
	D3DXVECTOR3 d3dVec(1.f, 2.f, 3.f);
	D3DXMatrixRotationAxis(&d3dMtx, &d3dVec, 1.f);
	Vector3 vec(1.f, 2.f, 3.f);
	vec.normalize();
	mtx0.setRotationAxis(vec, 1.f);
	TestAssert(d3dEpsilonEquals(d3dMtx, mtx0, Math::epsilon));
	// 任意軸回転追加
	mtx0.setUnit();
	mtx0.addRotationAxis(vec, 1.f);
	TestAssert(d3dEpsilonEquals(d3dMtx, mtx0, Math::epsilon));
	// 任意軸回転取得
	Vector3 vector;
	float radian;
	mtx0.getRotationAxis(&vector, &radian);
	TestAssert(vec.epsilonEquals(vector, Math::epsilon));
	TestEpsilonEquals(1.f, radian, Math::epsilon);
}
//------------------------------------------------------------------------------
// 四元数テスト
void Matrix44Test::testQuaternion(){
	// 回転設定
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	D3DXQUATERNION d3dQuat(1.f, 2.f, 3.f, 1.f);
	D3DXQuaternionNormalize(&d3dQuat, &d3dQuat);
	D3DXMatrixRotationQuaternion(&d3dMtx, &d3dQuat);
	Matrix44 mtx0;
	Quaternion quat0(1.f, 2.f, 3.f, 1.f);
	quat0.normalize();
	mtx0.setRotationQuaternion(quat0);
	TestAssert(d3dEpsilonEquals(d3dMtx, mtx0, Math::epsilon));
	// 回転追加
	D3DXMatrixMultiply(&d3dMtx, &d3dMtx, &d3dMtx);
	mtx0.addRotationQuaternion(quat0);
	TestAssert(d3dEpsilonEquals(d3dMtx, mtx0, Math::epsilon));
	// 回転取得
	D3DXQuaternionRotationMatrix(&d3dQuat, &d3dMtx);
	quat0 = mtx0.getRotationQuaternion();
	TestEpsilonEquals(d3dQuat.x, quat0.x, Math::epsilon);
	TestEpsilonEquals(d3dQuat.y, quat0.y, Math::epsilon);
	TestEpsilonEquals(d3dQuat.z, quat0.z, Math::epsilon);
	TestEpsilonEquals(d3dQuat.w, quat0.w, Math::epsilon);
	D3DXQUATERNION d3dQuat1(1.f, 2.f, 3.f, 0.5f);
	D3DXQuaternionNormalize(&d3dQuat1, &d3dQuat1);
	D3DXMatrixRotationQuaternion(&d3dMtx, &d3dQuat1);
	D3DXQuaternionRotationMatrix(&d3dQuat, &d3dMtx);
	quat0.set(1.f, 2.f, 3.f, 0.5f);
	quat0.normalize();
	mtx0.setRotationQuaternion(quat0);
	quat0 = mtx0.getRotationQuaternion();
	TestEpsilonEquals(d3dQuat.x, quat0.x, Math::epsilon);
	TestEpsilonEquals(d3dQuat.y, quat0.y, Math::epsilon);
	TestEpsilonEquals(d3dQuat.z, quat0.z, Math::epsilon);
	TestEpsilonEquals(d3dQuat.w, quat0.w, Math::epsilon);
}
//------------------------------------------------------------------------------
// 三軸回転テスト
void Matrix44Test::testThreeAxisRotation(){
	Matrix44 mtxRotX, mtxRotY, mtxRotZ, mtxResult, mtx0, mtx1;
	Vector3 vec0(0.5f, -1.f, 1.5f), vec1, vec2;
	mtxRotX.setRotationX(0.5f);
	mtxRotY.setRotationY(-1.f);
	mtxRotZ.setRotationZ(1.5f);
	// XYZ
	mtxResult = mtxRotZ * mtxRotY * mtxRotX;
	mtx0.setRotationXYZ(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationXYZ(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationXYZ(&vec1));
	mtx1.setRotationXYZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-1.5f, Math::halfPI, 10.f);
	mtx0.setRotationXYZ(vec2);
	mtx0.getRotationXYZ(&vec1);
	mtx1.setRotationXYZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-0.5f, -Math::halfPI, 10.f);
	mtx0.setRotationXYZ(vec2);
	mtx0.getRotationXYZ(&vec1);
	mtx1.setRotationXYZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	// XZY
	mtxResult = mtxRotY * mtxRotZ * mtxRotX;
	mtx0.setRotationXZY(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationXZY(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationXZY(&vec1));
	mtx1.setRotationXZY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-0.75f, 10.f, Math::halfPI);
	mtx0.setRotationXZY(vec2);
	mtx0.getRotationXZY(&vec1);
	mtx1.setRotationXZY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-0.55f, 30.f, -Math::halfPI);
	mtx0.setRotationXZY(vec2);
	mtx0.getRotationXZY(&vec1);
	mtx1.setRotationXZY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	// YXZ
	mtxResult = mtxRotZ * mtxRotX * mtxRotY;
	mtx0.setRotationYXZ(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationYXZ(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationYXZ(&vec1));
	mtx1.setRotationYXZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(Math::halfPI, -Math::halfPI, Math::halfPI);
	mtx0.setRotationYXZ(vec2);
	mtx0.getRotationYXZ(&vec1);
	mtx1.setRotationYXZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-Math::halfPI, Math::halfPI, -Math::halfPI);
	mtx0.setRotationYXZ(vec2);
	mtx0.getRotationYXZ(&vec1);
	mtx1.setRotationYXZ(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	// YZX
	mtxResult = mtxRotX * mtxRotZ * mtxRotY;
	mtx0.setRotationYZX(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationYZX(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationYZX(&vec1));
	mtx1.setRotationYZX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(1.f, 0.5f, Math::halfPI);
	mtx0.setRotationYZX(vec2);
	mtx0.getRotationYZX(&vec1);
	mtx1.setRotationYZX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(1.f, 0.5f, -Math::halfPI);
	mtx0.setRotationYZX(vec2);
	mtx0.getRotationYZX(&vec1);
	mtx1.setRotationYZX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	// ZXY
	mtxResult = mtxRotY * mtxRotX * mtxRotZ;
	mtx0.setRotationZXY(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationZXY(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationZXY(&vec1));
	mtx1.setRotationZXY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(Math::halfPI, -1.5f, 10.f);
	mtx0.setRotationZXY(vec2);
	mtx0.getRotationZXY(&vec1);
	mtx1.setRotationZXY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-Math::halfPI, -0.5f, 10.f);
	mtx0.setRotationZXY(vec2);
	mtx0.getRotationZXY(&vec1);
	mtx1.setRotationZXY(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	// ZYX
	mtxResult = mtxRotX * mtxRotY * mtxRotZ;
	mtx0.setRotationZYX(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addRotationZYX(vec0);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	TestAssert(mtx0.getRotationZYX(&vec1));
	mtx1.setRotationZYX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(1.5f, Math::halfPI, 1.0f);
	mtx0.setRotationZYX(vec2);
	mtx0.getRotationZYX(&vec1);
	mtx1.setRotationZYX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	vec2.set(-1.5f, -Math::halfPI, -1.f);
	mtx0.setRotationZYX(vec2);
	mtx0.getRotationZYX(&vec1);
	mtx1.setRotationZYX(vec1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
}
//------------------------------------------------------------------------------
// 移動テスト
void Matrix44Test::testTranslation(){
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	Matrix44 mtx0;
	// 設定
	D3DXMatrixTranslation(&d3dMtx, 1.f, 2.f, 3.f);
	mtx0.setTranslation(1.f, 2.f, 3.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	mtx0.setTranslation(Vector3(1.f, 2.f, 3.f));
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// 追加
	mtx0.setUnit();
	mtx0.addTranslation(1.f, 2.f, 3.f);
	TestAssert(d3dEquals(d3dMtx, mtx0));
	mtx0.setUnit();
	mtx0.addTranslation(Vector3(1.f, 2.f, 3.f));
	TestAssert(d3dEquals(d3dMtx, mtx0));
}
//------------------------------------------------------------------------------
// 変換テスト
void Matrix44Test::testTransformation(){
	Matrix44 mtxRotX, mtxRotY, mtxRotZ, mtxTrans, mtxResult, mtx0, mtx1;
	Vector3 rotation(0.5f, -1.f, 1.5f), translation(10.f, 20.f, 30.f);
	mtxRotX.setRotationX(0.5f);
	mtxRotY.setRotationY(-1.f);
	mtxRotZ.setRotationZ(1.5f);
	mtxTrans.setTranslation(translation);
	// XYZ
	mtxResult = mtxTrans * mtxRotZ * mtxRotY * mtxRotX;
	mtx0.setTransformationXYZ(rotation, translation);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addTransformationXYZ(rotation, translation);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	// Quaternion
	Quaternion quat;
	quat.setRotationXYZ(rotation);
	mtx0.setTransformationQuaternion(quat, translation);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	mtx0.setUnit();
	mtx0.addTransformationQuaternion(quat, translation);
	TestAssert(mtxResult.epsilonEquals(mtx0, Math::epsilon));
	// 変換逆行列
	Vector3 position(10.f, 20.f, 30.f), transPosition;
	mtx0.setTransformationQuaternion(quat, translation);
	mtx1 = mtx0;
	mtx1.invertTransformation();
	TestAssert((mtx0 * mtx1).epsilonEquals(Matrix44::unit, 0.0001f));
	transPosition = mtx0 * position;
	transPosition = mtx1 * transPosition;
	TestAssert(position.epsilonEquals(transPosition, 0.0001f));

	mtx0.invertTransformation(&mtx1);
	TestAssert((mtx0 * mtx1).epsilonEquals(Matrix44::unit, 0.0001f));
	transPosition = mtx0 * position;
	transPosition = mtx1 * transPosition;
	TestAssert(position.epsilonEquals(transPosition, 0.0001f));

}
//------------------------------------------------------------------------------
// 乗算テスト
void Matrix44Test::testMul(){
	D3DXMATRIX __declspec(align(16))
		d3dScale, d3dRotX, d3dRotY, d3dRotZ, d3dTrans, d3dResult;
	D3DXMatrixScaling(&d3dScale, 1.f, 2.f, 3.f);
	D3DXMatrixRotationX(&d3dRotX, 1.f);
	D3DXMatrixRotationY(&d3dRotY, 2.f);
	D3DXMatrixRotationZ(&d3dRotZ, 3.f);
	D3DXMatrixTranslation(&d3dTrans, 1.f, 2.f, 3.f);
	D3DXMatrixMultiply(&d3dResult, &d3dScale, &d3dRotX);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotY);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotZ);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dTrans);
	Matrix44 mtxScale, mtxRotX, mtxRotY, mtxRotZ, mtxTrans, mtxResult, mtx0;
	// 乗算
	mtxScale.setScale(1.f, 2.f, 3.f);
	mtxRotX.setRotationX(1.f);
	mtxRotY.setRotationY(2.f);
	mtxRotZ.setRotationZ(3.f);
	mtxTrans.setTranslation(1.f, 2.f, 3.f);
	mtxResult = mtxTrans * mtxRotZ * mtxRotY * mtxRotX * mtxScale;
	TestAssert(d3dEpsilonEquals(d3dResult, mtxResult, Math::epsilon));
	// 代入乗算
	mtxResult = mtxTrans;
	mtxResult *= mtxRotZ;
	mtxResult *= mtxRotY;
	mtxResult *= mtxRotX;
	mtxResult *= mtxScale;
	TestAssert(d3dEpsilonEquals(d3dResult, mtxResult, Math::epsilon));
	// ベクトル乗算
	D3DXVECTOR3 d3dVec(1.f, 2.f, 3.f);
	D3DXVECTOR4 d3dVecRes;
	D3DXVec3Transform(&d3dVecRes, &d3dVec, &d3dResult);
	Vector3 mtxVec = mtxResult * Vector3(1.f, 2.f, 3.f);
	TestEpsilonEquals(d3dVecRes.x, mtxVec.x, Math::epsilon);
	TestEpsilonEquals(d3dVecRes.y, mtxVec.y, Math::epsilon);
	TestEpsilonEquals(d3dVecRes.z, mtxVec.z, Math::epsilon);
	// スカラー乗算
	mtx0 = mtxResult * 2.f;
	for(int i = 0;i < 16;i++){ TestEquals(mtxResult.array[i] * 2.f, mtx0.array[i]); }
	mtx0 *= 0.5f;
	TestAssert(mtxResult == mtx0);
}
//------------------------------------------------------------------------------
// 行列演算テスト
void Matrix44Test::testMatrixOperation(){
	// 転置
	D3DXMATRIX d3dMtx(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	D3DXMatrixTranspose(&d3dMtx, &d3dMtx);
	Matrix44 mtx0(
		 0.f, 10.f, 20.f, 30.f,
		 1.f, 11.f, 21.f, 31.f,
		 2.f, 12.f, 22.f, 32.f,
		 3.f, 13.f, 23.f, 33.f);
	mtx0.transpose();
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// 行列式前準備
	D3DXMATRIX __declspec(align(16))
		d3dScale, d3dRotX, d3dRotY, d3dRotZ, d3dTrans, d3dResult;
	D3DXMatrixScaling(&d3dScale, 1.f, 2.f, 3.f);
	D3DXMatrixRotationX(&d3dRotX, 1.f);
	D3DXMatrixRotationY(&d3dRotY, 2.f);
	D3DXMatrixRotationZ(&d3dRotZ, 3.f);
	D3DXMatrixTranslation(&d3dTrans, 1.f, 2.f, 3.f);
	D3DXMatrixMultiply(&d3dResult, &d3dScale, &d3dRotX);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotY);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotZ);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dTrans);
	Matrix44 mtxScale, mtxRotX, mtxRotY, mtxRotZ, mtxTrans, mtxResult;
	mtxScale.setScale(1.f, 2.f, 3.f);
	mtxRotX.setRotationX(1.f);
	mtxRotY.setRotationY(2.f);
	mtxRotZ.setRotationZ(3.f);
	mtxTrans.setTranslation(1.f, 2.f, 3.f);
	mtxResult = mtxTrans * mtxRotZ * mtxRotY * mtxRotX * mtxScale;
	// 行列式
	float d3dDeterm = D3DXMatrixDeterminant(&d3dResult);
	float determ = mtxResult.determinant();
	TestEquals(d3dDeterm, determ);
	// 逆行列
	d3dResult._14 = 1.f;
	d3dResult._24 = 2.f;
	d3dResult._34 = 3.f;
	mtxResult.m30 = 1.f;
	mtxResult.m31 = 2.f;
	mtxResult.m32 = 3.f;
	D3DXMatrixInverse(&d3dResult, &d3dDeterm, &d3dResult);
	Matrix44 mtxInv;
	determ = mtxResult.invert(&mtxInv);
	TestEquals(d3dDeterm, determ);
	TestAssert(d3dEpsilonEquals(d3dResult, mtxInv, Math::epsilon));
	determ = mtxResult.invert();
	TestEquals(d3dDeterm, determ);
	TestAssert(d3dEpsilonEquals(d3dResult, mtxResult, Math::epsilon));
}
//------------------------------------------------------------------------------
// 論理演算テスト
void Matrix44Test::testLogicalOperation(){
	Matrix44 mtx0(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	Matrix44 mtx1(
		 0.f,  1.f,  2.f,  3.f,
		10.f, 11.f, 12.f, 13.f,
		20.f, 21.f, 22.f, 23.f,
		30.f, 31.f, 32.f, 33.f);
	TestAssert(mtx0 == mtx1);
	mtx1.m00 += Math::epsilon;
	TestAssert(mtx0 != mtx1);
	TestAssert(mtx0.epsilonEquals(mtx1, Math::epsilon));
	TestAssert(!mtx0.notEpsilonEquals(mtx1, Math::epsilon));
	TestAssert(!mtx0.epsilonEquals(mtx1, 0.f));
	TestAssert(mtx0.notEpsilonEquals(mtx1, 0.f));
}
//------------------------------------------------------------------------------
// 文字列テスト
void Matrix44Test::testToString(){
	Matrix44 mtx0(
		12345678.f, 1234.5678f, 0.12345678f, 0.12345678f,
		22345678.f, 2234.5678f, 2.12345678f, 2.12345678f,
		32345678.f, 3234.5678f, 3.12345678f, 3.12345678f,
		42345678.f, 4234.5678f, 4.12345678f, 4.12345678f);
	TestEquals("{\n"
		"  ( 12345678.00000000, 1234.56774902, 0.12345678, 0.12345678 )\n"
		"  ( 22345678.00000000, 2234.56787109, 2.12345672, 2.12345672 )\n"
		"  ( 32345678.00000000, 3234.56787109, 3.12345672, 3.12345672 )\n"
		"  ( 42345680.00000000, 4234.56787109, 4.12345695, 4.12345695 )\n}",
		mtx0.toString());
}
//------------------------------------------------------------------------------
// Direct3D行列との比較
bool Matrix44Test::d3dEquals(D3DXMATRIX& d3d, Matrix44& mtx){
	return(
		(d3d.m[0][0] == mtx.m00) &&
		(d3d.m[0][1] == mtx.m10) &&
		(d3d.m[0][2] == mtx.m20) &&
		(d3d.m[0][3] == mtx.m30) &&
		(d3d.m[1][0] == mtx.m01) &&
		(d3d.m[1][1] == mtx.m11) &&
		(d3d.m[1][2] == mtx.m21) &&
		(d3d.m[1][3] == mtx.m31) &&
		(d3d.m[2][0] == mtx.m02) &&
		(d3d.m[2][1] == mtx.m12) &&
		(d3d.m[2][2] == mtx.m22) &&
		(d3d.m[2][3] == mtx.m32) &&
		(d3d.m[3][0] == mtx.m03) &&
		(d3d.m[3][1] == mtx.m13) &&
		(d3d.m[3][2] == mtx.m23) &&
		(d3d.m[3][3] == mtx.m33));
}
//------------------------------------------------------------------------------
// Direct3D行列との比較
bool Matrix44Test::d3dEpsilonEquals(
	D3DXMATRIX& d3d, Matrix44& mtx, float epsilon){
	return(
		(Math::abs(d3d.m[0][0] - mtx.m00) <= epsilon) &&
		(Math::abs(d3d.m[0][1] - mtx.m10) <= epsilon) &&
		(Math::abs(d3d.m[0][2] - mtx.m20) <= epsilon) &&
		(Math::abs(d3d.m[0][3] - mtx.m30) <= epsilon) &&
		(Math::abs(d3d.m[1][0] - mtx.m01) <= epsilon) &&
		(Math::abs(d3d.m[1][1] - mtx.m11) <= epsilon) &&
		(Math::abs(d3d.m[1][2] - mtx.m21) <= epsilon) &&
		(Math::abs(d3d.m[1][3] - mtx.m31) <= epsilon) &&
		(Math::abs(d3d.m[2][0] - mtx.m02) <= epsilon) &&
		(Math::abs(d3d.m[2][1] - mtx.m12) <= epsilon) &&
		(Math::abs(d3d.m[2][2] - mtx.m22) <= epsilon) &&
		(Math::abs(d3d.m[2][3] - mtx.m32) <= epsilon) &&
		(Math::abs(d3d.m[3][0] - mtx.m03) <= epsilon) &&
		(Math::abs(d3d.m[3][1] - mtx.m13) <= epsilon) &&
		(Math::abs(d3d.m[3][2] - mtx.m23) <= epsilon) &&
		(Math::abs(d3d.m[3][3] - mtx.m33) <= epsilon));
}
//------------------------------------------------------------------------------
