12template <
class Type1, 
class Type2, 
class Element>
 
   18    { verbose = 
false; scale=1e3; tolerance = 1e-12; random_init(); }
 
   20  virtual ~MatrixTest () {}
 
   22  virtual void runtest (
unsigned nloops);
 
   32template <
class T, 
class U>
 
   33T max (
const T& a, 
const U& b)
 
   41template <
class Type1, 
class Type2, 
class Element>
 
   42void test_matrix (
const Type1& t1_1, 
const Type1& t1_2, 
const Type2& t2_null,
 
   43                  const Element& p, 
double scale, 
double tolerance, 
bool verbose)
 
   54  std::cerr << 
"\n*************** Testing operator =" << std::endl;
 
   57  std::cerr << 
"Type1 = Type1" << std::endl;
 
   60  if (verbose) std::cerr << 
"Type2 = Type1" << std::endl;
 
   63  if (verbose) std::cerr << 
"Type2 = Type2" << std::endl;
 
   66  if (verbose) std::cerr << 
"Type1 = Type2" << std::endl;
 
   69  if (verbose) std::cerr << 
"Type1 == Type1" << std::endl;
 
   71    throw std::string (
"test_matrix " 
   72                 "Error casting from Type1 to Type2");
 
   74  if (verbose) std::cerr << 
"Type1 == Type2" << std::endl;
 
   76    throw std::string (
"test_matrix " 
   77                 "Error casting from Type1 to Type2");
 
   83    std::cerr << 
"\n*************** Testing operator + and -" << std::endl;
 
   87  if (verbose) std::cerr << 
"Type1 + Type2" << std::endl;
 
   92  if (verbose) std::cerr << 
"Type2 - Type1" << std::endl;
 
   95  if (verbose) std::cerr << 
"Type1 == Type2" << std::endl;
 
   97  if (norm(t1_1 - t2_1)/norm(t2_1) > tolerance)
 
   99    std::cerr << 
"t1_1 = " << t1_1 << 
" != " 
  100         << 
"t2_1 = " << t2_1 << std::endl;
 
  102    throw std::string (
"test_matrix " 
  103                  "Error adding and subtracting Type1 and Type2");
 
  111    std::cerr << 
"\n*************** Testing operator * and / Element"  
  115  random_value (dfactor, scale);
 
  119  if (verbose) std::cerr << 
"Element * Type2" << std::endl;
 
  120  t2_2 = dfactor * t2_1;
 
  122  if (verbose) std::cerr << 
"Type2 / Element" << std::endl;
 
  123  t2_1 = t2_2 / dfactor;
 
  125  if (verbose) std::cerr << 
"Type1 == Type2" << std::endl;
 
  126  if (norm(t2_1 - t1_1)/norm(t2_1) > tolerance)
 
  128    std::cerr << 
"Error Type2=" << t2_1 
 
  129         << 
" * / Element=" << dfactor
 
  130         << 
" != Type1=" << t1_1 << std::endl;
 
  131    throw std::string (
"test_matrix Error in Type2 * / Element");
 
  137  if (verbose) std::cerr << 
"\n*************** Testing operator * Type1" << std::endl;
 
  139  if (verbose) std::cerr << 
"Type1::identity=" << Type1::identity() << std::endl;
 
  141  if (verbose) std::cerr << 
"Type1 * Type1::identity" << std::endl;
 
  142  t2_1 = t1_1 * Type1::identity();
 
  144  if (verbose) std::cerr << 
"Type1 == Type2" << std::endl;
 
  146    throw std::string (
"test_matrix Error Type1 * Type1::identity");
 
  152  if (verbose) std::cerr << 
"\n*************** Testing conjugate" << std::endl;
 
  154  if (verbose) std::cerr << 
"conj (t1_1 * t1_2)" << std::endl;
 
  155  t2_1 = conj (t1_1 * t1_2);
 
  157  if (verbose) std::cerr << 
"conj (t1_1) * conj (t1_2)" << std::endl;
 
  158  t2_2 = conj (t1_1) * conj (t1_2);
 
  160  if (verbose) std::cerr << 
"Type2 == Type2" << std::endl;
 
  161  if (norm(t2_1 - t2_2)/norm(t2_1) > tolerance)
 
  163    std::cerr << 
"1=" << t2_1 << 
"\n2=" << t2_2 << std::endl;
 
  164    throw std::string (
"test_matrix Error Conjugate");
 
  170  if (verbose) std::cerr << 
"\n*************** Testing Hermitian" << std::endl;
 
  175  if (verbose) std::cerr << 
"herm (t2_1 * t2_2)" << std::endl;
 
  176  temp1 = herm (t2_1 * t2_2);
 
  178  if (verbose) std::cerr << 
"herm (t2_2) * herm (t2_1)" << std::endl;
 
  179  temp2 = herm (t2_2) * herm (t2_1);
 
  181  if (verbose) std::cerr << 
"Type2 == Type2" << std::endl;
 
  183  if ( norm(temp2 - temp1)/norm(temp2) > tolerance) {
 
  184    std::cerr << 
"Error Hermitian" 
  187      "\n  herm(M1*M2)=" << temp1 <<
 
  188      "\n  herm(M2)*herm(M1)=" << temp2 << std::endl;
 
  190    throw std::string (
"test_matrix Error Hermitian");
 
  196  if (verbose) std::cerr << 
"\n*************** Testing determinant" << std::endl;
 
  200  if (verbose) std::cerr << 
"det(Type2)" << std::endl;
 
  201  Element det1 (det(t2_1));
 
  203  if (verbose) std::cerr << 
"Type2 /= sqrt(det)" << std::endl;
 
  206  if (verbose) std::cerr << 
"det(Type2)" << std::endl;
 
  207  Element det2 (det(t2_1));
 
  209  if (norm(det2 - one) > tolerance)
 
  210    throw std::string (
"test_matrix " 
  211                 "Error normalizing by square root of determinant"); 
 
  218    std::cerr << 
"\n*************** Testing norm and trace" << std::endl;
 
  222  if (verbose) std::cerr << 
"norm (Type2)" << std::endl;
 
  223  double variance1 = norm(t2_2);
 
  225  if (verbose) std::cerr << 
"herm (Type2)" << std::endl;
 
  226  t2_1 = t2_2*herm(t2_2);
 
  228  if (verbose) std::cerr << 
"trace (Type2)" << std::endl;
 
  229  Element variance2 (trace (t2_1));
 
  231  if ( norm(variance1 - variance2) > tolerance )
 
  233    std::cerr << 
"Q=" << t2_2 << std::endl;
 
  234    std::cerr << 
"herm(Q)=" << herm(t2_2) << std::endl;
 
  235    std::cerr << 
"Q*herm(Q)=" << t2_1 << std::endl;
 
  236    std::cerr << 
"norm(Q) = " << variance1 << std::endl;
 
  237    std::cerr << 
"trace (Q * herm(Q)) = " << variance2 << std::endl;
 
  239    throw std::string (
"test_matrix " 
  240                 "Error norm(Q) != trace (Q * herm(Q))");
 
  246  if (verbose) std::cerr << 
"\n*************** Testing inverse" << std::endl;
 
  248  if (verbose) std::cerr << 
"Type1::inv" << std::endl;
 
  251  if (verbose) std::cerr << 
"Type2 * Type2" << std::endl;
 
  252  t2_1 = Type2(t1_1) * t2_2;
 
  254  double threshold = tolerance * max (norm(t1_1), norm(t2_2));
 
  256  if (verbose) std::cerr << 
"norm (Type2)" << std::endl;
 
  257  variance1 = norm (Type2::identity() - t2_1);
 
  259  if ( variance1 > threshold ) {
 
  260    std::cerr << 
"Error multipying Type1 by its inverse" 
  262      "\n   inv(Q)=" << t2_2 <<
 
  263      "\n   Q*inv(Q)=" << t2_1 << std::endl;
 
  265    throw std::string (
"test_matrix " 
  266                  "Error multipying Type1 by its inverse");
 
  270template <
class Type1, 
class Type2, 
class Element>
 
  271void MatrixTest<Type1, Type2, Element>::runtest (
unsigned nloops)
 
  277    std::cerr << 
"\n*************** Testing constructors" << std::endl;
 
  280    std::cerr << 
"Type1 null construct" << std::endl;
 
  284    std::cerr << 
"Element array (static)" << std::endl;
 
  286  Element random_elements[4];
 
  287  for (
int i=0; i<4; i++)
 
  288    random_value (random_elements[i], scale);
 
  291    std::cerr << 
"Type1 construct from 4 Elements" << std::endl;
 
  292  Type1 t1_1 (random_elements[0], random_elements[1],
 
  293              random_elements[2], random_elements[3]);
 
  296    std::cerr << 
"Type1 construct from Type1" << std::endl;
 
  300    std::cerr << 
"TEST: Type1 == Type1" << std::endl;
 
  302    throw std::string (
"MatrixTest::runtest " 
  303                  "Error in constructing Type1 from Type1");
 
  306    std::cerr << 
"Type1 = Type1" << std::endl;
 
  310    std::cerr << 
"TEST: Type1 == Type1" << std::endl;
 
  312    throw std::string (
"MatrixTest::runtest " 
  313                 "Error setting Type1 equal to Type1");
 
  315  for (
unsigned iloop=0; iloop<nloops; iloop++) {
 
  319    random_vector (t1_1, scale);
 
  320    random_vector (t1_2, scale);
 
  326      test_matrix (t1_1, t1_2, t2_null, null, scale, tolerance, verbose);
 
  328    catch (std::string& error) {
 
  329      std::cerr << 
"MatrixTest::runtest error on loop "<< iloop <<
"/"<< nloops