Merge pull request #1762 from martin-frbg/issue1710-2
[platform/upstream/openblas.git] / interface / trmv.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 "QTRMV "
48 #elif defined(DOUBLE)
49 #define ERROR_NAME "DTRMV "
50 #else
51 #define ERROR_NAME "STRMV "
52 #endif
53
54 static int (*trmv[])(BLASLONG, FLOAT *, BLASLONG, FLOAT *, BLASLONG, FLOAT *) = {
55 #ifdef XDOUBLE
56   qtrmv_NUU, qtrmv_NUN, qtrmv_NLU, qtrmv_NLN,
57   qtrmv_TUU, qtrmv_TUN, qtrmv_TLU, qtrmv_TLN,
58 #elif defined(DOUBLE)
59   dtrmv_NUU, dtrmv_NUN, dtrmv_NLU, dtrmv_NLN,
60   dtrmv_TUU, dtrmv_TUN, dtrmv_TLU, dtrmv_TLN,
61 #else
62   strmv_NUU, strmv_NUN, strmv_NLU, strmv_NLN,
63   strmv_TUU, strmv_TUN, strmv_TLU, strmv_TLN,
64 #endif
65 };
66
67 #ifdef SMP
68 static int (*trmv_thread[])(BLASLONG, FLOAT *, BLASLONG, FLOAT *, BLASLONG, FLOAT *, int) = {
69 #ifdef XDOUBLE
70   qtrmv_thread_NUU, qtrmv_thread_NUN, qtrmv_thread_NLU, qtrmv_thread_NLN,
71   qtrmv_thread_TUU, qtrmv_thread_TUN, qtrmv_thread_TLU, qtrmv_thread_TLN,
72 #elif defined(DOUBLE)
73   dtrmv_thread_NUU, dtrmv_thread_NUN, dtrmv_thread_NLU, dtrmv_thread_NLN,
74   dtrmv_thread_TUU, dtrmv_thread_TUN, dtrmv_thread_TLU, dtrmv_thread_TLN,
75 #else
76   strmv_thread_NUU, strmv_thread_NUN, strmv_thread_NLU, strmv_thread_NLN,
77   strmv_thread_TUU, strmv_thread_TUN, strmv_thread_TLU, strmv_thread_TLN,
78 #endif
79 };
80 #endif
81
82 #ifndef CBLAS
83
84 void NAME(char *UPLO, char *TRANS, char *DIAG,
85            blasint *N, FLOAT *a, blasint *LDA, FLOAT *x, blasint *INCX){
86
87   char uplo_arg  = *UPLO;
88   char trans_arg = *TRANS;
89   char diag_arg  = *DIAG;
90
91   blasint n    = *N;
92   blasint lda  = *LDA;
93   blasint incx = *INCX;
94
95   blasint info;
96   int uplo;
97   int unit;
98   int trans;
99   FLOAT *buffer;
100 #ifdef SMP
101   int nthreads;
102 #endif
103
104   PRINT_DEBUG_NAME;
105
106   TOUPPER(uplo_arg);
107   TOUPPER(trans_arg);
108   TOUPPER(diag_arg);
109
110   trans = -1;
111   unit  = -1;
112   uplo  = -1;
113
114   if (trans_arg == 'N') trans = 0;
115   if (trans_arg == 'T') trans = 1;
116   if (trans_arg == 'R') trans = 0;
117   if (trans_arg == 'C') trans = 1;
118
119   if (diag_arg  == 'U') unit  = 0;
120   if (diag_arg  == 'N') unit  = 1;
121
122   if (uplo_arg  == 'U') uplo  = 0;
123   if (uplo_arg  == 'L') uplo  = 1;
124
125   info = 0;
126
127   if (incx == 0)          info =  8;
128   if (lda  < MAX(1, n))   info =  6;
129   if (n < 0)              info =  4;
130   if (unit  < 0)          info =  3;
131   if (trans < 0)          info =  2;
132   if (uplo  < 0)          info =  1;
133
134   if (info != 0) {
135     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
136     return;
137   }
138
139 #else
140
141 void CNAME(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,
142            enum CBLAS_TRANSPOSE TransA, enum CBLAS_DIAG Diag,
143            blasint n, FLOAT  *a, blasint lda, FLOAT  *x, blasint incx) {
144
145   int trans, uplo, unit;
146   blasint info;
147   FLOAT *buffer;
148 #ifdef SMP
149   int nthreads;
150 #endif
151
152   PRINT_DEBUG_CNAME;
153
154   unit  = -1;
155   uplo  = -1;
156   trans = -1;
157   info  =  0;
158
159   if (order == CblasColMajor) {
160     if (Uplo == CblasUpper)         uplo  = 0;
161     if (Uplo == CblasLower)         uplo  = 1;
162
163     if (TransA == CblasNoTrans)     trans = 0;
164     if (TransA == CblasTrans)       trans = 1;
165     if (TransA == CblasConjNoTrans) trans = 0;
166     if (TransA == CblasConjTrans)   trans = 1;
167
168     if (Diag == CblasUnit)          unit  = 0;
169     if (Diag == CblasNonUnit)       unit  = 1;
170
171     info = -1;
172
173     if (incx == 0)          info =  8;
174     if (lda  < MAX(1, n))   info =  6;
175     if (n < 0)              info =  4;
176     if (unit  < 0)          info =  3;
177     if (trans < 0)          info =  2;
178     if (uplo  < 0)          info =  1;
179   }
180
181   if (order == CblasRowMajor) {
182     if (Uplo == CblasUpper)         uplo  = 1;
183     if (Uplo == CblasLower)         uplo  = 0;
184
185     if (TransA == CblasNoTrans)     trans = 1;
186     if (TransA == CblasTrans)       trans = 0;
187     if (TransA == CblasConjNoTrans) trans = 1;
188     if (TransA == CblasConjTrans)   trans = 0;
189
190     if (Diag == CblasUnit)          unit  = 0;
191     if (Diag == CblasNonUnit)       unit  = 1;
192
193     info = -1;
194
195     if (incx == 0)          info =  8;
196     if (lda  < MAX(1, n))   info =  6;
197     if (n < 0)              info =  4;
198     if (unit  < 0)          info =  3;
199     if (trans < 0)          info =  2;
200     if (uplo  < 0)          info =  1;
201   }
202
203   if (info >= 0) {
204     BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
205     return;
206   }
207
208 #endif
209
210   if (n == 0) return;
211
212   IDEBUG_START;
213
214   FUNCTION_PROFILE_START();
215
216   if (incx < 0 ) x -= (n - 1) * incx;
217
218   buffer = (FLOAT *)blas_memory_alloc(1);
219
220 #ifdef SMP
221 /*  nthreads = num_cpu_avail(2);
222
223 FIXME trmv_thread was found to be broken, see issue 1332 */
224   nthreads = 1;
225   
226   if (nthreads == 1) {
227 #endif
228
229     (trmv[(trans<<2) | (uplo<<1) | unit])(n, a, lda, x, incx, buffer);
230
231 #ifdef SMP
232   } else {
233
234     (trmv_thread[(trans<<2) | (uplo<<1) | unit])(n, a, lda, x, incx, buffer, nthreads);
235
236   }
237 #endif
238
239   blas_memory_free(buffer);
240
241   FUNCTION_PROFILE_END(1, n * n / 2 + n,  n * n);
242
243   IDEBUG_END;
244
245   return;
246 }