Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_BLAS_MP_Vector.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef _TEUCHOS_BLAS_MP_VECTOR_HPP_
11 #define _TEUCHOS_BLAS_MP_VECTOR_HPP_
12 
13 #include "Teuchos_BLAS.hpp"
14 #include "Sacado_MP_Vector.hpp"
15 
16 namespace Teuchos
17 {
18 
19 namespace details
20 {
21 
22 template <typename Storage>
23 class GivensRotator<Sacado::MP::Vector<Storage>, false>
24 {
25 public:
27  typedef ScalarType c_type;
28 
29  void
31  ScalarType *db,
32  ScalarType *c,
33  ScalarType *s) const
34  {
35  typedef ScalarTraits<ScalarType> STS;
36 
37  ScalarType r, roe, scale, z, da_scaled, db_scaled;
38  auto m_da = (STS::magnitude(*da) > STS::magnitude(*db));
39  mask_assign(m_da, roe) = {*da, *db};
40 
41  scale = STS::magnitude(*da) + STS::magnitude(*db);
42 
43  auto m_scale = scale != STS::zero();
44 
45  da_scaled = *da;
46  db_scaled = *db;
47 
48  *c = *da;
49  *s = *db;
50 
51  ScalarType tmp = STS::one();
52  mask_assign(m_scale, tmp) /= scale;
53 
54  mask_assign(m_scale, da_scaled) *= tmp;
55  mask_assign(m_scale, db_scaled) *= tmp;
56 
57  r = scale * STS::squareroot(da_scaled * da_scaled + db_scaled * db_scaled);
58  auto m_roe = roe < 0;
59  mask_assign(m_roe, r) = -r;
60 
61  tmp = STS::one();
62  mask_assign(m_scale, tmp) /= r;
63 
64  mask_assign(m_scale, *c) *= tmp;
65  mask_assign(m_scale, *s) *= tmp;
66 
67  mask_assign(!m_scale, *c) = STS::one();
68  mask_assign(!m_scale, *s) = STS::zero();
69 
70  mask_assign(*c != STS::zero(), z) /= {STS::one(), *c, STS::zero()};
71  mask_assign(!m_scale, z) = STS::zero();
72  mask_assign(m_da, z) = *s;
73 
74  *da = r;
75  *db = z;
76  }
77 };
78 } // namespace details
79 } // namespace Teuchos
80 
81 //namespace Sacado {
82 // namespace MP {
83 namespace Teuchos
84 {
86 template <typename OrdinalType, typename Storage>
87 class BLAS<OrdinalType, Sacado::MP::Vector<Storage>> : public Teuchos::DefaultBLASImpl<OrdinalType, Sacado::MP::Vector<Storage>>
88 {
89 
91  typedef typename Sacado::ValueType<Sacado::MP::Vector<Storage>>::type ValueType;
92  typedef typename Sacado::ScalarType<Sacado::MP::Vector<Storage>>::type scalar_type;
95 
96 public:
97  template <typename alpha_type, typename A_type>
100  const OrdinalType m, const OrdinalType n,
101  const alpha_type &alpha,
102  const A_type *A, const OrdinalType lda,
103  ScalarType *B, const OrdinalType ldb) const
104  {
105  OrdinalType izero = OrdinalTraits<OrdinalType>::zero();
106  OrdinalType ione = OrdinalTraits<OrdinalType>::one();
107  alpha_type alpha_zero = ScalarTraits<alpha_type>::zero();
108  A_type A_zero = ScalarTraits<A_type>::zero();
110  alpha_type alpha_one = ScalarTraits<alpha_type>::one();
112  ScalarType temp;
113  OrdinalType NRowA = m;
114  bool BadArgument = false;
115  bool noUnit = (EDiagChar[diag] == 'N');
116  bool noConj = (ETranspChar[transa] == 'T');
117 
118  if (!(ESideChar[side] == 'L'))
119  {
120  NRowA = n;
121  }
122 
123  // Quick return.
124  if (n == izero || m == izero)
125  {
126  return;
127  }
128  if (m < izero)
129  {
130  std::cout << "BLAS::TRSM Error: M == " << m << std::endl;
131  BadArgument = true;
132  }
133  if (n < izero)
134  {
135  std::cout << "BLAS::TRSM Error: N == " << n << std::endl;
136  BadArgument = true;
137  }
138  if (lda < NRowA)
139  {
140  std::cout << "BLAS::TRSM Error: LDA < " << NRowA << std::endl;
141  BadArgument = true;
142  }
143  if (ldb < m)
144  {
145  std::cout << "BLAS::TRSM Error: LDB < MAX(1,M)" << std::endl;
146  BadArgument = true;
147  }
148 
149  if (!BadArgument)
150  {
151  int i, j, k;
152  // Set the solution to the zero vector.
153  auto alpha_is_zero = (alpha == alpha_zero);
154  for (j = izero; j < n; j++)
155  {
156  for (i = izero; i < m; i++)
157  {
158  mask_assign(alpha_is_zero, B[j * ldb + i]) = B_zero;
159  }
160  }
161 
162  auto alpha_is_not_one = (alpha != alpha_one);
163 
164  { // Start the operations.
165  if (ESideChar[side] == 'L')
166  {
167  //
168  // Perform computations for OP(A)*X = alpha*B
169  //
170  if (ETranspChar[transa] == 'N')
171  {
172  //
173  // Compute B = alpha*inv( A )*B
174  //
175  if (EUploChar[uplo] == 'U')
176  {
177  // A is upper triangular.
178  for (j = izero; j < n; j++)
179  {
180  // Perform alpha*B if alpha is not 1.
181  for (i = izero; i < m; i++)
182  {
183  mask_assign(alpha_is_not_one, B[j * ldb + i]) *= alpha;
184  }
185 
186  // Perform a backsolve for column j of B.
187  for (k = (m - ione); k > -ione; k--)
188  {
189  // If this entry is zero, we don't have to do anything.
190  auto B_is_not_zero = (B[j * ldb + k] != B_zero);
191 
192  if (noUnit)
193  {
194  mask_assign(B_is_not_zero, B[j * ldb + k]) /= A[k * lda + k];
195  }
196  for (i = izero; i < k; i++)
197  {
198  mask_assign(B_is_not_zero, B[j * ldb + i]) -= B[j * ldb + k] * A[k * lda + i];
199  }
200  }
201  }
202  }
203  else
204  { // A is lower triangular.
205  for (j = izero; j < n; j++)
206  {
207  // Perform alpha*B if alpha is not 1.
208  for (i = izero; i < m; i++)
209  {
210  mask_assign(alpha_is_not_one, B[j * ldb + i]) *= alpha;
211  }
212  // Perform a forward solve for column j of B.
213  for (k = izero; k < m; k++)
214  {
215  // If this entry is zero, we don't have to do anything.
216  auto B_is_not_zero = (B[j * ldb + k] != B_zero);
217  if (noUnit)
218  {
219  mask_assign(B_is_not_zero, B[j * ldb + k]) /= A[k * lda + k];
220  }
221  for (i = k + ione; i < m; i++)
222  {
223  mask_assign(B_is_not_zero, B[j * ldb + i]) -= B[j * ldb + k] * A[k * lda + i];
224  }
225  }
226  }
227  } // end if (uplo == 'U')
228  } // if (transa =='N')
229  else
230  {
231  //
232  // Compute B = alpha*inv( A' )*B
233  // or B = alpha*inv( conj(A') )*B
234  //
235  if (EUploChar[uplo] == 'U')
236  {
237  // A is upper triangular.
238  for (j = izero; j < n; j++)
239  {
240  for (i = izero; i < m; i++)
241  {
242  temp = alpha * B[j * ldb + i];
243  if (noConj)
244  {
245  for (k = izero; k < i; k++)
246  {
247  temp -= A[i * lda + k] * B[j * ldb + k];
248  }
249  if (noUnit)
250  {
251  temp /= A[i * lda + i];
252  }
253  }
254  else
255  {
256  for (k = izero; k < i; k++)
257  {
258  temp -= ScalarTraits<A_type>::conjugate(A[i * lda + k]) * B[j * ldb + k];
259  }
260  if (noUnit)
261  {
262  temp /= ScalarTraits<A_type>::conjugate(A[i * lda + i]);
263  }
264  }
265  B[j * ldb + i] = temp;
266  }
267  }
268  }
269  else
270  { // A is lower triangular.
271  for (j = izero; j < n; j++)
272  {
273  for (i = (m - ione); i > -ione; i--)
274  {
275  temp = alpha * B[j * ldb + i];
276  if (noConj)
277  {
278  for (k = i + ione; k < m; k++)
279  {
280  temp -= A[i * lda + k] * B[j * ldb + k];
281  }
282  if (noUnit)
283  {
284  temp /= A[i * lda + i];
285  }
286  }
287  else
288  {
289  for (k = i + ione; k < m; k++)
290  {
291  temp -= ScalarTraits<A_type>::conjugate(A[i * lda + k]) * B[j * ldb + k];
292  }
293  if (noUnit)
294  {
295  temp /= ScalarTraits<A_type>::conjugate(A[i * lda + i]);
296  }
297  }
298  B[j * ldb + i] = temp;
299  }
300  }
301  }
302  }
303  } // if (side == 'L')
304  else
305  {
306  // side == 'R'
307  //
308  // Perform computations for X*OP(A) = alpha*B
309  //
310  if (ETranspChar[transa] == 'N')
311  {
312  //
313  // Compute B = alpha*B*inv( A )
314  //
315  if (EUploChar[uplo] == 'U')
316  {
317  // A is upper triangular.
318  // Perform a backsolve for column j of B.
319  for (j = izero; j < n; j++)
320  {
321  // Perform alpha*B if alpha is not 1.
322  for (i = izero; i < m; i++)
323  {
324  mask_assign(alpha_is_not_one, B[j * ldb + i]) *= alpha;
325  }
326  for (k = izero; k < j; k++)
327  {
328  // If this entry is zero, we don't have to do anything.
329  auto A_is_not_zero = (A[j * lda + k] != A_zero);
330  for (i = izero; i < m; i++)
331  {
332  mask_assign(A_is_not_zero, B[j * ldb + i]) -= A[j * lda + k] * B[k * ldb + i];
333  }
334  }
335  if (noUnit)
336  {
337  temp = B_one / A[j * lda + j];
338  for (i = izero; i < m; i++)
339  {
340  B[j * ldb + i] *= temp;
341  }
342  }
343  }
344  }
345  else
346  { // A is lower triangular.
347  for (j = (n - ione); j > -ione; j--)
348  {
349  // Perform alpha*B if alpha is not 1.
350  for (i = izero; i < m; i++)
351  {
352  mask_assign(alpha_is_not_one, B[j * ldb + i]) *= alpha;
353  }
354 
355  // Perform a forward solve for column j of B.
356  for (k = j + ione; k < n; k++)
357  {
358  // If this entry is zero, we don't have to do anything.
359  auto A_is_not_zero = (A[j * lda + k] != A_zero);
360  for (i = izero; i < m; i++)
361  {
362  mask_assign(A_is_not_zero, B[j * ldb + i]) -= A[j * lda + k] * B[k * ldb + i];
363  }
364  }
365  if (noUnit)
366  {
367  temp = B_one / A[j * lda + j];
368  for (i = izero; i < m; i++)
369  {
370  B[j * ldb + i] *= temp;
371  }
372  }
373  }
374  } // end if (uplo == 'U')
375  } // if (transa =='N')
376  else
377  {
378  //
379  // Compute B = alpha*B*inv( A' )
380  // or B = alpha*B*inv( conj(A') )
381  //
382  if (EUploChar[uplo] == 'U')
383  {
384  // A is upper triangular.
385  for (k = (n - ione); k > -ione; k--)
386  {
387  if (noUnit)
388  {
389  if (noConj)
390  temp = B_one / A[k * lda + k];
391  else
392  temp = B_one / ScalarTraits<A_type>::conjugate(A[k * lda + k]);
393  for (i = izero; i < m; i++)
394  {
395  B[k * ldb + i] *= temp;
396  }
397  }
398  for (j = izero; j < k; j++)
399  {
400  auto A_is_not_zero = (A[k * lda + j] != A_zero);
401  if (noConj)
402  mask_assign(A_is_not_zero, temp) = A[k * lda + j];
403  else
404  mask_assign(A_is_not_zero, temp) = ScalarTraits<A_type>::conjugate(A[k * lda + j]);
405  for (i = izero; i < m; i++)
406  {
407  mask_assign(A_is_not_zero, B[j * ldb + i]) -= temp * B[k * ldb + i];
408  }
409  }
410  for (i = izero; i < m; i++)
411  {
412  mask_assign(alpha_is_not_one, B[k * ldb + i]) *= alpha;
413  }
414  }
415  }
416  else
417  { // A is lower triangular.
418  for (k = izero; k < n; k++)
419  {
420  if (noUnit)
421  {
422  if (noConj)
423  temp = B_one / A[k * lda + k];
424  else
425  temp = B_one / ScalarTraits<A_type>::conjugate(A[k * lda + k]);
426  for (i = izero; i < m; i++)
427  {
428  B[k * ldb + i] *= temp;
429  }
430  }
431  for (j = k + ione; j < n; j++)
432  {
433  auto A_is_not_zero = (A[k * lda + j] != A_zero);
434  if (noConj)
435  mask_assign(A_is_not_zero, temp) = A[k * lda + j];
436  else
437  mask_assign(A_is_not_zero, temp) = ScalarTraits<A_type>::conjugate(A[k * lda + j]);
438  for (i = izero; i < m; i++)
439  {
440  mask_assign(A_is_not_zero, B[j * ldb + i]) -= temp * B[k * ldb + i];
441  }
442  }
443  for (i = izero; i < m; i++)
444  {
445  mask_assign(alpha_is_not_one, B[k * ldb + i]) *= alpha;
446  }
447  }
448  }
449  }
450  }
451  }
452  }
453  }
454 }; // class BLAS
455 // }
456 //}
457 
458 } // namespace Teuchos
459 
460 #endif // _TEUCHOS_BLAS__MP_VECTOR_HPP_
Teuchos::ScalarTraits< Sacado::MP::Vector< Storage > >::magnitudeType MagnitudeType
KOKKOS_INLINE_FUNCTION MaskedAssign< scalar > mask_assign(bool b, scalar *s)
TEUCHOSNUMERICS_LIB_DLL_EXPORT const char EDiagChar[]
static T conjugate(T a)
Sacado::ScalarType< Sacado::MP::Vector< Storage > >::type scalar_type
TEUCHOSNUMERICS_LIB_DLL_EXPORT const char EUploChar[]
void ROTG(ScalarType *da, ScalarType *db, ScalarType *c, ScalarType *s) const
TEUCHOSNUMERICS_LIB_DLL_EXPORT const char ESideChar[]
void TRSM(Teuchos::ESide side, Teuchos::EUplo uplo, Teuchos::ETransp transa, Teuchos::EDiag diag, const OrdinalType m, const OrdinalType n, const alpha_type &alpha, const A_type *A, const OrdinalType lda, ScalarType *B, const OrdinalType ldb) const
Teuchos::DefaultBLASImpl< OrdinalType, Sacado::MP::Vector< Storage > > BLASType
TEUCHOSNUMERICS_LIB_DLL_EXPORT const char ETranspChar[]
Sacado::ValueType< Sacado::MP::Vector< Storage > >::type ValueType