ViennaCL - The Vienna Computing Library  1.5.2
execute_matrix_prod.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_SCHEDULER_EXECUTE_MATRIX_PROD_HPP
2 #define VIENNACL_SCHEDULER_EXECUTE_MATRIX_PROD_HPP
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8  Portions of this software are copyright by UChicago Argonne, LLC.
9 
10  -----------------
11  ViennaCL - The Vienna Computing Library
12  -----------------
13 
14  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15 
16  (A list of authors and contributors can be found in the PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
21 
26 #include "viennacl/forwards.h"
35 #include "viennacl/ell_matrix.hpp"
36 #include "viennacl/hyb_matrix.hpp"
37 
38 namespace viennacl
39 {
40  namespace scheduler
41  {
42  namespace detail
43  {
44  inline bool matrix_prod_temporary_required(statement const & s, lhs_rhs_element const & elem)
45  {
47  return false;
48 
49  // check composite node for being a transposed matrix proxy:
50  statement_node const & leaf = s.array()[elem.node_index];
52  return false;
53 
54  return true;
55  }
56 
57  inline void matrix_matrix_prod(statement const & s,
58  lhs_rhs_element result,
59  lhs_rhs_element const & A,
60  lhs_rhs_element const & B,
61  double alpha,
62  double beta)
63  {
64  if (A.type_family == MATRIX_TYPE_FAMILY && B.type_family == MATRIX_TYPE_FAMILY) // C = A * B
65  {
66  assert( A.numeric_type == B.numeric_type && bool("Numeric type not the same!"));
67  assert( result.numeric_type == B.numeric_type && bool("Numeric type not the same!"));
68 
69 #define VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD(LAYOUTA, MEMBERA, LAYOUTB, MEMBERB, LAYOUTC, MEMBERC)\
70  if (A.subtype == LAYOUTA && B.subtype == LAYOUTB && result.subtype == LAYOUTC)\
71  {\
72  switch (result.numeric_type)\
73  {\
74  case FLOAT_TYPE:\
75  viennacl::linalg::prod_impl(*A.matrix_##MEMBERA##_float, *B.matrix_##MEMBERB##_float, *result.matrix_##MEMBERC##_float, static_cast<float>(alpha), static_cast<float>(beta)); break;\
76  case DOUBLE_TYPE:\
77  viennacl::linalg::prod_impl(*A.matrix_##MEMBERA##_double, *B.matrix_##MEMBERB##_double, *result.matrix_##MEMBERC##_double, alpha, beta); break;\
78  default:\
79  throw statement_not_supported_exception("Invalid numeric type in matrix-matrix multiplication");\
80  }\
81  }
82 
85 
88 
91 
94 
95 #undef VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD
96  }
97  else if (A.type_family == MATRIX_TYPE_FAMILY && B.type_family == COMPOSITE_OPERATION_FAMILY) // C = A * B^T
98  {
99  statement_node const & leaf = s.array()[B.node_index];
100 
101  assert(leaf.lhs.type_family == MATRIX_TYPE_FAMILY && leaf.op.type == OPERATION_UNARY_TRANS_TYPE && bool("Logic error: Argument not a matrix transpose!"));
102  assert(leaf.lhs.numeric_type == result.numeric_type && bool("Numeric type not the same!"));
103  assert(result.numeric_type == A.numeric_type && bool("Numeric type not the same!"));
104 
105 #define VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD(LAYOUTA, MEMBERA, LAYOUTB, MEMBERB, MAJORB, LAYOUTC, MEMBERC)\
106  if (A.subtype == LAYOUTA && leaf.lhs.subtype == LAYOUTB && result.subtype == LAYOUTC)\
107  {\
108  switch (result.numeric_type)\
109  {\
110  case FLOAT_TYPE:\
111  viennacl::linalg::prod_impl(*A.matrix_##MEMBERA##_float, \
112  viennacl::matrix_expression< const matrix_base<float, MAJORB>,\
113  const matrix_base<float, MAJORB>,\
114  op_trans> (*(leaf.lhs.matrix_##MEMBERB##_float), *(leaf.lhs.matrix_##MEMBERB##_float)), \
115  *result.matrix_##MEMBERC##_float, static_cast<float>(alpha), static_cast<float>(beta)); break;\
116  case DOUBLE_TYPE:\
117  viennacl::linalg::prod_impl(*A.matrix_##MEMBERA##_double,\
118  viennacl::matrix_expression< const matrix_base<double, MAJORB>,\
119  const matrix_base<double, MAJORB>,\
120  op_trans>(*(leaf.lhs.matrix_##MEMBERB##_double), *(leaf.lhs.matrix_##MEMBERB##_double)), \
121  *result.matrix_##MEMBERC##_double, alpha, beta); break;\
122  default:\
123  throw statement_not_supported_exception("Invalid numeric type in matrix-matrix multiplication");\
124  }\
125  }
126 
129 
132 
135 
138 
139 #undef VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD
140  }
141  else if (A.type_family == COMPOSITE_OPERATION_FAMILY && B.type_family == MATRIX_TYPE_FAMILY) // C = A^T * B
142  {
143  statement_node const & leaf = s.array()[A.node_index];
144 
145  assert(leaf.lhs.type_family == MATRIX_TYPE_FAMILY && leaf.op.type == OPERATION_UNARY_TRANS_TYPE && bool("Logic error: Argument not a matrix transpose!"));
146  assert(leaf.lhs.numeric_type == result.numeric_type && bool("Numeric type not the same!"));
147  assert(result.numeric_type == B.numeric_type && bool("Numeric type not the same!"));
148 
149 #define VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD(LAYOUTA, MEMBERA, MAJORA, LAYOUTB, MEMBERB, LAYOUTC, MEMBERC)\
150  if (leaf.lhs.subtype == LAYOUTA && B.subtype == LAYOUTB && result.subtype == LAYOUTC)\
151  {\
152  switch (result.numeric_type)\
153  {\
154  case FLOAT_TYPE:\
155  viennacl::linalg::prod_impl(viennacl::matrix_expression< const matrix_base<float, MAJORA>,\
156  const matrix_base<float, MAJORA>,\
157  op_trans>(*leaf.lhs.matrix_##MEMBERA##_float, *leaf.lhs.matrix_##MEMBERA##_float), \
158  *B.matrix_##MEMBERB##_float,\
159  *result.matrix_##MEMBERC##_float, static_cast<float>(alpha), static_cast<float>(beta)); break;\
160  case DOUBLE_TYPE:\
161  viennacl::linalg::prod_impl(viennacl::matrix_expression< const matrix_base<double, MAJORA>,\
162  const matrix_base<double, MAJORA>,\
163  op_trans>(*leaf.lhs.matrix_##MEMBERA##_double, *leaf.lhs.matrix_##MEMBERA##_double), \
164  *B.matrix_##MEMBERB##_double,\
165  *result.matrix_##MEMBERC##_double, alpha, beta); break;\
166  default:\
167  throw statement_not_supported_exception("Invalid numeric type in matrix-matrix multiplication");\
168  }\
169  }
170 
173 
176 
179 
182 
183 #undef VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD
184  }
185  else if (A.type_family == COMPOSITE_OPERATION_FAMILY && B.type_family == COMPOSITE_OPERATION_FAMILY) // C = A^T * B^T
186  {
187  statement_node const & leafA = s.array()[A.node_index];
188  statement_node const & leafB = s.array()[B.node_index];
189 
190  assert(leafA.lhs.type_family == MATRIX_TYPE_FAMILY && leafA.op.type == OPERATION_UNARY_TRANS_TYPE && bool("Logic error: Argument not a matrix transpose!"));
191  assert(leafB.lhs.type_family == MATRIX_TYPE_FAMILY && leafB.op.type == OPERATION_UNARY_TRANS_TYPE && bool("Logic error: Argument not a matrix transpose!"));
192  assert(leafA.lhs.numeric_type == result.numeric_type && bool("Numeric type not the same!"));
193  assert(leafB.lhs.numeric_type == result.numeric_type && bool("Numeric type not the same!"));
194 
195 #define VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD(LAYOUTA, MEMBERA, MAJORA, LAYOUTB, MEMBERB, MAJORB, LAYOUTC, MEMBERC)\
196  if (leafA.lhs.subtype == LAYOUTA && leafB.lhs.subtype == LAYOUTB && result.subtype == LAYOUTC)\
197  {\
198  switch (result.numeric_type)\
199  {\
200  case FLOAT_TYPE:\
201  viennacl::linalg::prod_impl(viennacl::matrix_expression< const matrix_base<float, MAJORA>,\
202  const matrix_base<float, MAJORA>,\
203  op_trans>(*leafA.lhs.matrix_##MEMBERA##_float, *leafA.lhs.matrix_##MEMBERA##_float), \
204  viennacl::matrix_expression< const matrix_base<float, MAJORB>,\
205  const matrix_base<float, MAJORB>,\
206  op_trans>(*leafB.lhs.matrix_##MEMBERB##_float, *leafB.lhs.matrix_##MEMBERB##_float), \
207  *result.matrix_##MEMBERC##_float, static_cast<float>(alpha), static_cast<float>(beta)); break;\
208  case DOUBLE_TYPE:\
209  viennacl::linalg::prod_impl(viennacl::matrix_expression< const matrix_base<double, MAJORA>,\
210  const matrix_base<double, MAJORA>,\
211  op_trans>(*leafA.lhs.matrix_##MEMBERA##_double, *leafA.lhs.matrix_##MEMBERA##_double), \
212  viennacl::matrix_expression< const matrix_base<double, MAJORB>,\
213  const matrix_base<double, MAJORB>,\
214  op_trans>(*leafB.lhs.matrix_##MEMBERB##_double, *leafB.lhs.matrix_##MEMBERB##_double), \
215  *result.matrix_##MEMBERC##_double, alpha, beta); break;\
216  default:\
217  throw statement_not_supported_exception("Invalid numeric type in matrix-matrix multiplication");\
218  }\
219  }
220 
223 
226 
229 
232 
233 #undef VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD
234  }
235  else
236  throw statement_not_supported_exception("Matrix-matrix multiplication encountered operands being neither dense matrices nor transposed dense matrices");
237  }
238 
239  inline void matrix_vector_prod(statement const & s,
240  lhs_rhs_element result,
241  lhs_rhs_element const & A,
242  lhs_rhs_element const & x)
243  {
244  assert( result.numeric_type == x.numeric_type && bool("Numeric type not the same!"));
245  assert( result.type_family == x.type_family && bool("Subtype not the same!"));
246  assert( result.subtype == DENSE_VECTOR_TYPE && bool("Result node for matrix-vector product not a vector type!"));
247 
248  // deal with transposed product first:
249  // switch: trans for A
250  if (A.type_family == COMPOSITE_OPERATION_FAMILY) // prod(trans(A), x)
251  {
252  statement_node const & leaf = s.array()[A.node_index];
253 
254  assert(leaf.lhs.type_family == MATRIX_TYPE_FAMILY && leaf.op.type == OPERATION_UNARY_TRANS_TYPE && bool("Logic error: Argument not a matrix transpose!"));
255  assert(leaf.lhs.numeric_type == x.numeric_type && bool("Numeric type not the same!"));
256 
257  if (leaf.lhs.subtype == DENSE_ROW_MATRIX_TYPE)
258  {
259  switch (leaf.lhs.numeric_type)
260  {
261  case FLOAT_TYPE:
265  *x.vector_float,
266  *result.vector_float); break;
267  case DOUBLE_TYPE:
271  *x.vector_double,
272  *result.vector_double); break;
273  default:
274  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
275  }
276  }
277  else if (leaf.lhs.subtype == DENSE_COL_MATRIX_TYPE)
278  {
279  switch (leaf.lhs.numeric_type)
280  {
281  case FLOAT_TYPE:
285  *x.vector_float,
286  *result.vector_float); break;
287  case DOUBLE_TYPE:
291  *x.vector_double,
292  *result.vector_double); break;
293  default:
294  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
295  }
296  }
297  else
298  throw statement_not_supported_exception("Invalid matrix type for transposed matrix-vector product");
299  }
300  else if (A.subtype == DENSE_ROW_MATRIX_TYPE)
301  {
302  switch (A.numeric_type)
303  {
304  case FLOAT_TYPE:
306  break;
307  case DOUBLE_TYPE:
309  break;
310  default:
311  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
312  }
313  }
314  else if (A.subtype == DENSE_COL_MATRIX_TYPE)
315  {
316  switch (A.numeric_type)
317  {
318  case FLOAT_TYPE:
320  break;
321  case DOUBLE_TYPE:
323  break;
324  default:
325  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
326  }
327  }
328  else if (A.subtype == COMPRESSED_MATRIX_TYPE)
329  {
330  switch (A.numeric_type)
331  {
332  case FLOAT_TYPE:
334  break;
335  case DOUBLE_TYPE:
337  break;
338  default:
339  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
340  }
341  }
342  else if (A.subtype == COORDINATE_MATRIX_TYPE)
343  {
344  switch (A.numeric_type)
345  {
346  case FLOAT_TYPE:
348  break;
349  case DOUBLE_TYPE:
351  break;
352  default:
353  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
354  }
355  }
356  else if (A.subtype == ELL_MATRIX_TYPE)
357  {
358  switch (A.numeric_type)
359  {
360  case FLOAT_TYPE:
362  break;
363  case DOUBLE_TYPE:
365  break;
366  default:
367  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
368  }
369  }
370  else if (A.subtype == HYB_MATRIX_TYPE)
371  {
372  switch (A.numeric_type)
373  {
374  case FLOAT_TYPE:
376  break;
377  case DOUBLE_TYPE:
379  break;
380  default:
381  throw statement_not_supported_exception("Invalid numeric type in matrix-{matrix,vector} multiplication");
382  }
383  }
384  else
385  {
386  std::cout << "A.subtype: " << A.subtype << std::endl;
387  throw statement_not_supported_exception("Invalid matrix type for matrix-vector product");
388  }
389  }
390 
391  } // namespace detail
392 
393  inline void execute_matrix_prod(statement const & s, statement_node const & root_node)
394  {
395  statement_node const & leaf = s.array()[root_node.rhs.node_index];
396 
397  // Part 1: Check whether temporaries are required //
398 
399  statement_node new_root_lhs;
400  statement_node new_root_rhs;
401 
402  bool lhs_needs_temporary = detail::matrix_prod_temporary_required(s, leaf.lhs);
403  bool rhs_needs_temporary = detail::matrix_prod_temporary_required(s, leaf.rhs);
404 
405  // check for temporary on lhs:
406  if (lhs_needs_temporary)
407  {
408  std::cout << "Temporary for LHS!" << std::endl;
409  detail::new_element(new_root_lhs.lhs, root_node.lhs);
410 
412  new_root_lhs.op.type = OPERATION_BINARY_ASSIGN_TYPE;
413 
415  new_root_lhs.rhs.subtype = INVALID_SUBTYPE;
416  new_root_lhs.rhs.numeric_type = INVALID_NUMERIC_TYPE;
417  new_root_lhs.rhs.node_index = leaf.lhs.node_index;
418 
419  // work on subexpression:
420  // TODO: Catch exception, free temporary, then rethrow
421  detail::execute_composite(s, new_root_lhs);
422  }
423 
424  // check for temporary on rhs:
425  if (rhs_needs_temporary)
426  {
427  detail::new_element(new_root_rhs.lhs, root_node.lhs);
428 
430  new_root_rhs.op.type = OPERATION_BINARY_ASSIGN_TYPE;
431 
433  new_root_rhs.rhs.subtype = INVALID_SUBTYPE;
434  new_root_rhs.rhs.numeric_type = INVALID_NUMERIC_TYPE;
435  new_root_rhs.rhs.node_index = leaf.rhs.node_index;
436 
437  // work on subexpression:
438  // TODO: Catch exception, free temporary, then rethrow
439  detail::execute_composite(s, new_root_rhs);
440  }
441 
442  // Part 2: Run the actual computations //
443 
444  lhs_rhs_element x = lhs_needs_temporary ? new_root_lhs.lhs : leaf.lhs;
445  lhs_rhs_element y = rhs_needs_temporary ? new_root_rhs.lhs : leaf.rhs;
446 
447  if (root_node.lhs.type_family == VECTOR_TYPE_FAMILY)
448  {
449  if (root_node.op.type != OPERATION_BINARY_ASSIGN_TYPE)
450  {
451  //split y += A*x
452  statement_node new_root_z;
453  detail::new_element(new_root_z.lhs, root_node.lhs);
454 
455  // compute z = A * x
456  detail::matrix_vector_prod(s, new_root_z.lhs, x, y);
457 
458  // assignment y = z
459  double alpha = 0;
460  if (root_node.op.type == OPERATION_BINARY_INPLACE_ADD_TYPE)
461  alpha = 1.0;
462  else if (root_node.op.type == OPERATION_BINARY_INPLACE_SUB_TYPE)
463  alpha = -1.0;
464  else
465  throw statement_not_supported_exception("Invalid assignment type for matrix-vector product");
466 
467  lhs_rhs_element y = root_node.lhs;
468  detail::axbx(y,
469  y, 1.0, 1, false, false,
470  new_root_z.lhs, alpha, 1, false, false);
471 
472  detail::delete_element(new_root_z.lhs);
473  }
474  else
475  detail::matrix_vector_prod(s, root_node.lhs, x, y);
476  }
477  else
478  {
479  double alpha = (root_node.op.type == OPERATION_BINARY_INPLACE_SUB_TYPE) ? -1.0 : 1.0;
480  double beta = (root_node.op.type != OPERATION_BINARY_ASSIGN_TYPE) ? 1.0 : 0.0;
481 
482  detail::matrix_matrix_prod(s, root_node.lhs, x, y, alpha, beta);
483  }
484 
485  // Part 3: Clean up //
486 
487  if (lhs_needs_temporary)
488  detail::delete_element(new_root_lhs.lhs);
489 
490  if (rhs_needs_temporary)
491  detail::delete_element(new_root_rhs.lhs);
492  }
493 
494  } // namespace scheduler
495 } // namespace viennacl
496 
497 #endif
498 
statement_node_subtype subtype
Definition: forwards.h:270
viennacl::hyb_matrix< float > * hyb_matrix_float
Definition: forwards.h:406
viennacl::matrix_base< float > * matrix_row_float
Definition: forwards.h:339
#define VIENNACL_SCHEDULER_GENERATE_MATRIX_MATRIX_PROD(LAYOUTA, MEMBERA, LAYOUTB, MEMBERB, LAYOUTC, MEMBERC)
Definition: forwards.h:182
Implementations of dense matrix related operations including matrix-vector products.
vcl_size_t node_index
Definition: forwards.h:276
void new_element(lhs_rhs_element &new_elem, lhs_rhs_element const &old_element)
Definition: execute_util.hpp:102
void execute_matrix_prod(statement const &s, statement_node const &root_node)
Definition: execute_matrix_prod.hpp:393
Implementations of vector operations.
lhs_rhs_element lhs
Definition: forwards.h:422
Definition: forwards.h:176
Definition: forwards.h:217
Definition: forwards.h:196
viennacl::coordinate_matrix< float > * coordinate_matrix_float
Definition: forwards.h:384
This file provides the forward declarations for the main types used within ViennaCL.
void matrix_vector_prod(statement const &s, lhs_rhs_element result, lhs_rhs_element const &A, lhs_rhs_element const &x)
Definition: execute_matrix_prod.hpp:239
A class representing the 'data' for the LHS or RHS operand of the respective node.
Definition: forwards.h:267
operation_node_type_family type_family
Definition: forwards.h:415
viennacl::compressed_matrix< double > * compressed_matrix_double
Definition: forwards.h:374
Provides unified wrappers for the common routines {as(), asbs(), asbs_s()}, {av(), avbv(), avbv_v()}, and {am(), ambm(), ambm_m()} such that scheduler logic is not cluttered with numeric type decutions.
lhs_rhs_element rhs
Definition: forwards.h:424
Implementation of the coordinate_matrix class.
viennacl::matrix_base< float, viennacl::column_major > * matrix_col_float
Definition: forwards.h:351
void delete_element(lhs_rhs_element &elem)
Definition: execute_util.hpp:179
A dense matrix class.
Definition: forwards.h:290
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
Definition: cpu_ram.hpp:29
Definition: forwards.h:197
viennacl::matrix_base< double, viennacl::column_major > * matrix_col_double
Definition: forwards.h:352
viennacl::vector_base< float > * vector_float
Definition: forwards.h:315
Implementation of the hyb_matrix class.
statement_node_numeric_type numeric_type
Definition: forwards.h:271
void axbx(lhs_rhs_element &x1, lhs_rhs_element const &x2, ScalarType1 const &alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha, lhs_rhs_element const &x3, ScalarType2 const &beta, vcl_size_t len_beta, bool reciprocal_beta, bool flip_sign_beta)
Wrapper for viennacl::linalg::avbv(), taking care of the argument unwrapping.
Definition: execute_generic_dispatcher.hpp:67
viennacl::coordinate_matrix< double > * coordinate_matrix_double
Definition: forwards.h:385
viennacl::vector_base< double > * vector_double
Definition: forwards.h:316
Implementation of the compressed_matrix class.
Implementations of operations using sparse matrices.
Definition: forwards.h:173
Implementation of the ell_matrix class.
Expression template class for representing a tree of expressions which ultimately result in a matrix...
Definition: forwards.h:283
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
viennacl::compressed_matrix< float > * compressed_matrix_float
Definition: forwards.h:373
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_row > row(const matrix_base< NumericT, F > &A, unsigned int i)
Definition: matrix.hpp:910
container_type const & array() const
Definition: forwards.h:473
void execute_composite(statement const &s, statement_node const &root_node)
Deals with x = RHS where RHS is an expression and x is either a scalar, a vector, or a matrix...
Definition: execute.hpp:41
A tag class representing transposed matrices.
Definition: forwards.h:165
viennacl::matrix_base< double > * matrix_row_double
Definition: forwards.h:340
A tag for column-major storage of a dense matrix.
Definition: forwards.h:263
statement_node_type_family type_family
Definition: forwards.h:269
void prod_impl(const matrix_base< NumericT, F > &mat, const vector_base< NumericT > &vec, vector_base< NumericT > &result)
Carries out matrix-vector multiplication.
Definition: matrix_operations.hpp:350
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
Definition: forwards.h:447
void matrix_matrix_prod(statement const &s, lhs_rhs_element result, lhs_rhs_element const &A, lhs_rhs_element const &B, double alpha, double beta)
Definition: execute_matrix_prod.hpp:57
viennacl::ell_matrix< float > * ell_matrix_float
Definition: forwards.h:395
viennacl::ell_matrix< double > * ell_matrix_double
Definition: forwards.h:396
Definition: forwards.h:187
op_element op
Definition: forwards.h:423
A tag for row-major storage of a dense matrix.
Definition: forwards.h:246
bool matrix_prod_temporary_required(statement const &s, lhs_rhs_element const &elem)
Definition: execute_matrix_prod.hpp:44
Definition: forwards.h:216
Provides various utilities for implementing the execution of statements.
Main datastructure for an node in the statement tree.
Definition: forwards.h:420
Exception for the case the scheduler is unable to deal with the operation.
Definition: forwards.h:36
operation_node_type type
Definition: forwards.h:416
viennacl::hyb_matrix< double > * hyb_matrix_double
Definition: forwards.h:407