//------------------------------------------------------------------------------
// 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
 * 3×3行列テスト実装
 * @author Junpee
 */

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

//------------------------------------------------------------------------------
// コンストラクタ
Matrix33Test::Matrix33Test(String name) : TestCase(name){
}
//------------------------------------------------------------------------------
// テストスィートの取得
Test* Matrix33Test::suite(){
	TestSuite* suite = new TestSuite("Matrix33Test");
	suite->addTest(new TestCaller(Matrix33Test, testConstructor));
	suite->addTest(new TestCaller(Matrix33Test, testFixedNumber));
	suite->addTest(new TestCaller(Matrix33Test, testSetValue));
	suite->addTest(new TestCaller(Matrix33Test, testScale));
	suite->addTest(new TestCaller(Matrix33Test, testRotation));
	suite->addTest(new TestCaller(Matrix33Test, testQuaternion));
	suite->addTest(new TestCaller(Matrix33Test, testThreeAxisRotation));
	suite->addTest(new TestCaller(Matrix33Test, testMul));
	suite->addTest(new TestCaller(Matrix33Test, testMatrixOperation));
	suite->addTest(new TestCaller(Matrix33Test, testLogicalOperation));
	suite->addTest(new TestCaller(Matrix33Test, testToString));
	return suite;
}
//------------------------------------------------------------------------------
// コンストラクタテスト
void Matrix33Test::testConstructor(){
	TestEquals(36, (int)sizeof(Matrix33));
	Matrix33 mtx0(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f);
	float source[] = {
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f};
	Matrix33 mtx1(source);
	TestAssert(mtx0 == mtx1);
	TestEquals( 0.f, mtx0.m00);
	TestEquals( 1.f, mtx0.m01);
	TestEquals( 2.f, mtx0.m02);
	TestEquals(10.f, mtx0.m10);
	TestEquals(11.f, mtx0.m11);
	TestEquals(12.f, mtx0.m12);
	TestEquals(20.f, mtx0.m20);
	TestEquals(21.f, mtx0.m21);
	TestEquals(22.f, mtx0.m22);
	TestEquals( 0.f, mtx0.m[0][0]);
	TestEquals( 1.f, mtx0.m[0][1]);
	TestEquals( 2.f, mtx0.m[0][2]);
	TestEquals(10.f, mtx0.m[1][0]);
	TestEquals(11.f, mtx0.m[1][1]);
	TestEquals(12.f, mtx0.m[1][2]);
	TestEquals(20.f, mtx0.m[2][0]);
	TestEquals(21.f, mtx0.m[2][1]);
	TestEquals(22.f, mtx0.m[2][2]);
	TestEquals( 0.f, mtx0.array[ 0]);
	TestEquals( 1.f, mtx0.array[ 1]);
	TestEquals( 2.f, mtx0.array[ 2]);
	TestEquals(10.f, mtx0.array[ 3]);
	TestEquals(11.f, mtx0.array[ 4]);
	TestEquals(12.f, mtx0.array[ 5]);
	TestEquals(20.f, mtx0.array[ 6]);
	TestEquals(21.f, mtx0.array[ 7]);
	TestEquals(22.f, mtx0.array[ 8]);
}
//------------------------------------------------------------------------------
// 定数テスト
void Matrix33Test::testFixedNumber(){
	Matrix33 mtx0(
		0.f, 0.f, 0.f,
		0.f, 0.f, 0.f,
		0.f, 0.f, 0.f);
	TestAssert(mtx0 == Matrix33::zero);
	Matrix33 mtx1(
		1.f, 0.f, 0.f,
		0.f, 1.f, 0.f,
		0.f, 0.f, 1.f);
	TestAssert(mtx1 == Matrix33::unit);
}
//------------------------------------------------------------------------------
// 値の設定テスト
void Matrix33Test::testSetValue(){
	Matrix33 mtx0(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f);
	Matrix33 mtx1;
	mtx1.set(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f);
	TestAssert(mtx0 == mtx1);
	Matrix33 mtx2;
	float source[] = {
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f};
	mtx2.set(source);
	TestAssert(mtx0 == mtx2);
	Matrix33 mtx3;
	mtx3.setZero();
	TestAssert(Matrix33::zero == mtx3);
	Matrix33 mtx4;
	mtx4.setUnit();
	TestAssert(Matrix33::unit == mtx4);
	// 行列の設定
	Matrix33 mtx33;
	Matrix34 mtx43(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f,
		30.f, 31.f, 32.f);
	mtx33.set(mtx43);
	for(int i = 0;i < 3;i++){
		for(int j = 0;j < 3;j++){
			TestEquals(mtx43.m[i][j], mtx33.m[i][j]);
		}
	}
	Matrix44 mtx44(
		 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);
	mtx33.set(mtx44);
	for(int i = 0;i < 3;i++){
		for(int j = 0;j < 3;j++){
			TestEquals(mtx44.m[i][j], mtx33.m[i][j]);
		}
	}
}
//------------------------------------------------------------------------------
// スケールテスト
void Matrix33Test::testScale(){
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	Matrix33 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 Matrix33Test::testRotation(){
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	Matrix33 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 Matrix33Test::testQuaternion(){
	// 回転設定
	D3DXMATRIX __declspec(align(16)) d3dMtx;
	D3DXQUATERNION d3dQuat(1.f, 2.f, 3.f, 1.f);
	D3DXQuaternionNormalize(&d3dQuat, &d3dQuat);
	D3DXMatrixRotationQuaternion(&d3dMtx, &d3dQuat);
	Matrix33 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 Matrix33Test::testThreeAxisRotation(){
	Matrix33 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 Matrix33Test::testMul(){
	D3DXMATRIX __declspec(align(16))
		d3dScale, d3dRotX, d3dRotY, d3dRotZ, d3dResult;
	D3DXMatrixScaling(&d3dScale, 1.f, 2.f, 3.f);
	D3DXMatrixRotationX(&d3dRotX, 1.f);
	D3DXMatrixRotationY(&d3dRotY, 2.f);
	D3DXMatrixRotationZ(&d3dRotZ, 3.f);
	D3DXMatrixMultiply(&d3dResult, &d3dScale, &d3dRotX);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotY);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotZ);
	Matrix33 mtxScale, mtxRotX, mtxRotY, mtxRotZ, mtxResult, mtx0;
	// 乗算
	mtxScale.setScale(1.f, 2.f, 3.f);
	mtxRotX.setRotationX(1.f);
	mtxRotY.setRotationY(2.f);
	mtxRotZ.setRotationZ(3.f);
	mtxResult = mtxRotZ * mtxRotY * mtxRotX * mtxScale;
	TestAssert(d3dEpsilonEquals(d3dResult, mtxResult, Math::epsilon));
	// 代入乗算
	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 < 9;i++){ TestEquals(mtxResult.array[i] * 2.f, mtx0.array[i]); }
	mtx0 *= 0.5f;
	TestAssert(mtxResult == mtx0);
}
//------------------------------------------------------------------------------
// 行列演算テスト
void Matrix33Test::testMatrixOperation(){
	// 転置
	D3DXMATRIX __declspec(align(16)) d3dMtx(
		0.f, 1.f, 2.f, 0.f,
		3.f, 4.f, 5.f, 0.f,
		6.f, 7.f, 8.f, 0.f,
		0.f, 0.f, 0.f, 1.f);
	D3DXMatrixTranspose(&d3dMtx, &d3dMtx);
	Matrix33 mtx0(
		0.f,  3.f,  6.f,
		1.f,  4.f,  7.f,
		2.f,  5.f,  8.f);
	mtx0.transpose();
	TestAssert(d3dEquals(d3dMtx, mtx0));
	// 行列式前準備
	D3DXMATRIX __declspec(align(16))
		d3dScale, d3dRotX, d3dRotY, d3dRotZ, d3dResult;
	D3DXMatrixScaling(&d3dScale, 1.f, 2.f, 3.f);
	D3DXMatrixRotationX(&d3dRotX, 1.f);
	D3DXMatrixRotationY(&d3dRotY, 2.f);
	D3DXMatrixRotationZ(&d3dRotZ, 3.f);
	D3DXMatrixMultiply(&d3dResult, &d3dScale, &d3dRotX);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotY);
	D3DXMatrixMultiply(&d3dResult, &d3dResult, &d3dRotZ);
	Matrix33 mtxScale, mtxRotX, mtxRotY, mtxRotZ, mtxResult;
	mtxScale.setScale(1.f, 2.f, 3.f);
	mtxRotX.setRotationX(1.f);
	mtxRotY.setRotationY(2.f);
	mtxRotZ.setRotationZ(3.f);
	mtxResult = mtxRotZ * mtxRotY * mtxRotX * mtxScale;
	// 行列式
	float d3dDeterm = D3DXMatrixDeterminant(&d3dResult);
	float determ = mtxResult.determinant();
	TestEquals(d3dDeterm, determ);
	// 逆行列
	D3DXMatrixInverse(&d3dResult, &d3dDeterm, &d3dResult);
	Matrix33 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 Matrix33Test::testLogicalOperation(){
	Matrix33 mtx0(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.f);
	Matrix33 mtx1(
		 0.f,  1.f,  2.f,
		10.f, 11.f, 12.f,
		20.f, 21.f, 22.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 Matrix33Test::testToString(){
	Matrix33 mtx0(
		12345678.f, 1234.5678f, 0.12345678f,
		22345678.f, 2234.5678f, 2.12345678f,
		32345678.f, 3234.5678f, 3.12345678f);
	TestEquals("{\n"
		"  ( 12345678.00000000, 1234.56774902, 0.12345678 )\n"
		"  ( 22345678.00000000, 2234.56787109, 2.12345672 )\n"
		"  ( 32345678.00000000, 3234.56787109, 3.12345672 )\n}",
		mtx0.toString());
}
//------------------------------------------------------------------------------
// Direct3D行列との比較
bool Matrix33Test::d3dEquals(D3DXMATRIX& d3d, Matrix33& mtx){
	if(
		(d3d.m[0][3] != 0.f) || (d3d.m[1][3] != 0.f) ||
		(d3d.m[2][3] != 0.f) || (d3d.m[3][3] != 1.f) ||
		(d3d.m[3][0] != 0.f) || (d3d.m[3][1] != 0.f) ||
		(d3d.m[3][2] != 0.f)){ return false; }
	return(
		(d3d.m[0][0] == mtx.m00) &&
		(d3d.m[0][1] == mtx.m10) &&
		(d3d.m[0][2] == mtx.m20) &&
		(d3d.m[1][0] == mtx.m01) &&
		(d3d.m[1][1] == mtx.m11) &&
		(d3d.m[1][2] == mtx.m21) &&
		(d3d.m[2][0] == mtx.m02) &&
		(d3d.m[2][1] == mtx.m12) &&
		(d3d.m[2][2] == mtx.m22));
}
//------------------------------------------------------------------------------
// Direct3D行列との比較
bool Matrix33Test::d3dEpsilonEquals(
	D3DXMATRIX& d3d, Matrix33& mtx, float epsilon){
	if(
		(Math::abs(d3d.m[0][3]) > epsilon) ||
		(Math::abs(d3d.m[1][3]) > epsilon) ||
		(Math::abs(d3d.m[2][3]) > epsilon) ||
		(Math::abs(d3d.m[3][0]) > epsilon) ||
		(Math::abs(d3d.m[3][1]) > epsilon) ||
		(Math::abs(d3d.m[3][2]) > epsilon) ||
		(Math::abs(d3d.m[3][3] - 1.f) > epsilon)){ return false; }
	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[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[2][0] - mtx.m02) <= epsilon) &&
		(Math::abs(d3d.m[2][1] - mtx.m12) <= epsilon) &&
		(Math::abs(d3d.m[2][2] - mtx.m22) <= epsilon));
}
//------------------------------------------------------------------------------
