MyraMath
cpotrf


Source: tests/dense/potrf.cpp

1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
11 // Containers.
13 #include <myramath/dense/Matrix.h>
16 
17 // Data generators.
18 #include <myramath/dense/triu.h>
19 #include <myramath/dense/tril.h>
20 #include <myramath/dense/diag.h>
21 
22 // Algorithms.
23 #include <myramath/dense/potrf.h>
24 #include <myramath/dense/gemm.h>
26 
27 // Reporting.
28 #include <myramath/utility/Timer.h>
29 #include <tests/myratest.h>
30 
31 using namespace myra;
32 
33 namespace {
34 
35 template<class Number> void test(int N, typename ReflectPrecision<Number>::type tolerance)
36  {
37  typedef typename ReflectPrecision<Number>::type Precision;
38  myra::out() << typestring<Number>() << std::endl;
39 
40  // Construct random symmetric positive definite A.
41  auto G = Matrix<Number>::random(N,N);
42  auto A = gemm(G,G,'H') + 10*Matrix<Number>::identity(N);
43 
44  // Check potrf('L','R'): it factors A = L*L', touching only tril(A)
45  {
46  auto L = A;
47  Timer timer;
48  potrf_inplace('L','R',L);
49  double t = timer.elapsed_time();
50  // Verify that triu(L) is untouched / still matches triu(A)
51  Precision error1 = frobenius( (triu(L)-diag(L).make_Matrix()) - (triu(A)-diag(A).make_Matrix()) ) / frobenius(triu(A)-diag(A).make_Matrix());
52  myra::out() << " |triu(L)-triu(A)| = " << error1 << std::endl;
53  REQUIRE(error1 < tolerance);
54  // Verify that L*L' = A
55  L = tril(L);
56  Precision error2 = frobenius(gemm(L,L,'H')-A) / frobenius(A);
57  myra::out() << " |L*L'-A| = " << error2 << " (" << t << " sec)" << std::endl;
58  REQUIRE(error2 < tolerance);
59  }
60 
61  // Check potrf('L','L'): it factors A = L'*L, touching only tril(A)
62  {
63  auto L = A;
64  Timer timer;
65  potrf_inplace('L','L',L);
66  double t = timer.elapsed_time();
67  // Verify that triu(L) is untouched / still matches triu(A)
68  Precision error1 = frobenius( (triu(L)-diag(L).make_Matrix()) - (triu(A)-diag(A).make_Matrix()) ) / frobenius(triu(A)-diag(A).make_Matrix());
69  myra::out() << " |triu(L)-triu(A)| = " << error1 << std::endl;
70  REQUIRE(error1 < tolerance);
71  // Verify that L*L' = A
72  L = tril(L);
73  Precision error2 = frobenius(gemm(L,'H',L)-A) / frobenius(A);
74  myra::out() << " |L'*L-A| = " << error2 << " (" << t << " sec)" << std::endl;
75  REQUIRE(error2 < tolerance);
76  }
77 
78  // Check potrf('U','R'): it factors A = U*U', touching only triu(A)
79  {
80  auto U = A;
81  Timer timer;
82  potrf_inplace('U','R',U);
83  double t = timer.elapsed_time();
84  // Verify that tril(U) is untouched / still matches tril(A)
85  Precision error1 = frobenius( (tril(U)-diag(U).make_Matrix()) - (tril(A)-diag(A).make_Matrix()) ) / frobenius(tril(A)-diag(A).make_Matrix());
86  myra::out() << " |tril(U)-tril(A)| = " << error1 << std::endl;
87  REQUIRE(error1 < tolerance);
88  // Verify that U*U' = A
89  U = triu(U);
90  Precision error2 = frobenius(gemm(U,U,'H')-A) / frobenius(A);
91  myra::out() << " |U*U'-A| = " << error2 << " (" << t << " sec)" << std::endl;
92  REQUIRE(error2 < tolerance);
93  }
94 
95  // Check potrf('U','L'): it factors A = U'*U, touching only triu(A)
96  {
97  auto U = A;
98  Timer timer;
99  potrf_inplace('U','L',U);
100  double t = timer.elapsed_time();
101  // Verify that tril(U) is untouched / still matches tril(A)
102  Precision error1 = frobenius( (tril(U)-diag(U).make_Matrix()) - (tril(A)-diag(A).make_Matrix()) ) / frobenius(tril(A)-diag(A).make_Matrix());
103  myra::out() << " |tril(U)-tril(A)| = " << error1 << std::endl;
104  REQUIRE(error1 < tolerance);
105  // Verify that U'*U = A
106  U = triu(U);
107  Precision error2 = frobenius(gemm(U,'H',U)-A) / frobenius(A);
108  myra::out() << " |U'*U-A| = " << error2 << " (" << t << " sec)" << std::endl;
109  REQUIRE(error2 < tolerance);
110  }
111  }
112 
113 } // namespace
114 
115 ADD_TEST("spotrf","[dense][lapack]")
116  { test<NumberS>(128,1.0e-4f); }
117 
118 ADD_TEST("dpotrf","[dense][lapack]")
119  { test<NumberD>(128,1.0e-9); }
120 
121 ADD_TEST("cpotrf","[dense][lapack]")
122  { test<NumberC>(128,1.0e-4f); }
123 
124 ADD_TEST("zpotrf","[dense][lapack]")
125  { test<NumberZ>(128,1.0e-9); }
126 
Cholesky factorization routines for positive definite matrices.
Interface class for representing subranges of dense Matrix&#39;s.
Routines for computing Frobenius norms of various algebraic containers.
static Matrix< Number > random(int I, int J)
Generates a random Matrix of specified size.
Definition: Matrix.cpp:353
Simplistic timing class, might dispatch to platform specific timers depending upon environment...
Definition: syntax.dox:1
Measures elapsed time.
Definition: Timer.h:19
Returns the lower triangle of a dense Matrix.
Returns the upper triangle of a dense Matrix.
Various utility functions/classes related to scalar Number types.
static Matrix< Number > identity(int IJ)
Generates an identity Matrix of specified size.
Definition: Matrix.cpp:349
General purpose dense matrix container, O(i*j) storage.
Reflects Precision trait for a Number, scalar Number types should specialize it.
Definition: Number.h:33
Returns the diagonal of a dense Matrix or LowerMatrix.
Container for a diagonal matrix, O(n) storage. Used by SVD, row/column scaling, etc.
Variety of routines all for dense Matrix*Matrix multiplies. Delegates to the BLAS.
double elapsed_time() const
Returns elapsed time in seconds since last call to reset()
Definition: Timer.cpp:18


Results: [PASS]

std::complex<float>
|triu(L)-triu(A)| = 0
|L*L'-A| = 1.22153e-07 (0 sec)
|triu(L)-triu(A)| = 0
|L'*L-A| = 1.68518e-07 (0 sec)
|tril(U)-tril(A)| = 0
|U*U'-A| = 1.68872e-07 (0.001 sec)
|tril(U)-tril(A)| = 0
|U'*U-A| = 7.54459e-08 (0 sec)


Go back to Summary of /test programs.