File: lu_factor.cpp

package info (click to toggle)
cppad 2026.00.00.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,584 kB
  • sloc: cpp: 112,960; sh: 6,146; ansic: 179; python: 71; sed: 12; makefile: 10
file content (109 lines) | stat: -rw-r--r-- 2,915 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------

/*
{xrst_begin lu_factor.cpp}

LuFactor: Example and Test
##########################

{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end lu_factor.cpp}
*/

// BEGIN C++
# include <cstdlib>               // for rand function
# include <cppad/utility/lu_factor.hpp>      // for CppAD::LuFactor
# include <cppad/utility/near_equal.hpp>     // for CppAD::NearEqual
# include <cppad/utility/vector.hpp>  // for CppAD::vector

bool LuFactor(void)
{  bool  ok = true;

# ifndef _MSC_VER
   using std::rand;
   using std::srand;
# endif
   using CppAD::NearEqual;
   double eps99 = 99.0 * std::numeric_limits<double>::epsilon();

   size_t  n = 5;                        // number rows in A
   double  rand_max = double(RAND_MAX);  // maximum rand value
   double  sum;                          // element of L * U
   double  pij;                          // element of permuted A
   size_t  i, j, k;                      // temporary indices

   // A is an n by n matrix
   CppAD::vector<double> A(n*n), LU(n*n), L(n*n), U(n*n);

   // set A equal to an n by n random matrix
   for(i = 0; i < n; i++)
      for(j = 0; j < n; j++)
         A[i * n + j] = rand() / rand_max;

   // pivot vectors
   CppAD::vector<size_t> ip(n);
   CppAD::vector<size_t> jp(n);

   // factor the matrix A
   LU       = A;
   CppAD::LuFactor(ip, jp, LU);

   // check that ip and jp are permutations of the indices 0, ... , n-1
   for(i = 0; i < n; i++)
   {  ok &= (ip[i] < n);
      ok &= (jp[i] < n);
      for(j = 0; j < n; j++)
      {  if( i != j )
         {  ok &= (ip[i] != ip[j]);
            ok &= (jp[i] != jp[j]);
         }
      }
   }

   // Extract L from LU
   for(i = 0; i < n; i++)
   {  // elements along and below the diagonal
      for(j = 0; j <= i; j++)
         L[i * n + j] = LU[ ip[i] * n + jp[j] ];
      // elements above the diagonal
      for(j = i+1; j < n; j++)
         L[i * n + j] = 0.;
   }

   // Extract U from LU
   for(i = 0; i < n; i++)
   {  // elements below the diagonal
      for(j = 0; j < i; j++)
         U[i * n + j] = 0.;
      // elements along the diagonal
      U[i * n + i] = 1.;
      // elements above the diagonal
      for(j = i+1; j < n; j++)
         U[i * n + j] = LU[ ip[i] * n + jp[j] ];
   }

   // Compute L * U
   for(i = 0; i < n; i++)
   {  for(j = 0; j < n; j++)
      {  // compute element (i,j) entry in L * U
         sum = 0.;
         for(k = 0; k < n; k++)
            sum += L[i * n + k] * U[k * n + j];
         // element (i,j) in permuted version of A
         pij  = A[ ip[i] * n + jp[j] ];
         // compare
         ok  &= NearEqual(pij, sum, eps99, eps99);
      }
   }

   return ok;
}

// END C++