Nektar++
MatrixVectorMultiplication.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: MatrixVectorMultiplication.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description:
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <type_traits>
36
37#include <boost/core/ignore_unused.hpp>
38
41
42namespace Nektar
43{
44
45template <typename DataType, typename LhsDataType, typename MatrixType>
47 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
48 const DataType *rhs)
49{
50 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
51 {
52 DataType accum = DataType(0);
53 for (unsigned int j = 0; j < lhs.GetColumns(); ++j)
54 {
55 accum += lhs(i, j) * rhs[j];
56 }
57 result[i] = accum;
58 }
59}
60
61template <typename DataType, typename LhsDataType, typename MatrixType>
62void NekMultiplyDiagonalMatrix(DataType *result,
64 const DataType *rhs)
65{
66 int n = lhs.GetRows();
67 for (unsigned int i = 0; i < n; ++i)
68 {
69 result[i] = lhs(i, i) * rhs[i];
70 }
71}
72
73template <typename DataType, typename LhsDataType>
75 DataType *result, const NekMatrix<LhsDataType, StandardMatrixTag> &lhs,
76 const DataType *rhs)
77{
78 int n = lhs.GetRows();
79 const DataType *mat_ptr = lhs.GetRawPtr();
80 Vmath::Vmul(n, mat_ptr, 1, rhs, 1, result, 1);
81}
82
83template <typename DataType, typename LhsDataType, typename MatrixType>
85 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
86 const DataType *rhs,
87 typename std::enable_if<
89{
90 boost::ignore_unused(p);
91
92 int m = lhs.GetRows();
93 int n = lhs.GetColumns();
94 int kl = lhs.GetNumberOfSubDiagonals();
95 int ku = lhs.GetNumberOfSuperDiagonals();
96 DataType alpha = lhs.Scale();
97 const DataType *a = lhs.GetRawPtr();
98 int lda = kl + ku + 1;
99 const DataType *x = rhs;
100 int incx = 1;
101 DataType beta = 0.0;
102 DataType *y = result;
103 int incy = 1;
104 Blas::Gbmv('N', m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy);
105}
106
107template <typename DataType, typename LhsDataType>
109 DataType *result, const NekMatrix<LhsDataType, BlockMatrixTag> &lhs,
110 const DataType *rhs,
111 typename std::enable_if<
113 0)
114{
115 boost::ignore_unused(result, lhs, rhs, p);
116
118 "Banded block matrix multiplication not yet implemented");
119}
120
121template <typename DataType, typename LhsInnerMatrixType>
123 NekVector<DataType> &result,
125 const NekVector<DataType> &rhs)
126{
127 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
128 unsigned int numberOfBlockColumns = lhs.GetNumberOfBlockColumns();
129 DataType *result_ptr = result.GetRawPtr();
130 const DataType *rhs_ptr = rhs.GetRawPtr();
131
132 for (unsigned int i = 0; i < result.GetDimension(); ++i)
133 {
134 result_ptr[i] = DataType(0);
135 }
136 Array<OneD, DataType> temp(result.GetDimension());
137 DataType *temp_ptr = temp.get();
138
139 unsigned int curResultRow = 0;
140 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
141 {
142 unsigned int rowsInBlock = lhs.GetNumberOfRowsInBlockRow(blockRow);
143
144 if (blockRow != 0)
145 {
146 curResultRow += lhs.GetNumberOfRowsInBlockRow(blockRow - 1);
147 }
148
149 if (rowsInBlock == 0)
150 {
151 continue;
152 }
153
154 DataType *resultWrapper = result_ptr + curResultRow;
155
156 unsigned int curWrapperRow = 0;
157 for (unsigned int blockColumn = 0; blockColumn < numberOfBlockColumns;
158 ++blockColumn)
159 {
160 if (blockColumn != 0)
161 {
162 curWrapperRow +=
163 lhs.GetNumberOfColumnsInBlockColumn(blockColumn - 1);
164 }
165
166 const LhsInnerMatrixType *block =
167 lhs.GetBlockPtr(blockRow, blockColumn);
168 if (!block)
169 {
170 continue;
171 }
172
173 unsigned int columnsInBlock =
174 lhs.GetNumberOfColumnsInBlockColumn(blockColumn);
175 if (columnsInBlock == 0)
176 {
177 continue;
178 }
179
180 const DataType *rhsWrapper = rhs_ptr + curWrapperRow;
181 Multiply(temp_ptr, *block, rhsWrapper);
182 for (unsigned int i = 0; i < rowsInBlock; ++i)
183 {
184 resultWrapper[i] += temp_ptr[i];
185 }
186 }
187 }
188}
189
190template <typename DataType, typename LhsInnerMatrixType>
192 NekVector<DataType> &result,
194 const NekVector<DataType> &rhs)
195{
196 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
197 DataType *result_ptr = result.GetRawPtr();
198 const DataType *rhs_ptr = rhs.GetRawPtr();
199
202 lhs.GetBlockSizes(rowSizes, colSizes);
203
204 unsigned int curResultRow = 0;
205 unsigned int curWrapperRow = 0;
206 unsigned int rowsInBlock = 0;
207 unsigned int columnsInBlock = 0;
208 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
209 {
210 curResultRow += rowsInBlock;
211 curWrapperRow += columnsInBlock;
212 if (blockRow == 0)
213 {
214 rowsInBlock = rowSizes[blockRow] + 1;
215 columnsInBlock = colSizes[blockRow] + 1;
216 }
217 else
218 {
219 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
220 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
221 }
222
223 if (rowsInBlock == 0)
224 {
225 continue;
226 }
227 if (columnsInBlock == 0)
228 {
229 std::fill(result.begin() + curResultRow,
230 result.begin() + curResultRow + rowsInBlock, 0.0);
231 continue;
232 }
233
234 const LhsInnerMatrixType *block = lhs.GetBlockPtr(blockRow, blockRow);
235 if (!block)
236 {
237 continue;
238 }
239
240 DataType *resultWrapper = result_ptr + curResultRow;
241 const DataType *rhsWrapper = rhs_ptr + curWrapperRow;
242 Multiply(resultWrapper, *block, rhsWrapper);
243 }
244 curResultRow += rowsInBlock;
245 if (curResultRow < result.GetRows())
246 {
247 std::fill(result.begin() + curResultRow, result.end(), 0.0);
248 }
249}
250
252 NekVector<double> &result,
253 const NekMatrix<
255 BlockMatrixTag> &lhs,
256 const NekVector<double> &rhs)
257{
258 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
259 double *result_ptr = result.GetRawPtr();
260 const double *rhs_ptr = rhs.GetRawPtr();
261
264 lhs.GetBlockSizes(rowSizes, colSizes);
265
266 unsigned int curResultRow = 0;
267 unsigned int curWrapperRow = 0;
268 unsigned int rowsInBlock = 0;
269 unsigned int columnsInBlock = 0;
270 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
271 {
272 curResultRow += rowsInBlock;
273 curWrapperRow += columnsInBlock;
274 if (blockRow == 0)
275 {
276 rowsInBlock = rowSizes[blockRow] + 1;
277 columnsInBlock = colSizes[blockRow] + 1;
278 }
279 else
280 {
281 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
282 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
283 }
284
285 if (rowsInBlock == 0)
286 {
287 continue;
288 }
289 if (columnsInBlock == 0)
290 {
291 std::fill(result.begin() + curResultRow,
292 result.begin() + curResultRow + rowsInBlock, 0.0);
293 continue;
294 }
295
296 const DNekScalMat *block = lhs.GetBlockPtr(blockRow, blockRow);
297 if (!block)
298 {
299 continue;
300 }
301
302 double *resultWrapper = result_ptr + curResultRow;
303 const double *rhsWrapper = rhs_ptr + curWrapperRow;
304
305 // Multiply
306 const unsigned int *size = block->GetSize();
307 Blas::Gemv('N', size[0], size[1], block->Scale(), block->GetRawPtr(),
308 size[0], rhsWrapper, 1, 0.0, resultWrapper, 1);
309 }
310 curResultRow += rowsInBlock;
311 if (curResultRow < result.GetRows())
312 {
313 std::fill(result.begin() + curResultRow, result.end(), 0.0);
314 }
315}
316
318 NekVector<NekSingle> &result,
319 const NekMatrix<
321 BlockMatrixTag> &lhs,
322 const NekVector<NekSingle> &rhs)
323{
324 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
325 NekSingle *result_ptr = result.GetRawPtr();
326 const NekSingle *rhs_ptr = rhs.GetRawPtr();
327
330 lhs.GetBlockSizes(rowSizes, colSizes);
331
332 unsigned int curResultRow = 0;
333 unsigned int curWrapperRow = 0;
334 unsigned int rowsInBlock = 0;
335 unsigned int columnsInBlock = 0;
336 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
337 {
338 curResultRow += rowsInBlock;
339 curWrapperRow += columnsInBlock;
340 if (blockRow == 0)
341 {
342 rowsInBlock = rowSizes[blockRow] + 1;
343 columnsInBlock = colSizes[blockRow] + 1;
344 }
345 else
346 {
347 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
348 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
349 }
350
351 if (rowsInBlock == 0)
352 {
353 continue;
354 }
355 if (columnsInBlock == 0)
356 {
357 std::fill(result.begin() + curResultRow,
358 result.begin() + curResultRow + rowsInBlock, 0.0);
359 continue;
360 }
361
362 const SNekScalMat *block = lhs.GetBlockPtr(blockRow, blockRow);
363 if (!block)
364 {
365 continue;
366 }
367
368 NekSingle *resultWrapper = result_ptr + curResultRow;
369 const NekSingle *rhsWrapper = rhs_ptr + curWrapperRow;
370
371 // Multiply
372 const unsigned int *size = block->GetSize();
373 Blas::Gemv('N', size[0], size[1], block->Scale(), block->GetRawPtr(),
374 size[0], rhsWrapper, 1, 0.0, resultWrapper, 1);
375 }
376 curResultRow += rowsInBlock;
377 if (curResultRow < result.GetRows())
378 {
379 std::fill(result.begin() + curResultRow, result.end(), 0.0);
380 }
381}
382
383template <typename DataType>
385 DataType *result, const NekMatrix<DataType, StandardMatrixTag> &lhs,
386 const DataType *rhs)
387{
388 int vectorSize = lhs.GetColumns();
389 std::copy(rhs, rhs + vectorSize, result);
390 int n = lhs.GetRows();
391 const DataType *a = lhs.GetRawPtr();
392 DataType *x = result;
393 int incx = 1;
394
395 Blas::Tpmv('L', lhs.GetTransposeFlag(), 'N', n, a, x, incx);
396}
397
398template <typename DataType>
400 DataType *result,
402 &lhs,
403 const DataType *rhs)
404{
405 NekMultiplyLowerTriangularMatrix(result, *lhs.GetOwnedMatrix(), rhs);
406
407 for (unsigned int i = 0; i < lhs.GetColumns(); ++i)
408 {
409 result[i] *= lhs.Scale();
410 }
411}
412
413template <typename DataType, typename LhsDataType, typename MatrixType>
415 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
416 const DataType *rhs)
417{
418 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
419 {
420 DataType accum = DataType(0);
421 for (unsigned int j = 0; j <= i; ++j)
422 {
423 accum += lhs(i, j) * rhs[j];
424 }
425 result[i] = accum;
426 }
427}
428
429template <typename DataType>
431 DataType *result, const NekMatrix<DataType, StandardMatrixTag> &lhs,
432 const DataType *rhs)
433{
434 int vectorSize = lhs.GetColumns();
435 std::copy(rhs, rhs + vectorSize, result);
436 int n = lhs.GetRows();
437 const DataType *a = lhs.GetRawPtr();
438 DataType *x = result;
439 int incx = 1;
440
441 Blas::Tpmv('U', lhs.GetTransposeFlag(), 'N', n, a, x, incx);
442}
443
444template <typename DataType>
446 DataType *result,
448 &lhs,
449 const DataType *rhs)
450{
451 NekMultiplyUpperTriangularMatrix(result, *lhs.GetOwnedMatrix(), rhs);
452
453 for (unsigned int i = 0; i < lhs.GetColumns(); ++i)
454 {
455 result[i] *= lhs.Scale();
456 }
457}
458
459template <typename DataType, typename LhsDataType, typename MatrixType>
461 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
462 const DataType *rhs)
463{
464 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
465 {
466 DataType accum = DataType(0);
467 for (unsigned int j = i; j < lhs.GetColumns(); ++j)
468 {
469 accum += lhs(i, j) * rhs[j];
470 }
471 result[i] = accum;
472 }
473}
474
475template <typename DataType, typename InnerMatrixType, typename MatrixTag>
477 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
478 const DataType *rhs,
479 typename std::enable_if<
481 0)
482{
483 boost::ignore_unused(p);
484
485 const unsigned int *size = lhs.GetSize();
486
487 DataType alpha = lhs.Scale();
488 const DataType *a = lhs.GetRawPtr();
489 const DataType *x = rhs;
490 int incx = 1;
491 DataType beta = 0.0;
492 DataType *y = result;
493 int incy = 1;
494
495 Blas::Spmv('U', size[0], alpha, a, x, incx, beta, y, incy);
496}
497
498template <typename DataType, typename InnerMatrixType, typename MatrixTag>
500 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
501 const DataType *rhs,
502 typename std::enable_if<
504 0)
505{
506 boost::ignore_unused(p);
507
508 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
509}
510
511template <typename DataType, typename InnerMatrixType, typename MatrixTag>
513 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
514 const DataType *rhs,
515 typename std::enable_if<
517 0)
518{
519 boost::ignore_unused(p);
520
521 const unsigned int *size = lhs.GetSize();
522
523 char t = lhs.GetTransposeFlag();
524
525 DataType alpha = lhs.Scale();
526 const DataType *a = lhs.GetRawPtr();
527 int lda = size[0];
528 const DataType *x = rhs;
529 int incx = 1;
530 DataType beta = 0.0;
531 DataType *y = result;
532 int incy = 1;
533
534 Blas::Gemv(t, size[0], size[1], alpha, a, lda, x, incx, beta, y, incy);
535}
536
537template <typename DataType, typename InnerMatrixType, typename MatrixTag>
539 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
540 const DataType *rhs,
541 typename std::enable_if<
543 0)
544{
545 boost::ignore_unused(p);
546
547 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
548}
549
550template <typename DataType, typename LhsDataType, typename MatrixType>
551void Multiply(DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
552 const DataType *rhs)
553{
554 switch (lhs.GetType())
555 {
556 case eFULL:
557 NekMultiplyFullMatrix(result, lhs, rhs);
558 break;
559 case eDIAGONAL:
560 NekMultiplyDiagonalMatrix(result, lhs, rhs);
561 break;
563 NekMultiplyUpperTriangularMatrix(result, lhs, rhs);
564 break;
566 NekMultiplyLowerTriangularMatrix(result, lhs, rhs);
567 break;
568 case eSYMMETRIC:
569 NekMultiplySymmetricMatrix(result, lhs, rhs);
570 break;
571 case eBANDED:
572 NekMultiplyBandedMatrix(result, lhs, rhs);
573 break;
577 default:
578 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
579 }
580}
581
582template <typename DataType, typename LhsDataType, typename MatrixType>
585 const NekVector<DataType> &rhs)
586{
587
588 ASSERTL1(lhs.GetColumns() == rhs.GetRows(),
589 std::string("A left side matrix with column count ") +
590 std::to_string(lhs.GetColumns()) +
591 std::string(" and a right side vector with row count ") +
592 std::to_string(rhs.GetRows()) +
593 std::string(" can't be multiplied."));
594 Multiply(result.GetRawPtr(), lhs, rhs.GetRawPtr());
595}
596
599 (1, (NekVector<NekDouble> &)), (1, (const NekVector<NekDouble> &)))
602 (1, (NekVector<NekSingle> &)), (1, (const NekVector<NekSingle> &)))
603
604template <typename DataType, typename LhsInnerMatrixType>
607 const NekVector<DataType> &rhs)
608{
609 if (lhs.GetStorageType() == eDIAGONAL)
610 {
611 DiagonalBlockMatrixMultiply(result, lhs, rhs);
612 }
613 else
614 {
615 FullBlockMatrixMultiply(result, lhs, rhs);
616 }
617}
618
621 (1, (NekVector<NekDouble> &)), (1, (const NekVector<NekDouble> &)))
624 (1, (NekVector<NekSingle> &)), (1, (const NekVector<NekSingle> &)))
625
626template <typename DataType, typename LhsDataType, typename MatrixType>
628 const NekVector<DataType> &rhs)
629{
630 NekVector<DataType> result(lhs.GetRows(), DataType(0));
631 Multiply(result, lhs, rhs);
632 return result;
633}
634
637 (1, (const NekVector<NekDouble> &)))
640 (0, ()), (1, (const NekVector<NekSingle> &)))
641
642} // namespace Nektar
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define NEKTAR_STANDARD_AND_SCALED_MATRICES
#define NEKTAR_ALL_MATRIX_TYPES
#define NEKTAR_BLOCK_MATRIX_TYPES
unsigned int GetRows() const
Definition: MatrixBase.cpp:65
char GetTransposeFlag() const
Definition: MatrixBase.cpp:122
unsigned int GetColumns() const
Definition: MatrixBase.cpp:84
unsigned int GetDimension() const
Returns the number of dimensions for the point.
Definition: NekVector.cpp:201
unsigned int GetRows() const
Definition: NekVector.cpp:206
iterator begin()
Definition: NekVector.cpp:235
iterator end()
Definition: NekVector.cpp:241
DataType * GetRawPtr()
Definition: NekVector.cpp:211
static void Gemv(const char &trans, const int &m, const int &n, const double &alpha, const double *a, const int &lda, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[m x n].
Definition: Blas.hpp:193
static void Gbmv(const char &trans, const int &m, const int &n, const int &kl, const int &ku, const double &alpha, const double *a, const int &lda, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[m x n] is banded.
Definition: Blas.hpp:223
static void Tpmv(const char &uplo, const char &trans, const char &diag, const int &n, const double *ap, double *x, const int &incx)
BLAS level 2: Matrix vector multiply x = alpha A x where A[n x n].
Definition: Blas.hpp:312
static void Spmv(const char &uplo, const int &n, const double &alpha, const double *a, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[n x n] is symmetric packed.
Definition: Blas.hpp:256
def copy(self)
Definition: pycml.py:2663
@ beta
Gauss Radau pinned at x=-1,.
Definition: PointsType.h:61
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
SNekMat NEKTAR_GENERATE_EXPLICIT_FUNCTION_INSTANTIATION_SINGLE_MATRIX(AddEqualNegatedLhs, NEKTAR_ALL_MATRIX_TYPES,(1,(void)),(1,(DNekMat &)),(0,())) NEKTAR_GENERATE_EXPLICIT_FUNCTION_INSTANTIATION_SINGLE_MATRIX(AddEqualNegatedLhs
void NekMultiplyFullMatrix(DataType *result, const NekMatrix< InnerMatrixType, MatrixTag > &lhs, const DataType *rhs, typename std::enable_if< CanGetRawPtr< NekMatrix< InnerMatrixType, MatrixTag > >::value >::type *p=0)
void DiagonalBlockMatrixMultiply(NekVector< DataType > &result, const NekMatrix< LhsInnerMatrixType, BlockMatrixTag > &lhs, const NekVector< DataType > &rhs)
void Multiply(NekMatrix< ResultDataType, StandardMatrixTag > &result, const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const ResultDataType &rhs)
void NekMultiplyLowerTriangularMatrix(DataType *result, const NekMatrix< DataType, StandardMatrixTag > &lhs, const DataType *rhs)
NEKTAR_ALL_MATRIX_TYPES_SINGLE
void NekMultiplyDiagonalMatrix(DataType *result, const NekMatrix< LhsDataType, MatrixType > &lhs, const DataType *rhs)
void NekMultiplySymmetricMatrix(DataType *result, const NekMatrix< InnerMatrixType, MatrixTag > &lhs, const DataType *rhs, typename std::enable_if< CanGetRawPtr< NekMatrix< InnerMatrixType, MatrixTag > >::value >::type *p=0)
void DiagonalBlockFullScalMatrixMultiply(NekVector< double > &result, const NekMatrix< NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag >, BlockMatrixTag > &lhs, const NekVector< double > &rhs)
void NekMultiplyBandedMatrix(DataType *result, const NekMatrix< LhsDataType, MatrixType > &lhs, const DataType *rhs, typename std::enable_if< CanGetRawPtr< NekMatrix< LhsDataType, MatrixType > >::value >::type *p=0)
void NekMultiplyUnspecializedMatrixType(DataType *result, const NekMatrix< LhsDataType, MatrixType > &lhs, const DataType *rhs)
@ eLOWER_TRIANGULAR_BANDED
@ eUPPER_TRIANGULAR_BANDED
void FullBlockMatrixMultiply(NekVector< DataType > &result, const NekMatrix< LhsInnerMatrixType, BlockMatrixTag > &lhs, const NekVector< DataType > &rhs)
void NekMultiplyUpperTriangularMatrix(DataType *result, const NekMatrix< DataType, StandardMatrixTag > &lhs, const DataType *rhs)
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:207