All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
execute_axbx.hpp
Go to the documentation of this file.
#ifndef VIENNACL_SCHEDULER_EXECUTE_AXBX_HPP
#define VIENNACL_SCHEDULER_EXECUTE_AXBX_HPP
/* =========================================================================
Copyright (c) 2010-2016, Institute for Microelectronics,
Institute for Analysis and Scientific Computing,
TU Wien.
Portions of this software are copyright by UChicago Argonne, LLC.
-----------------
ViennaCL - The Vienna Computing Library
-----------------
Project Head: Karl Rupp rupp@iue.tuwien.ac.at
(A list of authors and contributors can be found in the manual)
License: MIT (X11), see file LICENSE in the base directory
============================================================================= */
#include "viennacl/forwards.h"
#include "viennacl/scheduler/forwards.h"
#include "viennacl/scheduler/execute_scalar_assign.hpp"
#include "viennacl/scheduler/execute_generic_dispatcher.hpp"
namespace viennacl
{
namespace scheduler
{
namespace detail
{
inline void execute_axbx(statement const & s, statement_node const & root_node)
{
statement::container_type const & expr = s.array();
viennacl::context ctx = detail::extract_context(root_node);
statement_node const & leaf = expr[root_node.rhs.node_index];
if (leaf.op.type == OPERATION_BINARY_ADD_TYPE || leaf.op.type == OPERATION_BINARY_SUB_TYPE) // x = (y) +- (z) where y and z are either data objects or expressions
{
bool flip_sign_z = (leaf.op.type == OPERATION_BINARY_SUB_TYPE);
if ( leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY)
{
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = leaf.lhs;
lhs_rhs_element w = leaf.rhs;
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, true,
w, 1.0, 1, false, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for operation in root note (should be =, +=, or -=)");
}
}
else if ( leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
&& leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY) // x = (y) + z, y being a subtree itself, z being a scalar, vector, or matrix
{
statement_node const & y = expr[leaf.lhs.node_index];
if (y.op.type_family == OPERATION_BINARY_TYPE_FAMILY || y.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
{
// y might be 'v * alpha' or 'v / alpha' with {scalar|vector|matrix} v
if ( (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
&& y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& y.rhs.type_family == SCALAR_TYPE_FAMILY)
{
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = y.lhs;
lhs_rhs_element w = leaf.rhs;
lhs_rhs_element alpha = y.rhs;
bool is_division = (y.op.type == OPERATION_BINARY_DIV_TYPE);
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, alpha, 1, is_division, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, alpha, 1, is_division, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, alpha, 1, is_division, true,
w, 1.0, 1, false, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
}
else // no built-in kernel, we use a temporary.
{
statement_node new_root_y;
detail::new_element(new_root_y.lhs, root_node.lhs, ctx);
new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
new_root_y.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
new_root_y.rhs.subtype = INVALID_SUBTYPE;
new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
new_root_y.rhs.node_index = leaf.lhs.node_index;
// work on subexpression:
// TODO: Catch exception, free temporary, then rethrow
execute_composite(s, new_root_y);
// now add:
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = new_root_y.lhs;
lhs_rhs_element w = leaf.rhs;
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, true,
w, 1.0, 1, false, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
detail::delete_element(new_root_y.lhs);
}
}
else
throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
}
else if ( leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = y + (z), y being vector, z being a subtree itself
{
statement_node const & z = expr[leaf.rhs.node_index];
if (z.op.type_family == OPERATION_BINARY_TYPE_FAMILY || z.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
{
// z might be 'v * alpha' or 'v / alpha' with vector v
if ( (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
&& z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& z.rhs.type_family == SCALAR_TYPE_FAMILY)
{
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = leaf.lhs;
lhs_rhs_element w = z.lhs;
lhs_rhs_element beta = z.rhs;
bool is_division = (z.op.type == OPERATION_BINARY_DIV_TYPE);
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, 1.0, 1, false, false,
w, beta, 1, is_division, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, false,
w, beta, 1, is_division, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, true,
w, beta, 1, is_division, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
}
else // no built-in kernel, we use a temporary.
{
statement_node new_root_z;
detail::new_element(new_root_z.lhs, root_node.lhs, ctx);
new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
new_root_z.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
new_root_z.rhs.subtype = INVALID_SUBTYPE;
new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
new_root_z.rhs.node_index = leaf.rhs.node_index;
// work on subexpression:
// TODO: Catch exception, free temporary, then rethrow
execute_composite(s, new_root_z);
// now add:
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = leaf.lhs;
lhs_rhs_element w = new_root_z.lhs;
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, true,
w, 1.0, 1, false, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
detail::delete_element(new_root_z.lhs);
}
}
else
throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
}
else if ( leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
&& leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = (y) + (z), y and z being subtrees
{
statement_node const & y = expr[leaf.lhs.node_index];
statement_node const & z = expr[leaf.rhs.node_index];
if ( (y.op.type_family == OPERATION_BINARY_TYPE_FAMILY || y.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
&& (z.op.type_family == OPERATION_BINARY_TYPE_FAMILY || z.op.type_family == OPERATION_UNARY_TYPE_FAMILY))
{
// z might be 'v * alpha' or 'v / alpha' with vector v
if ( (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
&& y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& y.rhs.type_family == SCALAR_TYPE_FAMILY
&& (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
&& z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
&& z.rhs.type_family == SCALAR_TYPE_FAMILY)
{
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = y.lhs;
lhs_rhs_element w = z.lhs;
lhs_rhs_element alpha = y.rhs;
lhs_rhs_element beta = z.rhs;
bool is_division_y = (y.op.type == OPERATION_BINARY_DIV_TYPE);
bool is_division_z = (z.op.type == OPERATION_BINARY_DIV_TYPE);
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, alpha, 1, is_division_y, false,
w, beta, 1, is_division_z, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, alpha, 1, is_division_y, false,
w, beta, 1, is_division_z, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, alpha, 1, is_division_y, true,
w, beta, 1, is_division_z, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
}
else // no built-in kernel, we use a temporary.
{
statement_node new_root_y;
detail::new_element(new_root_y.lhs, root_node.lhs, ctx);
new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
new_root_y.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
new_root_y.rhs.subtype = INVALID_SUBTYPE;
new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
new_root_y.rhs.node_index = leaf.lhs.node_index;
// work on subexpression:
// TODO: Catch exception, free temporary, then rethrow
execute_composite(s, new_root_y);
statement_node new_root_z;
detail::new_element(new_root_z.lhs, root_node.lhs, ctx);
new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
new_root_z.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
new_root_z.rhs.subtype = INVALID_SUBTYPE;
new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
new_root_z.rhs.node_index = leaf.rhs.node_index;
// work on subexpression:
// TODO: Catch exception, free temporaries, then rethrow
execute_composite(s, new_root_z);
// now add:
lhs_rhs_element u = root_node.lhs;
lhs_rhs_element v = new_root_y.lhs;
lhs_rhs_element w = new_root_z.lhs;
switch (root_node.op.type)
{
case OPERATION_BINARY_ASSIGN_TYPE:
detail::axbx(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_ADD_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, false,
w, 1.0, 1, false, flip_sign_z);
break;
case OPERATION_BINARY_INPLACE_SUB_TYPE:
detail::axbx_x(u,
v, 1.0, 1, false, true,
w, 1.0, 1, false, !flip_sign_z);
break;
default:
throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
}
detail::delete_element(new_root_y.lhs);
detail::delete_element(new_root_z.lhs);
}
}
else
throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
}
else
throw statement_not_supported_exception("Cannot deal with addition of vectors");
}
else
throw statement_not_supported_exception("Unsupported binary operator for vector operations");
}
} // namespace detail
} // namespace scheduler
} // namespace viennacl
#endif
viennacl::scheduler::detail::extract_context
viennacl::context extract_context(statement_node const &root_node)
Helper routine for extracting the context in which a statement is executed.
Definition: execute_util.hpp:105
viennacl::scheduler::INVALID_SUBTYPE
Definition: forwards.h:266
viennacl::scheduler::lhs_rhs_element::subtype
statement_node_subtype subtype
Definition: forwards.h:340
viennacl::scheduler::statement_node::op
op_element op
Definition: forwards.h:481
viennacl::scheduler::SCALAR_TYPE_FAMILY
Definition: forwards.h:254
forwards.h
This file provides the forward declarations for the main types used within ViennaCL.
viennacl::scheduler::lhs_rhs_element::type_family
statement_node_type_family type_family
Definition: forwards.h:339
viennacl::scheduler::OPERATION_BINARY_ASSIGN_TYPE
Definition: forwards.h:115
viennacl::scheduler::lhs_rhs_element
A class representing the 'data' for the LHS or RHS operand of the respective node.
Definition: forwards.h:337
viennacl::scheduler::statement::array
container_type const & array() const
Definition: forwards.h:528
execute_generic_dispatcher.hpp
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.
viennacl::scheduler::op_element::type_family
operation_node_type_family type_family
Definition: forwards.h:473
execute_scalar_assign.hpp
Deals with the execution of x = RHS; for a vector x and any compatible right hand side expression RHS...
viennacl::scheduler::detail::delete_element
void delete_element(lhs_rhs_element &elem)
Definition: execute_util.hpp:266
viennacl::context
Represents a generic 'context' similar to an OpenCL context, but is backend-agnostic and thus also su...
Definition: context.hpp:39
viennacl::scheduler::COMPOSITE_OPERATION_FAMILY
Definition: forwards.h:251
viennacl::scheduler::statement::container_type
std::vector< value_type > container_type
Definition: forwards.h:507
viennacl::scheduler::detail::axbx
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::scheduler::INVALID_NUMERIC_TYPE
Definition: forwards.h:288
viennacl::scheduler::OPERATION_BINARY_INPLACE_ADD_TYPE
Definition: forwards.h:116
viennacl::scheduler::lhs_rhs_element::numeric_type
statement_node_numeric_type numeric_type
Definition: forwards.h:341
viennacl::scheduler::detail::execute_axbx
void execute_axbx(statement const &s, statement_node const &root_node)
Deals with x = (y) +- (z) where y and z are either data objects or expressions.
Definition: execute_axbx.hpp:40
viennacl::scheduler::statement_node::rhs
lhs_rhs_element rhs
Definition: forwards.h:482
viennacl::scheduler::statement_node::lhs
lhs_rhs_element lhs
Definition: forwards.h:480
viennacl::scheduler::OPERATION_BINARY_TYPE_FAMILY
Definition: forwards.h:59
forwards.h
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
viennacl::is_division
Helper metafunction for checking whether the provided type is viennacl::op_div (for division) ...
Definition: predicate.hpp:466
viennacl::scheduler::detail::execute_composite
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:42
viennacl::scheduler::OPERATION_BINARY_SUB_TYPE
Definition: forwards.h:119
viennacl::scheduler::OPERATION_BINARY_INPLACE_SUB_TYPE
Definition: forwards.h:117
viennacl::scheduler::detail::new_element
void new_element(lhs_rhs_element &new_elem, lhs_rhs_element const &old_element, viennacl::context const &ctx)
Definition: execute_util.hpp:204
viennacl::scheduler::op_element::type
operation_node_type type
Definition: forwards.h:474
viennacl::scheduler::OPERATION_BINARY_DIV_TYPE
Definition: forwards.h:121
viennacl::scheduler::statement
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
Definition: forwards.h:502
viennacl::scheduler::OPERATION_BINARY_ADD_TYPE
Definition: forwards.h:118
viennacl::scheduler::lhs_rhs_element::node_index
vcl_size_t node_index
Definition: forwards.h:346
viennacl::scheduler::detail::axbx_x
void axbx_x(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_v(), taking care of the argument unwrapping.
Definition: execute_generic_dispatcher.hpp:99
viennacl::scheduler::statement_node
Main datastructure for an node in the statement tree.
Definition: forwards.h:478
viennacl::scheduler::statement_not_supported_exception
Exception for the case the scheduler is unable to deal with the operation.
Definition: forwards.h:38
viennacl::scheduler::OPERATION_UNARY_TYPE_FAMILY
Definition: forwards.h:58
viennacl::scheduler::OPERATION_BINARY_MULT_TYPE
Definition: forwards.h:120