Add CPUID identification of Intel Ice Lake
[platform/upstream/openblas.git] / interface / ztrmv.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 <ctype.h>
41 #include "common.h"
42 #ifdef FUNCTION_PROFILE
43 #include "functable.h"
44 #endif
45
46 #ifdef XDOUBLE
47 #define ERROR_NAME "XTRMV "
48 #elif defined(DOUBLE)
49 #define ERROR_NAME "ZTRMV "
50 #else
51 #define ERROR_NAME "CTRMV "
52 #endif
53
54 static int (*trmv[])(BLASLONG, FLOAT *, BLASLONG, FLOAT *, BLASLONG, FLOAT *) = {
55 #ifdef XDOUBLE
56   xtrmv_NUU, xtrmv_NUN, xtrmv_NLU, xtrmv_NLN,
57   xtrmv_TUU, xtrmv_TUN, xtrmv_TLU, xtrmv_TLN,
58   xtrmv_RUU, xtrmv_RUN, xtrmv_RLU, xtrmv_RLN,
59   xtrmv_CUU, xtrmv_CUN, xtrmv_CLU, xtrmv_CLN,
60 #elif defined(DOUBLE)
61   ztrmv_NUU, ztrmv_NUN, ztrmv_NLU, ztrmv_NLN,
62   ztrmv_TUU, ztrmv_TUN, ztrmv_TLU, ztrmv_TLN,
63   ztrmv_RUU, ztrmv_RUN, ztrmv_RLU, ztrmv_RLN,
64   ztrmv_CUU, ztrmv_CUN, ztrmv_CLU, ztrmv_CLN,
65 #else
66   ctrmv_NUU, ctrmv_NUN, ctrmv_NLU, ctrmv_NLN,
67   ctrmv_TUU, ctrmv_TUN, ctrmv_TLU, ctrmv_TLN,
68   ctrmv_RUU, ctrmv_RUN, ctrmv_RLU, ctrmv_RLN,
69   ctrmv_CUU, ctrmv_CUN, ctrmv_CLU, ctrmv_CLN,
70 #endif
71 };
72
73 #ifdef SMP
74 static int (*trmv_thread[])(BLASLONG, FLOAT *, BLASLONG, FLOAT *, BLASLONG, FLOAT *, int) = {
75 #ifdef XDOUBLE
76   xtrmv_thread_NUU, xtrmv_thread_NUN, xtrmv_thread_NLU, xtrmv_thread_NLN,
77   xtrmv_thread_TUU, xtrmv_thread_TUN, xtrmv_thread_TLU, xtrmv_thread_TLN,
78   xtrmv_thread_RUU, xtrmv_thread_RUN, xtrmv_thread_RLU, xtrmv_thread_RLN,
79   xtrmv_thread_CUU, xtrmv_thread_CUN, xtrmv_thread_CLU, xtrmv_thread_CLN,
80 #elif defined(DOUBLE)
81   ztrmv_thread_NUU, ztrmv_thread_NUN, ztrmv_thread_NLU, ztrmv_thread_NLN,
82   ztrmv_thread_TUU, ztrmv_thread_TUN, ztrmv_thread_TLU, ztrmv_thread_TLN,
83   ztrmv_thread_RUU, ztrmv_thread_RUN, ztrmv_thread_RLU, ztrmv_thread_RLN,
84   ztrmv_thread_CUU, ztrmv_thread_CUN, ztrmv_thread_CLU, ztrmv_thread_CLN,
85 #else
86   ctrmv_thread_NUU, ctrmv_thread_NUN, ctrmv_thread_NLU, ctrmv_thread_NLN,
87   ctrmv_thread_TUU, ctrmv_thread_TUN, ctrmv_thread_TLU, ctrmv_thread_TLN,
88   ctrmv_thread_RUU, ctrmv_thread_RUN, ctrmv_thread_RLU, ctrmv_thread_RLN,
89   ctrmv_thread_CUU, ctrmv_thread_CUN, ctrmv_thread_CLU, ctrmv_thread_CLN,
90 #endif
91 };
92 #endif
93
94 #ifndef CBLAS
95
96 void NAME(char *UPLO, char *TRANS, char *DIAG,
97            blasint *N, FLOAT *a, blasint *LDA, FLOAT *x, blasint *INCX){
98
99   char uplo_arg  = *UPLO;
100   char trans_arg = *TRANS;
101   char diag_arg  = *DIAG;
102
103   blasint n    = *N;
104   blasint lda  = *LDA;
105   blasint incx = *INCX;
106
107   blasint info;
108   int uplo;
109   int unit;
110   int trans, buffer_size;
111   FLOAT *buffer;
112 #ifdef SMP
113   int nthreads;
114 #endif
115
116   PRINT_DEBUG_NAME;
117
118   TOUPPER(uplo_arg);
119   TOUPPER(trans_arg);
120   TOUPPER(diag_arg);
121
122   trans = -1;
123   unit  = -1;
124   uplo  = -1;
125
126   if (trans_arg == 'N') trans = 0;
127   if (trans_arg == 'T') trans = 1;
128   if (trans_arg == 'R') trans = 2;
129   if (trans_arg == 'C') trans = 3;
130
131   if (diag_arg  == 'U') unit  = 0;
132   if (diag_arg  == 'N') unit  = 1;
133
134   if (uplo_arg  == 'U') uplo  = 0;
135   if (uplo_arg  == 'L') uplo  = 1;
136
137   info = 0;
138
139   if (incx == 0)          info =  8;
140   if (lda  < MAX(1, n))   info =  6;
141   if (n < 0)              info =  4;
142   if (unit  < 0)          info =  3;
143   if (trans < 0)          info =  2;
144   if (uplo  < 0)          info =  1;
145
146   if (info != 0) {
147     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
148     return;
149   }
150
151 #else
152
153 void CNAME(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,
154            enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag,
155            blasint n, void  *va, blasint lda, void  *vx, blasint incx) {
156
157   FLOAT *a = (FLOAT*) va;
158   FLOAT *x = (FLOAT*) vx;
159   
160   int trans, uplo, unit, buffer_size;
161   blasint info;
162   FLOAT *buffer;
163 #ifdef SMP
164   int nthreads;
165 #endif
166
167   PRINT_DEBUG_CNAME;
168
169   unit  = -1;
170   uplo  = -1;
171   trans = -1;
172   info  =  0;
173
174   if (order == CblasColMajor) {
175     if (Uplo == CblasUpper)         uplo  = 0;
176     if (Uplo == CblasLower)         uplo  = 1;
177
178     if (TransA == CblasNoTrans)     trans = 0;
179     if (TransA == CblasTrans)       trans = 1;
180     if (TransA == CblasConjNoTrans) trans = 2;
181     if (TransA == CblasConjTrans)   trans = 3;
182
183     if (Diag == CblasUnit)          unit  = 0;
184     if (Diag == CblasNonUnit)       unit  = 1;
185
186     info = -1;
187
188     if (incx == 0)          info =  8;
189     if (lda  < MAX(1, n))   info =  6;
190     if (n < 0)              info =  4;
191     if (unit  < 0)          info =  3;
192     if (trans < 0)          info =  2;
193     if (uplo  < 0)          info =  1;
194   }
195
196   if (order == CblasRowMajor) {
197     if (Uplo == CblasUpper)         uplo  = 1;
198     if (Uplo == CblasLower)         uplo  = 0;
199
200     if (TransA == CblasNoTrans)     trans = 1;
201     if (TransA == CblasTrans)       trans = 0;
202     if (TransA == CblasConjNoTrans) trans = 3;
203     if (TransA == CblasConjTrans)   trans = 2;
204
205     if (Diag == CblasUnit)          unit  = 0;
206     if (Diag == CblasNonUnit)       unit  = 1;
207
208     info = -1;
209
210     if (incx == 0)          info =  8;
211     if (lda  < MAX(1, n))   info =  6;
212     if (n < 0)              info =  4;
213     if (unit  < 0)          info =  3;
214     if (trans < 0)          info =  2;
215     if (uplo  < 0)          info =  1;
216   }
217
218   if (info >= 0) {
219     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
220     return;
221   }
222
223 #endif
224
225   if (n == 0) return;
226
227   IDEBUG_START;
228
229   FUNCTION_PROFILE_START();
230
231   if (incx < 0 ) x -= (n - 1) * incx * 2;
232
233 #ifdef SMP
234   // Calibrated on a Xeon E5-2630
235   if(1L * n * n > 36L * sizeof(FLOAT) * sizeof(FLOAT) * GEMM_MULTITHREAD_THRESHOLD) {
236     nthreads = num_cpu_avail(2);
237     if(nthreads > 2 && 1L * n * n < 64L * sizeof(FLOAT) * sizeof(FLOAT) * GEMM_MULTITHREAD_THRESHOLD)
238       nthreads = 2;
239   } else
240       nthreads = 1;
241
242   if(nthreads > 1) {
243     buffer_size = n > 16 ? 0 : n * 4 + 40;
244   }
245   else
246 #endif
247   {
248     buffer_size = ((n - 1) / DTB_ENTRIES) * 2 * DTB_ENTRIES + 32 / sizeof(FLOAT);
249     // It seems to be required for some K8 or Barcelona CPU
250     buffer_size += 8;
251     if(incx != 1)
252       buffer_size += n * 2;
253   }
254   STACK_ALLOC(buffer_size, FLOAT, buffer);
255
256 #ifdef SMP
257   if (nthreads == 1) {
258 #endif
259
260   (trmv[(trans<<2) | (uplo<<1) | unit])(n, a, lda, x, incx, buffer);
261
262 #ifdef SMP
263   } else {
264
265     (trmv_thread[(trans<<2) | (uplo<<1) | unit])(n, a, lda, x, incx, buffer, nthreads);
266
267   }
268 #endif
269
270   STACK_FREE(buffer);
271
272   FUNCTION_PROFILE_END(4, n * n / 2 + n,  n * n);
273
274   IDEBUG_END;
275
276   return;
277 }