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
39
40namespace Nektar
41{
42
43template <typename DataType, typename LhsDataType, typename MatrixType>
45 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
46 const DataType *rhs)
47{
48 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
49 {
50 DataType accum = DataType(0);
51 for (unsigned int j = 0; j < lhs.GetColumns(); ++j)
52 {
53 accum += lhs(i, j) * rhs[j];
54 }
55 result[i] = accum;
56 }
57}
58
59template <typename DataType, typename LhsDataType, typename MatrixType>
60void NekMultiplyDiagonalMatrix(DataType *result,
62 const DataType *rhs)
63{
64 int n = lhs.GetRows();
65 for (unsigned int i = 0; i < n; ++i)
66 {
67 result[i] = lhs(i, i) * rhs[i];
68 }
69}
70
71template <typename DataType, typename LhsDataType>
73 DataType *result, const NekMatrix<LhsDataType, StandardMatrixTag> &lhs,
74 const DataType *rhs)
75{
76 int n = lhs.GetRows();
77 const DataType *mat_ptr = lhs.GetRawPtr();
78 Vmath::Vmul(n, mat_ptr, 1, rhs, 1, result, 1);
79}
80
81template <typename DataType, typename LhsDataType, typename MatrixType>
83 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
84 const DataType *rhs,
85 [[maybe_unused]] typename std::enable_if<
87 nullptr)
88{
89 int m = lhs.GetRows();
90 int n = lhs.GetColumns();
91 int kl = lhs.GetNumberOfSubDiagonals();
92 int ku = lhs.GetNumberOfSuperDiagonals();
93 DataType alpha = lhs.Scale();
94 const DataType *a = lhs.GetRawPtr();
95 int lda = kl + ku + 1;
96 const DataType *x = rhs;
97 int incx = 1;
98 DataType beta = 0.0;
99 DataType *y = result;
100 int incy = 1;
101 Blas::Gbmv('N', m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy);
102}
103
104template <typename DataType, typename LhsDataType>
106 [[maybe_unused]] DataType *result,
107 [[maybe_unused]] const NekMatrix<LhsDataType, BlockMatrixTag> &lhs,
108 [[maybe_unused]] const DataType *rhs,
109 [[maybe_unused]] typename std::enable_if<
111 nullptr)
112{
114 "Banded block matrix multiplication not yet implemented");
115}
116
117template <typename DataType, typename LhsInnerMatrixType>
119 NekVector<DataType> &result,
121 const NekVector<DataType> &rhs)
122{
123 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
124 unsigned int numberOfBlockColumns = lhs.GetNumberOfBlockColumns();
125 DataType *result_ptr = result.GetRawPtr();
126 const DataType *rhs_ptr = rhs.GetRawPtr();
127
128 for (unsigned int i = 0; i < result.GetDimension(); ++i)
129 {
130 result_ptr[i] = DataType(0);
131 }
132 Array<OneD, DataType> temp(result.GetDimension());
133 DataType *temp_ptr = temp.get();
134
135 unsigned int curResultRow = 0;
136 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
137 {
138 unsigned int rowsInBlock = lhs.GetNumberOfRowsInBlockRow(blockRow);
139
140 if (blockRow != 0)
141 {
142 curResultRow += lhs.GetNumberOfRowsInBlockRow(blockRow - 1);
143 }
144
145 if (rowsInBlock == 0)
146 {
147 continue;
148 }
149
150 DataType *resultWrapper = result_ptr + curResultRow;
151
152 unsigned int curWrapperRow = 0;
153 for (unsigned int blockColumn = 0; blockColumn < numberOfBlockColumns;
154 ++blockColumn)
155 {
156 if (blockColumn != 0)
157 {
158 curWrapperRow +=
159 lhs.GetNumberOfColumnsInBlockColumn(blockColumn - 1);
160 }
161
162 const LhsInnerMatrixType *block =
163 lhs.GetBlockPtr(blockRow, blockColumn);
164 if (!block)
165 {
166 continue;
167 }
168
169 unsigned int columnsInBlock =
170 lhs.GetNumberOfColumnsInBlockColumn(blockColumn);
171 if (columnsInBlock == 0)
172 {
173 continue;
174 }
175
176 const DataType *rhsWrapper = rhs_ptr + curWrapperRow;
177 Multiply(temp_ptr, *block, rhsWrapper);
178 for (unsigned int i = 0; i < rowsInBlock; ++i)
179 {
180 resultWrapper[i] += temp_ptr[i];
181 }
182 }
183 }
184}
185
186template <typename DataType, typename LhsInnerMatrixType>
188 NekVector<DataType> &result,
190 const NekVector<DataType> &rhs)
191{
192 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
193 DataType *result_ptr = result.GetRawPtr();
194 const DataType *rhs_ptr = rhs.GetRawPtr();
195
198 lhs.GetBlockSizes(rowSizes, colSizes);
199
200 unsigned int curResultRow = 0;
201 unsigned int curWrapperRow = 0;
202 unsigned int rowsInBlock = 0;
203 unsigned int columnsInBlock = 0;
204 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
205 {
206 curResultRow += rowsInBlock;
207 curWrapperRow += columnsInBlock;
208 if (blockRow == 0)
209 {
210 rowsInBlock = rowSizes[blockRow] + 1;
211 columnsInBlock = colSizes[blockRow] + 1;
212 }
213 else
214 {
215 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
216 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
217 }
218
219 if (rowsInBlock == 0)
220 {
221 continue;
222 }
223 if (columnsInBlock == 0)
224 {
225 std::fill(result.begin() + curResultRow,
226 result.begin() + curResultRow + rowsInBlock, 0.0);
227 continue;
228 }
229
230 const LhsInnerMatrixType *block = lhs.GetBlockPtr(blockRow, blockRow);
231 if (!block)
232 {
233 continue;
234 }
235
236 DataType *resultWrapper = result_ptr + curResultRow;
237 const DataType *rhsWrapper = rhs_ptr + curWrapperRow;
238 Multiply(resultWrapper, *block, rhsWrapper);
239 }
240 curResultRow += rowsInBlock;
241 if (curResultRow < result.GetRows())
242 {
243 std::fill(result.begin() + curResultRow, result.end(), 0.0);
244 }
245}
246
248 NekVector<double> &result,
249 const NekMatrix<
251 BlockMatrixTag> &lhs,
252 const NekVector<double> &rhs)
253{
254 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
255 double *result_ptr = result.GetRawPtr();
256 const double *rhs_ptr = rhs.GetRawPtr();
257
260 lhs.GetBlockSizes(rowSizes, colSizes);
261
262 unsigned int curResultRow = 0;
263 unsigned int curWrapperRow = 0;
264 unsigned int rowsInBlock = 0;
265 unsigned int columnsInBlock = 0;
266 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
267 {
268 curResultRow += rowsInBlock;
269 curWrapperRow += columnsInBlock;
270 if (blockRow == 0)
271 {
272 rowsInBlock = rowSizes[blockRow] + 1;
273 columnsInBlock = colSizes[blockRow] + 1;
274 }
275 else
276 {
277 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
278 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
279 }
280
281 if (rowsInBlock == 0)
282 {
283 continue;
284 }
285 if (columnsInBlock == 0)
286 {
287 std::fill(result.begin() + curResultRow,
288 result.begin() + curResultRow + rowsInBlock, 0.0);
289 continue;
290 }
291
292 const DNekScalMat *block = lhs.GetBlockPtr(blockRow, blockRow);
293 if (!block)
294 {
295 continue;
296 }
297
298 double *resultWrapper = result_ptr + curResultRow;
299 const double *rhsWrapper = rhs_ptr + curWrapperRow;
300
301 // Multiply
302 const unsigned int *size = block->GetSize();
303 Blas::Gemv('N', size[0], size[1], block->Scale(), block->GetRawPtr(),
304 size[0], rhsWrapper, 1, 0.0, resultWrapper, 1);
305 }
306 curResultRow += rowsInBlock;
307 if (curResultRow < result.GetRows())
308 {
309 std::fill(result.begin() + curResultRow, result.end(), 0.0);
310 }
311}
312
314 NekVector<NekSingle> &result,
315 const NekMatrix<
317 BlockMatrixTag> &lhs,
318 const NekVector<NekSingle> &rhs)
319{
320 unsigned int numberOfBlockRows = lhs.GetNumberOfBlockRows();
321 NekSingle *result_ptr = result.GetRawPtr();
322 const NekSingle *rhs_ptr = rhs.GetRawPtr();
323
326 lhs.GetBlockSizes(rowSizes, colSizes);
327
328 unsigned int curResultRow = 0;
329 unsigned int curWrapperRow = 0;
330 unsigned int rowsInBlock = 0;
331 unsigned int columnsInBlock = 0;
332 for (unsigned int blockRow = 0; blockRow < numberOfBlockRows; ++blockRow)
333 {
334 curResultRow += rowsInBlock;
335 curWrapperRow += columnsInBlock;
336 if (blockRow == 0)
337 {
338 rowsInBlock = rowSizes[blockRow] + 1;
339 columnsInBlock = colSizes[blockRow] + 1;
340 }
341 else
342 {
343 rowsInBlock = rowSizes[blockRow] - rowSizes[blockRow - 1];
344 columnsInBlock = colSizes[blockRow] - colSizes[blockRow - 1];
345 }
346
347 if (rowsInBlock == 0)
348 {
349 continue;
350 }
351 if (columnsInBlock == 0)
352 {
353 std::fill(result.begin() + curResultRow,
354 result.begin() + curResultRow + rowsInBlock, 0.0);
355 continue;
356 }
357
358 const SNekScalMat *block = lhs.GetBlockPtr(blockRow, blockRow);
359 if (!block)
360 {
361 continue;
362 }
363
364 NekSingle *resultWrapper = result_ptr + curResultRow;
365 const NekSingle *rhsWrapper = rhs_ptr + curWrapperRow;
366
367 // Multiply
368 const unsigned int *size = block->GetSize();
369 Blas::Gemv('N', size[0], size[1], block->Scale(), block->GetRawPtr(),
370 size[0], rhsWrapper, 1, 0.0, resultWrapper, 1);
371 }
372 curResultRow += rowsInBlock;
373 if (curResultRow < result.GetRows())
374 {
375 std::fill(result.begin() + curResultRow, result.end(), 0.0);
376 }
377}
378
379template <typename DataType>
381 DataType *result, const NekMatrix<DataType, StandardMatrixTag> &lhs,
382 const DataType *rhs)
383{
384 int vectorSize = lhs.GetColumns();
385 std::copy(rhs, rhs + vectorSize, result);
386 int n = lhs.GetRows();
387 const DataType *a = lhs.GetRawPtr();
388 DataType *x = result;
389 int incx = 1;
390
391 Blas::Tpmv('L', lhs.GetTransposeFlag(), 'N', n, a, x, incx);
392}
393
394template <typename DataType>
396 DataType *result,
398 &lhs,
399 const DataType *rhs)
400{
401 NekMultiplyLowerTriangularMatrix(result, *lhs.GetOwnedMatrix(), rhs);
402
403 for (unsigned int i = 0; i < lhs.GetColumns(); ++i)
404 {
405 result[i] *= lhs.Scale();
406 }
407}
408
409template <typename DataType, typename LhsDataType, typename MatrixType>
411 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
412 const DataType *rhs)
413{
414 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
415 {
416 DataType accum = DataType(0);
417 for (unsigned int j = 0; j <= i; ++j)
418 {
419 accum += lhs(i, j) * rhs[j];
420 }
421 result[i] = accum;
422 }
423}
424
425template <typename DataType>
427 DataType *result, const NekMatrix<DataType, StandardMatrixTag> &lhs,
428 const DataType *rhs)
429{
430 int vectorSize = lhs.GetColumns();
431 std::copy(rhs, rhs + vectorSize, result);
432 int n = lhs.GetRows();
433 const DataType *a = lhs.GetRawPtr();
434 DataType *x = result;
435 int incx = 1;
436
437 Blas::Tpmv('U', lhs.GetTransposeFlag(), 'N', n, a, x, incx);
438}
439
440template <typename DataType>
442 DataType *result,
444 &lhs,
445 const DataType *rhs)
446{
447 NekMultiplyUpperTriangularMatrix(result, *lhs.GetOwnedMatrix(), rhs);
448
449 for (unsigned int i = 0; i < lhs.GetColumns(); ++i)
450 {
451 result[i] *= lhs.Scale();
452 }
453}
454
455template <typename DataType, typename LhsDataType, typename MatrixType>
457 DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
458 const DataType *rhs)
459{
460 for (unsigned int i = 0; i < lhs.GetRows(); ++i)
461 {
462 DataType accum = DataType(0);
463 for (unsigned int j = i; j < lhs.GetColumns(); ++j)
464 {
465 accum += lhs(i, j) * rhs[j];
466 }
467 result[i] = accum;
468 }
469}
470
471template <typename DataType, typename InnerMatrixType, typename MatrixTag>
473 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
474 const DataType *rhs,
475 [[maybe_unused]] typename std::enable_if<
477 nullptr)
478{
479 const unsigned int *size = lhs.GetSize();
480
481 DataType alpha = lhs.Scale();
482 const DataType *a = lhs.GetRawPtr();
483 const DataType *x = rhs;
484 int incx = 1;
485 DataType beta = 0.0;
486 DataType *y = result;
487 int incy = 1;
488
489 Blas::Spmv('U', size[0], alpha, a, x, incx, beta, y, incy);
490}
491
492template <typename DataType, typename InnerMatrixType, typename MatrixTag>
494 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
495 const DataType *rhs,
496 [[maybe_unused]] typename std::enable_if<
498 nullptr)
499{
500 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
501}
502
503template <typename DataType, typename InnerMatrixType, typename MatrixTag>
505 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
506 const DataType *rhs,
507 [[maybe_unused]] typename std::enable_if<
509 nullptr)
510{
511 const unsigned int *size = lhs.GetSize();
512
513 char t = lhs.GetTransposeFlag();
514
515 DataType alpha = lhs.Scale();
516 const DataType *a = lhs.GetRawPtr();
517 int lda = size[0];
518 const DataType *x = rhs;
519 int incx = 1;
520 DataType beta = 0.0;
521 DataType *y = result;
522 int incy = 1;
523
524 Blas::Gemv(t, size[0], size[1], alpha, a, lda, x, incx, beta, y, incy);
525}
526
527template <typename DataType, typename InnerMatrixType, typename MatrixTag>
529 DataType *result, const NekMatrix<InnerMatrixType, MatrixTag> &lhs,
530 const DataType *rhs,
531 [[maybe_unused]] typename std::enable_if<
533 nullptr)
534{
535 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
536}
537
538template <typename DataType, typename LhsDataType, typename MatrixType>
539void Multiply(DataType *result, const NekMatrix<LhsDataType, MatrixType> &lhs,
540 const DataType *rhs)
541{
542 switch (lhs.GetType())
543 {
544 case eFULL:
545 NekMultiplyFullMatrix(result, lhs, rhs);
546 break;
547 case eDIAGONAL:
548 NekMultiplyDiagonalMatrix(result, lhs, rhs);
549 break;
551 NekMultiplyUpperTriangularMatrix(result, lhs, rhs);
552 break;
554 NekMultiplyLowerTriangularMatrix(result, lhs, rhs);
555 break;
556 case eSYMMETRIC:
557 NekMultiplySymmetricMatrix(result, lhs, rhs);
558 break;
559 case eBANDED:
560 NekMultiplyBandedMatrix(result, lhs, rhs);
561 break;
565 default:
566 NekMultiplyUnspecializedMatrixType(result, lhs, rhs);
567 }
568}
569
570template <typename DataType, typename LhsDataType, typename MatrixType>
573 const NekVector<DataType> &rhs)
574{
575
576 ASSERTL1(lhs.GetColumns() == rhs.GetRows(),
577 std::string("A left side matrix with column count ") +
578 std::to_string(lhs.GetColumns()) +
579 std::string(" and a right side vector with row count ") +
580 std::to_string(rhs.GetRows()) +
581 std::string(" can't be multiplied."));
582 Multiply(result.GetRawPtr(), lhs, rhs.GetRawPtr());
583}
584
587 (1, (NekVector<NekDouble> &)), (1, (const NekVector<NekDouble> &)))
590 (1, (NekVector<NekSingle> &)), (1, (const NekVector<NekSingle> &)))
591
592template <typename DataType, typename LhsInnerMatrixType>
595 const NekVector<DataType> &rhs)
596{
597 if (lhs.GetStorageType() == eDIAGONAL)
598 {
599 DiagonalBlockMatrixMultiply(result, lhs, rhs);
600 }
601 else
602 {
603 FullBlockMatrixMultiply(result, lhs, rhs);
604 }
605}
606
609 (1, (NekVector<NekDouble> &)), (1, (const NekVector<NekDouble> &)))
612 (1, (NekVector<NekSingle> &)), (1, (const NekVector<NekSingle> &)))
613
614template <typename DataType, typename LhsDataType, typename MatrixType>
616 const NekVector<DataType> &rhs)
617{
618 NekVector<DataType> result(lhs.GetRows(), DataType(0));
619 Multiply(result, lhs, rhs);
620 return result;
621}
622
625 (1, (const NekVector<NekDouble> &)))
628 (0, ()), (1, (const NekVector<NekSingle> &)))
629
630} // 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:202
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
#define NEKTAR_STANDARD_AND_SCALED_MATRICES
#define NEKTAR_ALL_MATRIX_TYPES
#define NEKTAR_BLOCK_MATRIX_TYPES
unsigned int GetRows() const
Definition: MatrixBase.cpp:61
char GetTransposeFlag() const
Definition: MatrixBase.cpp:104
unsigned int GetColumns() const
Definition: MatrixBase.cpp:73
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:191
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:221
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:310
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:254
def copy(self)
Definition: pycml.py:2663
@ beta
Gauss Radau pinned at x=-1,.
Definition: PointsType.h:59
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 DiagonalBlockMatrixMultiply(NekVector< DataType > &result, const NekMatrix< LhsInnerMatrixType, BlockMatrixTag > &lhs, const NekVector< 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=nullptr)
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 DiagonalBlockFullScalMatrixMultiply(NekVector< double > &result, const NekMatrix< NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag >, BlockMatrixTag > &lhs, const NekVector< double > &rhs)
void NekMultiplyUnspecializedMatrixType(DataType *result, const NekMatrix< LhsDataType, MatrixType > &lhs, const DataType *rhs)
void NekMultiplyFullMatrix(DataType *result, const NekMatrix< InnerMatrixType, MatrixTag > &lhs, const DataType *rhs, typename std::enable_if< CanGetRawPtr< NekMatrix< InnerMatrixType, MatrixTag > >::value >::type *p=nullptr)
@ eLOWER_TRIANGULAR_BANDED
@ eUPPER_TRIANGULAR_BANDED
void FullBlockMatrixMultiply(NekVector< DataType > &result, const NekMatrix< LhsInnerMatrixType, BlockMatrixTag > &lhs, const NekVector< DataType > &rhs)
void NekMultiplyBandedMatrix(DataType *result, const NekMatrix< LhsDataType, MatrixType > &lhs, const DataType *rhs, typename std::enable_if< CanGetRawPtr< NekMatrix< LhsDataType, MatrixType > >::value >::type *p=nullptr)
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.hpp:72