blob: 7620f0a3899b979f671936e77e741bf7c4c76508 [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#include "common.h"
11
12// y = alpha*A*x + beta*y
Austin Schuh189376f2018-12-20 22:11:15 +110013int EIGEN_BLAS_FUNC(symv) (const char *uplo, const int *n, const RealScalar *palpha, const RealScalar *pa, const int *lda,
14 const RealScalar *px, const int *incx, const RealScalar *pbeta, RealScalar *py, const int *incy)
Brian Silverman72890c22015-09-19 14:37:37 -040015{
Austin Schuh189376f2018-12-20 22:11:15 +110016 typedef void (*functype)(int, const Scalar*, int, const Scalar*, Scalar*, Scalar);
17 static const functype func[2] = {
18 // array index: UP
19 (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Upper,false,false>::run),
20 // array index: LO
21 (internal::selfadjoint_matrix_vector_product<Scalar,int,ColMajor,Lower,false,false>::run),
22 };
Brian Silverman72890c22015-09-19 14:37:37 -040023
Austin Schuh189376f2018-12-20 22:11:15 +110024 const Scalar* a = reinterpret_cast<const Scalar*>(pa);
25 const Scalar* x = reinterpret_cast<const Scalar*>(px);
Brian Silverman72890c22015-09-19 14:37:37 -040026 Scalar* y = reinterpret_cast<Scalar*>(py);
Austin Schuh189376f2018-12-20 22:11:15 +110027 Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
28 Scalar beta = *reinterpret_cast<const Scalar*>(pbeta);
Brian Silverman72890c22015-09-19 14:37:37 -040029
30 // check arguments
31 int info = 0;
32 if(UPLO(*uplo)==INVALID) info = 1;
33 else if(*n<0) info = 2;
34 else if(*lda<std::max(1,*n)) info = 5;
35 else if(*incx==0) info = 7;
36 else if(*incy==0) info = 10;
37 if(info)
38 return xerbla_(SCALAR_SUFFIX_UP"SYMV ",&info,6);
39
40 if(*n==0)
41 return 0;
42
Austin Schuh189376f2018-12-20 22:11:15 +110043 const Scalar* actual_x = get_compact_vector(x,*n,*incx);
Brian Silverman72890c22015-09-19 14:37:37 -040044 Scalar* actual_y = get_compact_vector(y,*n,*incy);
45
46 if(beta!=Scalar(1))
47 {
Austin Schuh189376f2018-12-20 22:11:15 +110048 if(beta==Scalar(0)) make_vector(actual_y, *n).setZero();
49 else make_vector(actual_y, *n) *= beta;
Brian Silverman72890c22015-09-19 14:37:37 -040050 }
51
52 int code = UPLO(*uplo);
53 if(code>=2 || func[code]==0)
54 return 0;
55
Austin Schuh189376f2018-12-20 22:11:15 +110056 func[code](*n, a, *lda, actual_x, actual_y, alpha);
Brian Silverman72890c22015-09-19 14:37:37 -040057
58 if(actual_x!=x) delete[] actual_x;
59 if(actual_y!=y) delete[] copy_back(actual_y,y,*n,*incy);
60
61 return 1;
62}
63
64// C := alpha*x*x' + C
Austin Schuh189376f2018-12-20 22:11:15 +110065int EIGEN_BLAS_FUNC(syr)(const char *uplo, const int *n, const RealScalar *palpha, const RealScalar *px, const int *incx, RealScalar *pc, const int *ldc)
Brian Silverman72890c22015-09-19 14:37:37 -040066{
67
Brian Silverman72890c22015-09-19 14:37:37 -040068 typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, const Scalar&);
Austin Schuh189376f2018-12-20 22:11:15 +110069 static const functype func[2] = {
70 // array index: UP
71 (selfadjoint_rank1_update<Scalar,int,ColMajor,Upper,false,Conj>::run),
72 // array index: LO
73 (selfadjoint_rank1_update<Scalar,int,ColMajor,Lower,false,Conj>::run),
74 };
Brian Silverman72890c22015-09-19 14:37:37 -040075
Austin Schuh189376f2018-12-20 22:11:15 +110076 const Scalar* x = reinterpret_cast<const Scalar*>(px);
Brian Silverman72890c22015-09-19 14:37:37 -040077 Scalar* c = reinterpret_cast<Scalar*>(pc);
Austin Schuh189376f2018-12-20 22:11:15 +110078 Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
Brian Silverman72890c22015-09-19 14:37:37 -040079
80 int info = 0;
81 if(UPLO(*uplo)==INVALID) info = 1;
82 else if(*n<0) info = 2;
83 else if(*incx==0) info = 5;
84 else if(*ldc<std::max(1,*n)) info = 7;
85 if(info)
86 return xerbla_(SCALAR_SUFFIX_UP"SYR ",&info,6);
87
88 if(*n==0 || alpha==Scalar(0)) return 1;
89
90 // if the increment is not 1, let's copy it to a temporary vector to enable vectorization
Austin Schuh189376f2018-12-20 22:11:15 +110091 const Scalar* x_cpy = get_compact_vector(x,*n,*incx);
Brian Silverman72890c22015-09-19 14:37:37 -040092
93 int code = UPLO(*uplo);
94 if(code>=2 || func[code]==0)
95 return 0;
96
97 func[code](*n, c, *ldc, x_cpy, x_cpy, alpha);
98
99 if(x_cpy!=x) delete[] x_cpy;
100
101 return 1;
102}
103
104// C := alpha*x*y' + alpha*y*x' + C
Austin Schuh189376f2018-12-20 22:11:15 +1100105int EIGEN_BLAS_FUNC(syr2)(const char *uplo, const int *n, const RealScalar *palpha, const RealScalar *px, const int *incx, const RealScalar *py, const int *incy, RealScalar *pc, const int *ldc)
Brian Silverman72890c22015-09-19 14:37:37 -0400106{
Brian Silverman72890c22015-09-19 14:37:37 -0400107 typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, Scalar);
Austin Schuh189376f2018-12-20 22:11:15 +1100108 static const functype func[2] = {
109 // array index: UP
110 (internal::rank2_update_selector<Scalar,int,Upper>::run),
111 // array index: LO
112 (internal::rank2_update_selector<Scalar,int,Lower>::run),
113 };
Brian Silverman72890c22015-09-19 14:37:37 -0400114
Austin Schuh189376f2018-12-20 22:11:15 +1100115 const Scalar* x = reinterpret_cast<const Scalar*>(px);
116 const Scalar* y = reinterpret_cast<const Scalar*>(py);
Brian Silverman72890c22015-09-19 14:37:37 -0400117 Scalar* c = reinterpret_cast<Scalar*>(pc);
Austin Schuh189376f2018-12-20 22:11:15 +1100118 Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
Brian Silverman72890c22015-09-19 14:37:37 -0400119
120 int info = 0;
121 if(UPLO(*uplo)==INVALID) info = 1;
122 else if(*n<0) info = 2;
123 else if(*incx==0) info = 5;
124 else if(*incy==0) info = 7;
125 else if(*ldc<std::max(1,*n)) info = 9;
126 if(info)
127 return xerbla_(SCALAR_SUFFIX_UP"SYR2 ",&info,6);
128
129 if(alpha==Scalar(0))
130 return 1;
131
Austin Schuh189376f2018-12-20 22:11:15 +1100132 const Scalar* x_cpy = get_compact_vector(x,*n,*incx);
133 const Scalar* y_cpy = get_compact_vector(y,*n,*incy);
134
Brian Silverman72890c22015-09-19 14:37:37 -0400135 int code = UPLO(*uplo);
136 if(code>=2 || func[code]==0)
137 return 0;
138
139 func[code](*n, c, *ldc, x_cpy, y_cpy, alpha);
140
141 if(x_cpy!=x) delete[] x_cpy;
142 if(y_cpy!=y) delete[] y_cpy;
143
144// int code = UPLO(*uplo);
145// if(code>=2 || func[code]==0)
146// return 0;
147
148// func[code](*n, a, *inca, b, *incb, c, *ldc, alpha);
149 return 1;
150}
151
152/** DSBMV performs the matrix-vector operation
153 *
154 * y := alpha*A*x + beta*y,
155 *
156 * where alpha and beta are scalars, x and y are n element vectors and
157 * A is an n by n symmetric band matrix, with k super-diagonals.
158 */
159// int EIGEN_BLAS_FUNC(sbmv)( char *uplo, int *n, int *k, RealScalar *alpha, RealScalar *a, int *lda,
160// RealScalar *x, int *incx, RealScalar *beta, RealScalar *y, int *incy)
161// {
162// return 1;
163// }
164
165
166/** DSPMV performs the matrix-vector operation
167 *
168 * y := alpha*A*x + beta*y,
169 *
170 * where alpha and beta are scalars, x and y are n element vectors and
171 * A is an n by n symmetric matrix, supplied in packed form.
172 *
173 */
174// int EIGEN_BLAS_FUNC(spmv)(char *uplo, int *n, RealScalar *alpha, RealScalar *ap, RealScalar *x, int *incx, RealScalar *beta, RealScalar *y, int *incy)
175// {
176// return 1;
177// }
178
179/** DSPR performs the symmetric rank 1 operation
180 *
181 * A := alpha*x*x' + A,
182 *
183 * where alpha is a real scalar, x is an n element vector and A is an
184 * n by n symmetric matrix, supplied in packed form.
185 */
186int EIGEN_BLAS_FUNC(spr)(char *uplo, int *n, Scalar *palpha, Scalar *px, int *incx, Scalar *pap)
187{
188 typedef void (*functype)(int, Scalar*, const Scalar*, Scalar);
Austin Schuh189376f2018-12-20 22:11:15 +1100189 static const functype func[2] = {
190 // array index: UP
191 (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Upper,false,false>::run),
192 // array index: LO
193 (internal::selfadjoint_packed_rank1_update<Scalar,int,ColMajor,Lower,false,false>::run),
194 };
Brian Silverman72890c22015-09-19 14:37:37 -0400195
196 Scalar* x = reinterpret_cast<Scalar*>(px);
197 Scalar* ap = reinterpret_cast<Scalar*>(pap);
198 Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
199
200 int info = 0;
201 if(UPLO(*uplo)==INVALID) info = 1;
202 else if(*n<0) info = 2;
203 else if(*incx==0) info = 5;
204 if(info)
205 return xerbla_(SCALAR_SUFFIX_UP"SPR ",&info,6);
206
207 if(alpha==Scalar(0))
208 return 1;
209
210 Scalar* x_cpy = get_compact_vector(x, *n, *incx);
211
212 int code = UPLO(*uplo);
213 if(code>=2 || func[code]==0)
214 return 0;
215
216 func[code](*n, ap, x_cpy, alpha);
217
218 if(x_cpy!=x) delete[] x_cpy;
219
220 return 1;
221}
222
223/** DSPR2 performs the symmetric rank 2 operation
224 *
225 * A := alpha*x*y' + alpha*y*x' + A,
226 *
227 * where alpha is a scalar, x and y are n element vectors and A is an
228 * n by n symmetric matrix, supplied in packed form.
229 */
230int EIGEN_BLAS_FUNC(spr2)(char *uplo, int *n, RealScalar *palpha, RealScalar *px, int *incx, RealScalar *py, int *incy, RealScalar *pap)
231{
232 typedef void (*functype)(int, Scalar*, const Scalar*, const Scalar*, Scalar);
Austin Schuh189376f2018-12-20 22:11:15 +1100233 static const functype func[2] = {
234 // array index: UP
235 (internal::packed_rank2_update_selector<Scalar,int,Upper>::run),
236 // array index: LO
237 (internal::packed_rank2_update_selector<Scalar,int,Lower>::run),
238 };
Brian Silverman72890c22015-09-19 14:37:37 -0400239
240 Scalar* x = reinterpret_cast<Scalar*>(px);
241 Scalar* y = reinterpret_cast<Scalar*>(py);
242 Scalar* ap = reinterpret_cast<Scalar*>(pap);
243 Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
244
245 int info = 0;
246 if(UPLO(*uplo)==INVALID) info = 1;
247 else if(*n<0) info = 2;
248 else if(*incx==0) info = 5;
249 else if(*incy==0) info = 7;
250 if(info)
251 return xerbla_(SCALAR_SUFFIX_UP"SPR2 ",&info,6);
252
253 if(alpha==Scalar(0))
254 return 1;
255
256 Scalar* x_cpy = get_compact_vector(x, *n, *incx);
257 Scalar* y_cpy = get_compact_vector(y, *n, *incy);
258
259 int code = UPLO(*uplo);
260 if(code>=2 || func[code]==0)
261 return 0;
262
263 func[code](*n, ap, x_cpy, y_cpy, alpha);
264
265 if(x_cpy!=x) delete[] x_cpy;
266 if(y_cpy!=y) delete[] y_cpy;
267
268 return 1;
269}
270
271/** DGER performs the rank 1 operation
272 *
273 * A := alpha*x*y' + A,
274 *
275 * where alpha is a scalar, x is an m element vector, y is an n element
276 * vector and A is an m by n matrix.
277 */
278int EIGEN_BLAS_FUNC(ger)(int *m, int *n, Scalar *palpha, Scalar *px, int *incx, Scalar *py, int *incy, Scalar *pa, int *lda)
279{
280 Scalar* x = reinterpret_cast<Scalar*>(px);
281 Scalar* y = reinterpret_cast<Scalar*>(py);
282 Scalar* a = reinterpret_cast<Scalar*>(pa);
283 Scalar alpha = *reinterpret_cast<Scalar*>(palpha);
284
285 int info = 0;
286 if(*m<0) info = 1;
287 else if(*n<0) info = 2;
288 else if(*incx==0) info = 5;
289 else if(*incy==0) info = 7;
290 else if(*lda<std::max(1,*m)) info = 9;
291 if(info)
292 return xerbla_(SCALAR_SUFFIX_UP"GER ",&info,6);
293
294 if(alpha==Scalar(0))
295 return 1;
296
297 Scalar* x_cpy = get_compact_vector(x,*m,*incx);
298 Scalar* y_cpy = get_compact_vector(y,*n,*incy);
299
300 internal::general_rank1_update<Scalar,int,ColMajor,false,false>::run(*m, *n, a, *lda, x_cpy, y_cpy, alpha);
301
302 if(x_cpy!=x) delete[] x_cpy;
303 if(y_cpy!=y) delete[] y_cpy;
304
305 return 1;
306}