1 // 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
EIGEN_BLAS_FUNC(symv)13 int 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)
15 {
16   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   };
23 
24   const Scalar* a = reinterpret_cast<const Scalar*>(pa);
25   const Scalar* x = reinterpret_cast<const Scalar*>(px);
26   Scalar* y = reinterpret_cast<Scalar*>(py);
27   Scalar alpha  = *reinterpret_cast<const Scalar*>(palpha);
28   Scalar beta   = *reinterpret_cast<const Scalar*>(pbeta);
29 
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 
43   const Scalar* actual_x = get_compact_vector(x,*n,*incx);
44   Scalar* actual_y = get_compact_vector(y,*n,*incy);
45 
46   if(beta!=Scalar(1))
47   {
48     if(beta==Scalar(0)) make_vector(actual_y, *n).setZero();
49     else                make_vector(actual_y, *n) *= beta;
50   }
51 
52   int code = UPLO(*uplo);
53   if(code>=2 || func[code]==0)
54     return 0;
55 
56   func[code](*n, a, *lda, actual_x, actual_y, alpha);
57 
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
EIGEN_BLAS_FUNC(syr)65 int EIGEN_BLAS_FUNC(syr)(const char *uplo, const int *n, const RealScalar *palpha, const RealScalar *px, const int *incx, RealScalar *pc, const int *ldc)
66 {
67 
68   typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, const Scalar&);
69   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   };
75 
76   const Scalar* x = reinterpret_cast<const Scalar*>(px);
77   Scalar* c = reinterpret_cast<Scalar*>(pc);
78   Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
79 
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
91   const Scalar* x_cpy = get_compact_vector(x,*n,*incx);
92 
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
EIGEN_BLAS_FUNC(syr2)105 int 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)
106 {
107   typedef void (*functype)(int, Scalar*, int, const Scalar*, const Scalar*, Scalar);
108   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   };
114 
115   const Scalar* x = reinterpret_cast<const Scalar*>(px);
116   const Scalar* y = reinterpret_cast<const Scalar*>(py);
117   Scalar* c = reinterpret_cast<Scalar*>(pc);
118   Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
119 
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 
132   const Scalar* x_cpy = get_compact_vector(x,*n,*incx);
133   const Scalar* y_cpy = get_compact_vector(y,*n,*incy);
134 
135   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   */
EIGEN_BLAS_FUNC(spr)186 int 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);
189   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   };
195 
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   */
EIGEN_BLAS_FUNC(spr2)230 int 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);
233   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   };
239 
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   */
EIGEN_BLAS_FUNC(ger)278 int 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 }
307