File: Eigen.cpp

package info (click to toggle)
freemat 4.2%2Bdfsg1-6
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 142,116 kB
  • sloc: ansic: 126,788; cpp: 62,015; python: 2,080; perl: 1,255; sh: 1,146; yacc: 1,019; lex: 239; makefile: 107
file content (185 lines) | stat: -rw-r--r-- 5,758 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
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Copyright (c) 2009 Samit Basu
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "Math.hpp"
#include "EigenDecompose.hpp"
#include "Algorithms.hpp"

static ArrayVector GenEigFunction(int nargout, const ArrayVector &arg) {
  Array A(arg[0]);
  Array B(arg[1]);
  if (A.isSparse() || B.isSparse())
    throw Exception("eig only defined for full matrices.");  
  if (AnyNotFinite(A) || AnyNotFinite(B))
    throw Exception("eig only defined for matrices with finite entries.");
  if (A.isReferenceType() || B.isReferenceType())
    throw Exception("Cannot apply eigendecomposition to reference types.");
  if (!A.is2D() || !B.is2D())
    throw Exception("Cannot apply eigendecomposition to N-Dimensional arrays.");
  if (!A.isSquare())
    throw Exception("Cannot eigendecompose a non-square matrix.");
  if (!B.isSquare())
    throw Exception("Cannot eigendecompose a non-square matrix.");
  if (A.rows() != B.rows())
    throw Exception("B and A must be the same size when computing a generalized eigendecomposition");

  // Handle the type of A - if it is an integer type, then promote to double
  if (A.dataClass() != B.dataClass())
    throw Exception("B and A must be the same data class when computing a generalized eigendecomposition");

  ArrayVector retval;
  Array V, D;

  if (nargout > 1) {
    if (IsSymmetric(A) && IsSymmetric(B)) {
      if (!GeneralizedEigenDecomposeFullSymmetric(A,B,V,D))
	GeneralizedEigenDecomposeFullGeneral(A,B,V,D);
    } else
      GeneralizedEigenDecomposeFullGeneral(A,B,V,D);
    retval.push_back(V);
    retval.push_back(D);
  } else {
    if (IsSymmetric(A) && IsSymmetric(B)) {
      if (!GeneralizedEigenDecomposeCompactSymmetric(A,B,D))
	GeneralizedEigenDecomposeCompactGeneral(A,B,D);
    } else
      GeneralizedEigenDecomposeCompactGeneral(A,B,D);
    retval.push_back(D);
  }
  return retval;
}


//@@Signature
//function eig EigFunction
//inputs A flag
//outputs V D
//DOCBLOCK transforms_eig
ArrayVector EigFunction(int nargout, const ArrayVector& arg) {
  bool balance;
  if (arg.size() == 0)
    throw Exception("eig function requires at least one argument");
  if (arg.size() == 1)
    balance = true;
  else {
    Array b(arg[1]);
    if (b.isString()) {
      QString b2 = b.asString().toUpper();
      if (b2=="NOBALANCE")
	balance = false;
    }
    else
      return GenEigFunction(nargout, arg);
  }
  Array A(arg[0]);
  A.ensureNotScalarEncoded();
  if (!A.is2D())
    throw Exception("Cannot apply matrix operations to N-Dimensional arrays.");
  if (AnyNotFinite(A))
    throw Exception("eig only defined for matrices with finite entries.");
  ArrayVector retval;
  if (A.isEmpty()) {
    if (nargout > 1) {
      retval.push_back(A);
      retval.push_back(A);
    } else {
      retval.push_back(Array(Double,NTuple(0,1)));
    }
    return retval;
  }
  
  Array V, D;
  if (nargout > 1) {
    if (IsSymmetric(A))
      EigenDecomposeFullSymmetric(A,V,D);
    else
      EigenDecomposeFullGeneral(A,V,D,balance);
    retval.push_back(V);
    retval.push_back(D);
  } else {
    if (IsSymmetric(A))
      EigenDecomposeCompactSymmetric(A,D);
    else
      EigenDecomposeCompactGeneral(A,D,balance);
    retval.push_back(D);
  }
  return retval;
}


//@@Signature
//function eigs EigsFunction
//inputs A k sigma
//outputs V D
//DOCBLOCK sparse_eigs
ArrayVector EigsFunction(int nargout, const ArrayVector& arg) {
  if (arg.size() == 0)
    throw Exception("eigs function requires at least one argument");
  Array A(arg[0]);
  if (!A.isSparse())
    throw Exception("eigs only applies to sparse matrix arguments");
  int k;
  if (!A.isSquare())
    throw Exception("eigs can only be applied to square matrices.");
  if (arg.size() < 2) {
    k = 6;
    if (k >= (int)A.rows())
      k = int(A.rows() - 1);
  } else {
    Array kval(arg[1]);
    k = kval.asInteger();
  }
  if (A.dataClass() != Double) 
    throw Exception("eigs only works on double data class");
  bool shiftFlag;
  QString whichflag;
  double sigma[2];
  if (arg.size() < 3) {
    shiftFlag = false;
    whichflag = "LM";
  } else {
    Array S(arg[2]);
    if (S.isString()) {
      shiftFlag = false;
      QString stxt = S.asString().toUpper();
      if ((stxt == "LM") || (stxt == "SM") || (stxt == "LA") || (stxt == "SA") ||
	  (stxt == "BE") || (stxt == "LR") || (stxt == "SR") || (stxt == "LI") ||
	  (stxt == "SI"))
	whichflag = stxt;
      else
	throw Exception("Unrecognized option for sigma - it must be either 'lm', 'sm', 'la', 'sa', 'be', 'lr', 'sr', 'li', or 'si'");
    } else {
      if (!S.isScalar())
	throw Exception("shift parameter sigma must be a scalar");
      if (S.dataClass() != Double) throw Exception("shift parameter must be a double dataclass");
      if (!S.allReal()) {
	sigma[0] = S.constRealScalar<double>();
	sigma[1] = S.constImagScalar<double>();
      } else {
	sigma[0] = S.constRealScalar<double>();
	sigma[1] = 0;
      }
      shiftFlag = true;
    }
  }
  if (!shiftFlag)
    return SparseEigDecompose(nargout,A,k,whichflag);
  else 
    return SparseEigDecomposeShifted(nargout,A,k,sigma);
}