~ubuntu-branches/ubuntu/utopic/mricron/utopic

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{ ******************************************************************
  QR decomposition

  Ref.: 'Matrix Computations' by Golub & Van Loan
         Pascal implementation contributed by Mark Vaughan
  ****************************************************************** }

unit uqr;

interface

uses
  utypes;

procedure QR_Decomp(A            : PMatrix;
                    Lb, Ub1, Ub2 : Integer;
                    R            : PMatrix);
{ ------------------------------------------------------------------
  QR decomposition. Factors the matrix A (n x m, with n >= m) as a
  product Q * R where Q is a (n x m) column-orthogonal matrix, and R
  a (m x m) upper triangular matrix. This routine is used in
  conjunction with QR_Solve to solve a system of equations.
  ------------------------------------------------------------------
  Input parameters : A   = matrix
                     Lb  = index of first matrix element
                     Ub1 = index of last matrix element in 1st dim.
                     Ub2 = index of last matrix element in 2nd dim.
  ------------------------------------------------------------------
  Output parameter : A   = contains the elements of Q
                     R   = upper triangular matrix
  ------------------------------------------------------------------
  Possible results : MatOk
                     MatErrDim
                     MatSing
  ------------------------------------------------------------------
  NB : This procedure destroys the original matrix A
  ------------------------------------------------------------------ }

procedure QR_Solve(Q, R         : PMatrix;
                   B            : PVector;
                   Lb, Ub1, Ub2 : Integer;
                   X            : PVector);
{ ------------------------------------------------------------------
  Solves a system of equations by the QR decomposition,
  after the matrix has been transformed by QR_Decomp.
  ------------------------------------------------------------------
  Input parameters : Q, R         = matrices from QR_Decomp
                     B            = constant vector
                     Lb, Ub1, Ub2 = as in QR_Decomp
  ------------------------------------------------------------------
  Output parameter : X            = solution vector
  ------------------------------------------------------------------ }

implementation

procedure QR_Decomp(A            : PMatrix;
                    Lb, Ub1, Ub2 : Integer;
                    R            : PMatrix);
  var
    I, J, K : Integer;
    Sum     : Float;
  begin
    if Ub2 > Ub1 then
      begin
        SetErrCode(MatErrDim);
        Exit
      end;

    for K := Lb to Ub2 do
      begin
        { Compute the "k"th diagonal entry in R }
        Sum := 0.0;
        for I := Lb to Ub1 do
          Sum := Sum + Sqr(A^[I]^[K]);

        if Sum = 0.0 then
          begin
            SetErrCode(MatSing);
            Exit;
          end;

        R^[K]^[K] := Sqrt(Sum);

        { Divide the entries in the "k"th column of A by the computed "k"th }
        { diagonal element of R.  this begins the process of overwriting A  }
        { with Q . . .                                                      }
        for I := Lb to Ub1 do
          A^[I]^[K] := A^[I]^[K] / R^[K]^[K];

        for J := (K + 1) to Ub2 do
          begin
            { Complete the remainder of the row entries in R }
            Sum := 0.0;
            for I := Lb to Ub1 do
              Sum := Sum + A^[I]^[K] * A^[I]^[J];
            R^[K]^[J] := Sum;

            { Update the column entries of the Q/A matrix }
            for I := Lb to Ub1 do
              A^[I]^[J] := A^[I]^[J] - A^[I]^[K] * R^[K]^[J];
          end;
      end;

    SetErrCode(MatOk);
  end;

procedure QR_Solve(Q, R         : PMatrix;
                   B            : PVector;
                   Lb, Ub1, Ub2 : Integer;
                   X            : PVector);
  var
    I, J : Integer;
    Sum  : Float;
  begin
    { Form Q'B and store the result in X }
    for J := Lb to Ub2 do
      begin
        X^[J] := 0.0;
        for I := Lb to Ub1 do
          X^[J] := X^[J] + Q^[I]^[J] * B^[I];
      end;

    { Update X with the solution vector }
    X^[Ub2] := X^[Ub2] / R^[Ub2]^[Ub2];
    for I := (Ub2 - 1) downto Lb do
      begin
        Sum := 0.0;
        for J := (I + 1) to Ub2 do
          Sum := Sum + R^[I]^[J] * X^[J];
        X^[I] := (X^[I] - Sum) / R^[I]^[I];
      end;
  end;

end.