Add CPUID identification of Intel Ice Lake
[platform/upstream/openblas.git] / interface / gemv.c
1 /*********************************************************************/
2 /* Copyright 2009, 2010 The University of Texas at Austin.           */
3 /* All rights reserved.                                              */
4 /*                                                                   */
5 /* Redistribution and use in source and binary forms, with or        */
6 /* without modification, are permitted provided that the following   */
7 /* conditions are met:                                               */
8 /*                                                                   */
9 /*   1. Redistributions of source code must retain the above         */
10 /*      copyright notice, this list of conditions and the following  */
11 /*      disclaimer.                                                  */
12 /*                                                                   */
13 /*   2. Redistributions in binary form must reproduce the above      */
14 /*      copyright notice, this list of conditions and the following  */
15 /*      disclaimer in the documentation and/or other materials       */
16 /*      provided with the distribution.                              */
17 /*                                                                   */
18 /*    THIS  SOFTWARE IS PROVIDED  BY THE  UNIVERSITY OF  TEXAS AT    */
19 /*    AUSTIN  ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,    */
20 /*    INCLUDING, BUT  NOT LIMITED  TO, THE IMPLIED  WARRANTIES OF    */
21 /*    MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR  PURPOSE ARE    */
22 /*    DISCLAIMED.  IN  NO EVENT SHALL THE UNIVERSITY  OF TEXAS AT    */
23 /*    AUSTIN OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,    */
24 /*    INCIDENTAL,  SPECIAL, EXEMPLARY,  OR  CONSEQUENTIAL DAMAGES    */
25 /*    (INCLUDING, BUT  NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE    */
26 /*    GOODS  OR  SERVICES; LOSS  OF  USE,  DATA,  OR PROFITS;  OR    */
27 /*    BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON ANY THEORY OF    */
28 /*    LIABILITY, WHETHER  IN CONTRACT, STRICT  LIABILITY, OR TORT    */
29 /*    (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT    */
30 /*    OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE    */
31 /*    POSSIBILITY OF SUCH DAMAGE.                                    */
32 /*                                                                   */
33 /* The views and conclusions contained in the software and           */
34 /* documentation are those of the authors and should not be          */
35 /* interpreted as representing official policies, either expressed   */
36 /* or implied, of The University of Texas at Austin.                 */
37 /*********************************************************************/
38
39 #include <stdio.h>
40 #include "common.h"
41 #include "l1param.h"
42 #ifdef FUNCTION_PROFILE
43 #include "functable.h"
44 #endif
45
46 #ifdef XDOUBLE
47 #define ERROR_NAME "QGEMV "
48 #elif defined(DOUBLE)
49 #define ERROR_NAME "DGEMV "
50 #else
51 #define ERROR_NAME "SGEMV "
52 #endif
53
54 #ifdef SMP
55 static int (*gemv_thread[])(BLASLONG, BLASLONG, FLOAT, FLOAT *, BLASLONG,  FLOAT * , BLASLONG, FLOAT *, BLASLONG, FLOAT *, int) = {
56 #ifdef XDOUBLE
57   qgemv_thread_n, qgemv_thread_t,
58 #elif defined DOUBLE
59   dgemv_thread_n, dgemv_thread_t,
60 #else
61   sgemv_thread_n, sgemv_thread_t,
62 #endif
63 };
64 #endif
65
66 #ifndef CBLAS
67
68 void NAME(char *TRANS, blasint *M, blasint *N,
69            FLOAT *ALPHA, FLOAT *a, blasint *LDA,
70            FLOAT *x, blasint *INCX,
71            FLOAT *BETA, FLOAT *y, blasint *INCY){
72
73   char trans = *TRANS;
74   blasint m = *M;
75   blasint n = *N;
76   blasint lda = *LDA;
77   blasint incx = *INCX;
78   blasint incy = *INCY;
79   FLOAT alpha = *ALPHA;
80   FLOAT beta  = *BETA;
81   FLOAT *buffer;
82   int buffer_size;
83 #ifdef SMP
84   int nthreads;
85 #endif
86
87   int (*gemv[])(BLASLONG, BLASLONG, BLASLONG, FLOAT, FLOAT *, BLASLONG,  FLOAT * , BLASLONG, FLOAT *, BLASLONG, FLOAT *) = {
88     GEMV_N, GEMV_T,
89   };
90
91   blasint info;
92   blasint lenx, leny;
93   blasint i;
94
95   PRINT_DEBUG_NAME;
96
97   TOUPPER(trans);
98
99   info = 0;
100
101   i = -1;
102
103   if (trans == 'N') i = 0;
104   if (trans == 'T') i = 1;
105   if (trans == 'R') i = 0;
106   if (trans == 'C') i = 1;
107
108   if (incy == 0)        info = 11;
109   if (incx == 0)        info = 8;
110   if (lda < MAX(1, m))  info = 6;
111   if (n < 0)            info = 3;
112   if (m < 0)            info = 2;
113   if (i < 0)          info = 1;
114
115   trans = i;
116
117   if (info != 0){
118     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
119     return;
120   }
121
122 #else
123
124 void CNAME(enum CBLAS_ORDER order,
125            enum CBLAS_TRANSPOSE TransA,
126            blasint m, blasint n,
127            FLOAT alpha,
128            FLOAT  *a, blasint lda,
129            FLOAT  *x, blasint incx,
130            FLOAT beta,
131            FLOAT  *y, blasint incy){
132
133   FLOAT *buffer;
134   blasint lenx, leny;
135   int trans, buffer_size;
136   blasint info, t;
137 #ifdef SMP
138   int nthreads;
139 #endif
140
141   int (*gemv[])(BLASLONG, BLASLONG, BLASLONG, FLOAT, FLOAT *, BLASLONG,  FLOAT * , BLASLONG, FLOAT *, BLASLONG, FLOAT *) = {
142     GEMV_N, GEMV_T,
143   };
144
145   PRINT_DEBUG_CNAME;
146
147   trans = -1;
148   info  =  0;
149
150   if (order == CblasColMajor) {
151     if (TransA == CblasNoTrans)     trans = 0;
152     if (TransA == CblasTrans)       trans = 1;
153     if (TransA == CblasConjNoTrans) trans = 0;
154     if (TransA == CblasConjTrans)   trans = 1;
155
156     info = -1;
157
158     if (incy == 0)        info = 11;
159     if (incx == 0)        info = 8;
160     if (lda < MAX(1, m))  info = 6;
161     if (n < 0)            info = 3;
162     if (m < 0)            info = 2;
163     if (trans < 0)        info = 1;
164
165   }
166
167   if (order == CblasRowMajor) {
168     if (TransA == CblasNoTrans)     trans = 1;
169     if (TransA == CblasTrans)       trans = 0;
170     if (TransA == CblasConjNoTrans) trans = 1;
171     if (TransA == CblasConjTrans)   trans = 0;
172
173     info = -1;
174
175     t = n;
176     n = m;
177     m = t;
178
179     if (incy == 0)        info = 11;
180     if (incx == 0)        info = 8;
181     if (lda < MAX(1, m))  info = 6;
182     if (n < 0)            info = 3;
183     if (m < 0)            info = 2;
184     if (trans < 0)        info = 1;
185
186   }
187
188   if (info >= 0) {
189     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
190     return;
191   }
192
193 #endif
194   //printf("m=%d, n=%d, trans=%d, incx=%d, incy=%d, alpha=%f, beta=%f\n", m, n, trans, incx, incy, alpha, beta);
195   if ((m==0) || (n==0)) return;
196
197   lenx = n;
198   leny = m;
199   if (trans) lenx = m;
200   if (trans) leny = n;
201
202   if (beta != ONE) SCAL_K(leny, 0, 0, beta, y, blasabs(incy), NULL, 0, NULL, 0);
203
204   if (alpha == ZERO) return;
205
206   IDEBUG_START;
207
208   FUNCTION_PROFILE_START();
209
210   if (incx < 0) x -= (lenx - 1) * incx;
211   if (incy < 0) y -= (leny - 1) * incy;
212
213   buffer_size = m + n + 128 / sizeof(FLOAT);
214 #ifdef WINDOWS_ABI
215   buffer_size += 160 / sizeof(FLOAT) ;
216 #endif
217   // for alignment
218   buffer_size = (buffer_size + 3) & ~3;
219   STACK_ALLOC(buffer_size, FLOAT, buffer);
220
221 #ifdef SMP
222
223   if ( 1L * m * n < 2304L * GEMM_MULTITHREAD_THRESHOLD )
224     nthreads = 1;
225   else
226     nthreads = num_cpu_avail(2);
227
228   if (nthreads == 1) {
229 #endif
230
231     (gemv[(int)trans])(m, n, 0, alpha, a, lda, x, incx, y, incy, buffer);
232
233 #ifdef SMP
234   } else {
235
236     (gemv_thread[(int)trans])(m, n, alpha, a, lda, x, incx, y, incy, buffer, nthreads);
237
238   }
239 #endif
240
241   STACK_FREE(buffer);
242   FUNCTION_PROFILE_END(1, m * n + m + n,  2 * m * n);
243
244   IDEBUG_END;
245
246   return;
247
248 }