tensor-0.1.0
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
svd_d.cc
1 // -*- mode: c++; fill-column: 80; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 /*
3  Copyright (c) 2010 Juan Jose Garcia Ripoll
4 
5  Tensor is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published
7  by the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Library General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <tensor/tensor.h>
21 #include <tensor/tensor_lapack.h>
22 #include <tensor/linalg.h>
23 
24 namespace linalg {
25 
26  using namespace lapack;
27 
31  bool accurate_svd = 0;
32 
49  RTensor
50  svd(RTensor A, RTensor *U, RTensor *VT, bool economic)
51  {
52  /*
53  if (accurate_svd) {
54  return block_svd(A, U, VT, economic);
55  }
56  */
57 
58  assert(A.rows() > 0);
59  assert(A.columns() > 0);
60  assert(A.rank() == 2);
61 
62  integer m = A.rows();
63  integer n = A.columns();
64  integer k = std::min(m, n);
65  integer lwork, ldu, lda, ldv, info;
66  RTensor output(k);
67  double *work, *u, *v;
68  double *a = tensor_pointer(A), *s = tensor_pointer(output), foo;
69  char jobv[1], jobu[1];
70 
71  if (U) {
72  *U = RTensor(m, economic? k : m);
73  u = tensor_pointer(*U);
74  jobu[0] = economic? 'S' : 'A';
75  ldu = m;
76  } else {
77  jobu[0] = 'N';
78  u = &foo;
79  ldu = 1;
80  }
81  if (VT) {
82  (*VT) = RTensor(economic? k : n, n);
83  v = tensor_pointer(*VT);
84  jobv[0] = economic? 'S' : 'A';
85  ldv = economic? k : n;
86  } else {
87  jobv[0] = 'N';
88  v = &foo;
89  ldv = 1;
90  }
91  lda = m;
92 #ifdef TENSOR_USE_ACML
93  dgesvd(*jobu, *jobv, m, n, a, lda, s, u, ldu, v, ldv, &info);
94 #else
95  lwork = -1;
96  work = &foo;
97  F77NAME(dgesvd)(jobu, jobv, &m, &n, a, &lda, s, u, &ldu, v, &ldv,
98  work, &lwork, &info);
99  lwork = (int)work[0];
100  work = new double[lwork];
101  F77NAME(dgesvd)(jobu, jobv, &m, &n, a, &lda, s, u, &ldu, v, &ldv,
102  work, &lwork, &info);
103  delete[] work;
104 #endif
105  return output;
106  }
107 
108 } // namespace linalg
int rank() const
Number of Tensor indices.
Definition: tensor.h:119
index columns() const
Query the size of 2nd index.
Definition: tensor.h:137
index rows() const
Query then size of 1st index.
Definition: tensor.h:139
Real Tensor with elements of type "double".
Definition: tensor.h:349
RTensor svd(RTensor A, RTensor *pU=0, RTensor *pVT=0, bool economic=0)
Singular value decomposition of a real matrix.
Definition: svd_d.cc:50