PLASMA  2.4.5
PLASMA - Parallel Linear Algebra for Scalable Multi-core Architectures
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
core_zpemv.c
Go to the documentation of this file.
1 
15 #include <cblas.h>
16 #include <lapacke.h>
17 #include "common.h"
18 
19 /***************************************************************************/
114 #if defined(PLASMA_HAVE_WEAK)
115 #pragma weak CORE_zpemv = PCORE_zpemv
116 #define CORE_zpemv PCORE_zpemv
117 #endif
118 int CORE_zpemv(int trans, int storev,
119  int M, int N, int L,
120  PLASMA_Complex64_t ALPHA,
121  PLASMA_Complex64_t *A, int LDA,
122  PLASMA_Complex64_t *X, int INCX,
123  PLASMA_Complex64_t BETA,
124  PLASMA_Complex64_t *Y, int INCY,
125  PLASMA_Complex64_t *WORK)
126 {
127 
128  /*
129  * y = alpha * op(A) * x + beta * y
130  */
131 
132  int K;
133  static PLASMA_Complex64_t zzero = 0.0;
134 
135 
136  /* Check input arguments */
137  if ((trans != PlasmaNoTrans) && (trans != PlasmaTrans) && (trans != PlasmaConjTrans)) {
138  coreblas_error(1, "Illegal value of trans");
139  return -1;
140  }
141  if ((storev != PlasmaColumnwise) && (storev != PlasmaRowwise)) {
142  coreblas_error(2, "Illegal value of storev");
143  return -2;
144  }
145  if (!( ((storev == PlasmaColumnwise) && (trans != PlasmaNoTrans)) ||
146  ((storev == PlasmaRowwise) && (trans == PlasmaNoTrans)) )) {
147  coreblas_error(2, "Illegal values of trans/storev");
148  return -2;
149  }
150  if (M < 0) {
151  coreblas_error(3, "Illegal value of M");
152  return -3;
153  }
154  if (N < 0) {
155  coreblas_error(4, "Illegal value of N");
156  return -4;
157  }
158  if (L > min(M ,N)) {
159  coreblas_error(5, "Illegal value of L");
160  return -5;
161  }
162  if (LDA < max(1,M)) {
163  coreblas_error(8, "Illegal value of LDA");
164  return -8;
165  }
166  if (INCX < 1) {
167  coreblas_error(10, "Illegal value of INCX");
168  return -10;
169  }
170  if (INCY < 1) {
171  coreblas_error(13, "Illegal value of INCY");
172  return -13;
173  }
174 
175  /* Quick return */
176  if ((M == 0) || (N == 0))
177  return PLASMA_SUCCESS;
178  if ((ALPHA == zzero) && (BETA == zzero))
179  return PLASMA_SUCCESS;
180 
181  /* If L < 2, there is no triangular part */
182  if (L == 1) L = 0;
183 
184  /* Columnwise */
185  if (storev == PlasmaColumnwise) {
186  /*
187  * ______________
188  * | | | A1: A[ 0 ]
189  * | | | A2: A[ M-L ]
190  * | A1 | | A3: A[ (N-L) * LDA ]
191  * | | |
192  * |______| A3 |
193  * \ | |
194  * \ A2 | |
195  * \ | |
196  * \|_____|
197  *
198  */
199 
200 
201  /* Columnwise / NoTrans */
202  if (trans == PlasmaNoTrans) {
203  coreblas_error(1, "The case PlasmaNoTrans / PlasmaColumnwise is not yet implemented");
204  return -1;
205  }
206  /* Columnwise / [Conj]Trans */
207  else {
208 
209  /* L top rows of y */
210  if (L > 0) {
211 
212  /* w = A_2' * x_2 */
213  cblas_zcopy(
214  L, &X[INCX*(M-L)], INCX, WORK, 1);
215  cblas_ztrmv(
217  (CBLAS_TRANSPOSE)trans,
219  L, &A[M-L], LDA, WORK, 1);
220 
221  if (M > L) {
222 
223  /* y_1 = beta * y_1 [ + alpha * A_1 * x_1 ] */
224  cblas_zgemv(
226  M-L, L, CBLAS_SADDR(ALPHA), A, LDA,
227  X, INCX, CBLAS_SADDR(BETA), Y, INCY);
228 
229  /* y_1 = y_1 + alpha * w */
230  cblas_zaxpy(L, CBLAS_SADDR(ALPHA), WORK, 1, Y, INCY);
231 
232  } else {
233 
234  /* y_1 = y_1 + alpha * w */
235  if (BETA == zzero) {
236  cblas_zscal(L, CBLAS_SADDR(ALPHA), WORK, 1);
237  cblas_zcopy(L, WORK, 1, Y, INCY);
238  } else {
239  cblas_zscal(L, CBLAS_SADDR(BETA), Y, INCY);
240  cblas_zaxpy(L, CBLAS_SADDR(ALPHA), WORK, 1, Y, INCY);
241  }
242  }
243  }
244 
245  /* N-L bottom rows of Y */
246  if (N > L) {
247  K = N - L;
248  cblas_zgemv(
250  M, K, CBLAS_SADDR(ALPHA), &A[LDA*L], LDA,
251  X, INCX, CBLAS_SADDR(BETA), &Y[INCY*L], INCY);
252  }
253  }
254  }
255  /* Rowwise */
256  else {
257  /*
258  * --------------
259  * | | \ A1: A[ 0 ]
260  * | A1 | \ A2: A[ (N-L) * LDA ]
261  * | | A2 \ A3: A[ L ]
262  * |--------------------\
263  * | A3 |
264  * ----------------------
265  *
266  */
267 
268  /* Rowwise / NoTrans */
269  if (trans == PlasmaNoTrans) {
270  /* L top rows of A and y */
271  if (L > 0) {
272 
273  /* w = A_2 * x_2 */
274  cblas_zcopy(
275  L, &X[INCX*(N-L)], INCX, WORK, 1);
276  cblas_ztrmv(
280  L, &A[LDA*(N-L)], LDA, WORK, 1);
281 
282  if (N > L) {
283 
284  /* y_1 = beta * y_1 [ + alpha * A_1 * x_1 ] */
285  cblas_zgemv(
286  CblasColMajor, (CBLAS_TRANSPOSE)PlasmaNoTrans,
287  L, N-L, CBLAS_SADDR(ALPHA), A, LDA,
288  X, INCX, CBLAS_SADDR(BETA), Y, INCY);
289 
290  /* y_1 = y_1 + alpha * w */
291  cblas_zaxpy(L, CBLAS_SADDR(ALPHA), WORK, 1, Y, INCY);
292 
293  } else {
294 
295  /* y_1 = y_1 + alpha * w */
296  if (BETA == zzero) {
297  cblas_zscal(L, CBLAS_SADDR(ALPHA), WORK, 1);
298  cblas_zcopy(L, WORK, 1, Y, INCY);
299  } else {
300  cblas_zscal(L, CBLAS_SADDR(BETA), Y, INCY);
301  cblas_zaxpy(L, CBLAS_SADDR(ALPHA), WORK, 1, Y, INCY);
302  }
303  }
304  }
305 
306  /* M-L bottom rows of Y */
307  if (M > L) {
308  cblas_zgemv(
310  M-L, N, CBLAS_SADDR(ALPHA), &A[L], LDA,
311  X, INCX, CBLAS_SADDR(BETA), &Y[INCY*L], INCY);
312  }
313  }
314  /* Rowwise / [Conj]Trans */
315  else {
316  coreblas_error(1, "The case Plasma[Conj]Trans / PlasmaRowwise is not yet implemented");
317  return -1;
318  }
319  }
320 
321  return PLASMA_SUCCESS;
322 }