// © Copyright 2008 Владимир Фролов
#ifndef MGML_GUARDIAN
	#include "MGML.h"
#endif

 void MGML_TESTS::test_all(std::ostream& out)
 {
	test_mgml_types_sizes(out);
	test_mgml_mat_vec_op(out);
	test_operators(out);
	test_mgml_vec_func(out);
	test_kd_tree(out);
 }	

 void MGML_TESTS::test_mgml_types_sizes(std::ostream& out)
 {
	 bool res = false;
	 int size;
	
	 out << "Tests for sizeof some types haven't been changed" << std::endl;

	 size = sizeof(MGML_MATH::VECTOR<3,float>);
	 out << "VECTOR<3,float>: " << size << " " << ((size==12) ? "PASSED" : "FAILED") << std::endl;

	 size = sizeof(MGML_MATH::VECTOR<4,float>);
	 out << "VECTOR<4,float>: " << size << " " << ((size==16) ? "PASSED" : "FAILED") << std::endl;

	 size = sizeof(MGML_MATH::SPHERE<4,float>);
	 out << "SPHERE<4,float>: " << size << " " << ((size==32) ? "PASSED" : "FAILED") << std::endl;

	 size = sizeof(MGML_MATH::RAY<4,float>);
	 out << "RAY<4,float>:    " << size << " " << ((size==32) ? "PASSED" : "FAILED") << std::endl;

	// size = sizeof(MGML_MATH::Packed_Sphere);
	// out << "Packed_Sphere:   " << size << " " << ((size==16) ? "PASSED" : "FAILED") << std::endl;

	 out <<  std::endl;
 }

 void MGML_TESTS::test_mgml_vec_func(std::ostream& out)
 {
	 typedef MGML_MATH::VECTOR<4,float> _vec4f;
	 typedef MGML_MATH::VECTOR<3,float> _vec3f;

	 _vec4f v1(1,2,3,4);
	 _vec3f v31(1,2,3);

	 out << "Tests for functions-members" << std::endl;

	 out << "lenSquare4:         ";
	 if(abs(v1.lenSquare() - 14.0f) < MGML_MATH::EPSILON_E12 )
		out << "PASSED" << std::endl;
	 else							   
		out << "FAILED" << std::endl;

	 out << "lenSquare3:         ";
	 if(abs(v31.lenSquare() - 14.0f) < MGML_MATH::EPSILON_E12 )
		out << "PASSED" << std::endl;
	 else							   
		out << "FAILED" << std::endl;


	 out << "len4:               ";
	 if(abs(v1.len() - sqrt(14.0f)) < MGML_MATH::EPSILON_E12 )
		out << "PASSED" << std::endl;
	 else							   
		out << "FAILED" << std::endl;

	 out << "len3:               ";
	 if(abs(v31.len() - sqrt(14.0f)) < MGML_MATH::EPSILON_E12 )
		out << "PASSED" << std::endl;
	 else							   
		out << "FAILED" << std::endl;

	 out <<  std::endl;
 }
 
 void MGML_TESTS::test_mgml_mat_vec_op(std::ostream& out)
 {
	 typedef MGML_MATH::VECTOR<4,float> _vec4f;
	 typedef MGML_MATH::VECTOR<3,float> _vec3f;

	 MGML_MATH::VECTOR<3,float> v3(1,2,3),v31;
	 MGML_MATH::VECTOR<4,float> v4(1,2,3,4),v41;
	 MGML_MATH::MATRIX<4,4,float> m(1,2,3,4,
									5,6,7,8,
									9,10,11,12,
									13,14,15,16);


	 out << "Tests for matrix and matrix-vector mults" << std::endl;

	 out << "operator==(vec):    ";
	 if( (_vec4f(90,100,110,120.01) !=_vec4f(90,100,110,120)) &&
		 (_vec4f(1,2.5,3,4.01) ==_vec4f(1,2.5,3,4.01)))      out << "PASSED" << std::endl;
	 else													 out << "FAILED" << std::endl;

	 out << "vec4f*m:            ";
	 v41 = v4*m;
	 if( v41 ==_vec4f(90,100,110,120)) out << "PASSED" << std::endl;
	 else							   out << "FAILED" << std::endl;

	 out << "m*vec4f:            ";
	 v41 = m*v4; 
	 if( v41 ==_vec4f(30,70,110,150))  out << "PASSED" << std::endl;
	 else							   out << "FAILED" << std::endl;


	 m = MGML_MATH::MATRIX<4,4,float>(1,2,3,0,
									                  4,5,6,0,
									                  7,8,9,0,
									                  0,0,0,1);
	 out << "vec3f*m:            ";
	 v31 = v3*m; 
	 if( v31 ==_vec3f(30,36,42))  out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;
	

	 out << "m*vec3f:            ";
	 v31 = m*v3; 
	 if( v31 ==_vec3f(14,32,50))   out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;

	 out <<  std::endl;
 }

 void MGML_TESTS::test_operators(std::ostream& out)
 {
	 typedef MGML_MATH::VECTOR<2,float> _vec2f;
	 typedef MGML_MATH::VECTOR<4,float> _vec4f;
	 typedef MGML_MATH::VECTOR<3,double> _vec3d;
	 
	  _vec2f t;
	  _vec4f bar(1,2,3,4),va(1,2,3,4),vb(5,6,7,8),vc;
	  _vec2f A,B,C;
	  _vec3d v3a(1,2,3),v3b(5,6,7),v3c;

	 out << "VECTOR operators tests: " << std::endl;

	 v3c = v3a + v3b;
	 out << "vec3(+) :           ";
	 if(v3c == _vec3d(6,8,10))	  out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;

	 v3c = v3a - v3b;
	 out << "vec3(-) :           ";
	 if(v3c == _vec3d(-4,-4,-4))  out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;

	 A.set(1,0);  B.set(1,0);  C.set(1,1);
	 t = A*bar[0] + B*bar[1] + C*bar[2];
	 out << "vec(+,*):           ";
	 if(t == _vec2f(6,3))		  out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;

	 out << "dot3:               ";
	 double d3d = v3a*v3b;
	 if(abs(d3d - 38) <  MGML_MATH::EPSILON_E12)out << "PASSED" << std::endl;
	 else									    out << "FAILED" << std::endl;

	 out << "cross3:             ";
	 v3c = v3a ->* v3b;
	 if( (v3c.x() + 4 < MGML_MATH::EPSILON_E12) &&
		 (v3c.y() - 8 < MGML_MATH::EPSILON_E12) &&
		 (v3c.z() + 4 < MGML_MATH::EPSILON_E12) ) out << "PASSED" << std::endl;
	 else										out << "FAILED" << std::endl; 

	 vc = va + vb;
	 out << "vec4(+)(SSE):       ";
	 if(vc == _vec4f(6,8,10,12))  out << "PASSED" << std::endl;
	 else					      out << "FAILED" << std::endl;

	 vc = va - vb;
	 out << "vec4(-)(SSE):       ";
	 if(vc == _vec4f(-4,-4,-4,-4)) out << "PASSED" << std::endl;
	 else					       out << "FAILED" << std::endl;

	 vc = va/2.0f;
	 out << "vec4(/)(SSE):       ";
	 if(vc == _vec4f(0.5,1,1.5,2)) out << "PASSED" << std::endl;
	 else					       out << "FAILED" << std::endl;


	 out << "dot3(SSE):          ";
	 float d4f = dot3(va,vb);
	 if(abs(d4f - 38) <  MGML_MATH::EPSILON_E12)out << "PASSED" << std::endl;
	 else									    out << "FAILED" << std::endl;

	 out << "cross3(SSE):        ";
	 vc = cross3(va,vb);
	 if( (abs(vc.x() + 4) < MGML_MATH::EPSILON_E12) &&
		 (abs(vc.y() - 8) < MGML_MATH::EPSILON_E12) &&
		 (abs(vc.z() + 4) < MGML_MATH::EPSILON_E12) )  out << "PASSED" << std::endl;
	 else											   out << "FAILED" << std::endl; 



	  out <<  std::endl;
 }

  void MGML_TESTS::test_kd_tree(std::ostream& out)
  {
//	  using namespace RAYTR;

//	  out << "Tests of kd-tree" << std::endl;
	  
//	  int size = sizeof(KdTreeNode);
//	  out << "sz(KdTreeNode)  : " << size << " " << ((size==8) ? "PASSED" : "FAILED") << std::endl;

//	  size = sizeof(KdTreeNode*);
//	  out << "sz(KdTreeNode*) : " << size << " " << ((size==4) ? "PASSED" : "FAILED") << std::endl;

	  //KdTreeNode node,node2;
	  //node.setAxis(0);
	  //node.setSplitPos(0.5f);
	  //node.setLeft(&node2);
	  //node.setLeaf(false);

	  //node2.setLeaf(true);
	  //node2.setAxis(1);
	  //node2.setSplitPos(0.6f);
	  //node2.setLeft(0);

	  //KdTreeNode* next = node.getLeft();

	   //out << "KdTreeNode:         ";
	  //if(next->Leaf() && 
		//(fabs(next->getSplitPos()-0.6f) < EPSILON) &&
		//(next->getAxis() == 1)	)				  
		  // out << "PASSED" << std::endl;
	  //else out << "FAILED" << std::endl;

	  //out << KdTreeNode::MAX_NUM_KD_TREE_NODES	<< std::endl;

	  out << std::endl;
  }
