ViennaCL - The Vienna Computing Library  1.5.0
viennacl/scheduler/execute_elementwise.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_SCHEDULER_EXECUTE_ELEMENTWISE_HPP
00002 #define VIENNACL_SCHEDULER_EXECUTE_ELEMENTWISE_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2013, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00021 
00026 #include "viennacl/forwards.h"
00027 #include "viennacl/scheduler/forwards.h"
00028 #include "viennacl/scheduler/execute_util.hpp"
00029 #include "viennacl/linalg/vector_operations.hpp"
00030 #include "viennacl/linalg/matrix_operations.hpp"
00031 
00032 namespace viennacl
00033 {
00034   namespace scheduler
00035   {
00036     namespace detail
00037     {
00038       // result = element_op(x,y) for vectors or matrices x, y
00039       inline void element_op(lhs_rhs_element result,
00040                              lhs_rhs_element const & x,
00041                              operation_node_type  op_type)
00042       {
00043         assert( result.numeric_type == x.numeric_type && bool("Numeric type not the same!"));
00044         assert( result.type_family == x.type_family && bool("Subtype not the same!"));
00045 
00046         if (x.subtype == DENSE_VECTOR_TYPE)
00047         {
00048           assert( result.subtype == x.subtype && bool("result not of vector type for unary elementwise operation"));
00049           if (x.numeric_type == FLOAT_TYPE)
00050           {
00051             switch (op_type)
00052             {
00053 #define VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPNAME, SCALARTYPE, OPTAG) \
00054             case OPNAME:  viennacl::linalg::element_op(*result.vector_##SCALARTYPE, \
00055                                                        viennacl::vector_expression<const vector_base<SCALARTYPE>, const vector_base<SCALARTYPE>, \
00056                                                                                    op_element_unary<OPTAG> >(*x.vector_##SCALARTYPE, *x.vector_##SCALARTYPE)); break;
00057 
00058               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   float, op_abs)
00059               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  float, op_acos)
00060               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  float, op_asin)
00061               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  float, op_atan)
00062               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  float, op_ceil)
00063               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   float, op_cos)
00064               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  float, op_cosh)
00065               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   float, op_exp)
00066               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  float, op_fabs)
00067               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, float, op_floor)
00068               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   float, op_log)
00069               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, float, op_log10)
00070               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   float, op_sin)
00071               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  float, op_sinh)
00072               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  float, op_sqrt)
00073               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   float, op_tan)
00074               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  float, op_tanh)
00075             default:
00076               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00077             }
00078           }
00079           else if (x.numeric_type == DOUBLE_TYPE)
00080           {
00081             switch (op_type)
00082             {
00083               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   double, op_abs)
00084               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  double, op_acos)
00085               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  double, op_asin)
00086               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  double, op_atan)
00087               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  double, op_ceil)
00088               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   double, op_cos)
00089               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  double, op_cosh)
00090               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   double, op_exp)
00091               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  double, op_fabs)
00092               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, double, op_floor)
00093               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   double, op_log)
00094               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, double, op_log10)
00095               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   double, op_sin)
00096               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  double, op_sinh)
00097               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  double, op_sqrt)
00098               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   double, op_tan)
00099               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  double, op_tanh)
00100 
00101 #undef VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP
00102             default:
00103               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00104             }
00105           }
00106           else
00107             throw statement_not_supported_exception("Invalid numeric type in unary elementwise operator");
00108         }
00109         else if (x.subtype == DENSE_ROW_MATRIX_TYPE)
00110         {
00111           if (x.numeric_type == FLOAT_TYPE)
00112           {
00113             switch (op_type)
00114             {
00115 #define VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPNAME, SCALARTYPE, OPTAG) \
00116             case OPNAME:  viennacl::linalg::element_op(*result.matrix_row_##SCALARTYPE, \
00117                                                        viennacl::matrix_expression<const matrix_base<SCALARTYPE, viennacl::row_major>, const matrix_base<SCALARTYPE, viennacl::row_major>, \
00118                                                                                    op_element_unary<OPTAG> >(*x.matrix_row_##SCALARTYPE, *x.matrix_row_##SCALARTYPE)); break;
00119 
00120               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   float, op_abs)
00121               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  float, op_acos)
00122               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  float, op_asin)
00123               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  float, op_atan)
00124               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  float, op_ceil)
00125               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   float, op_cos)
00126               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  float, op_cosh)
00127               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   float, op_exp)
00128               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  float, op_fabs)
00129               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, float, op_floor)
00130               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   float, op_log)
00131               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, float, op_log10)
00132               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   float, op_sin)
00133               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  float, op_sinh)
00134               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  float, op_sqrt)
00135               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   float, op_tan)
00136               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  float, op_tanh)
00137             default:
00138               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00139             }
00140 
00141           }
00142           else if (x.numeric_type == DOUBLE_TYPE)
00143           {
00144             switch (op_type)
00145             {
00146               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   double, op_abs)
00147               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  double, op_acos)
00148               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  double, op_asin)
00149               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  double, op_atan)
00150               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  double, op_ceil)
00151               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   double, op_cos)
00152               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  double, op_cosh)
00153               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   double, op_exp)
00154               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  double, op_fabs)
00155               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, double, op_floor)
00156               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   double, op_log)
00157               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, double, op_log10)
00158               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   double, op_sin)
00159               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  double, op_sinh)
00160               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  double, op_sqrt)
00161               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   double, op_tan)
00162               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  double, op_tanh)
00163             default:
00164               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00165             }
00166           }
00167           else
00168             throw statement_not_supported_exception("Invalid numeric type in unary elementwise operator");
00169 
00170 #undef VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP
00171 
00172         }
00173         else if (x.subtype == DENSE_COL_MATRIX_TYPE)
00174         {
00175           if (x.numeric_type == FLOAT_TYPE)
00176           {
00177             switch (op_type)
00178             {
00179 #define VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPNAME, SCALARTYPE, OPTAG) \
00180             case OPNAME:  viennacl::linalg::element_op(*result.matrix_col_##SCALARTYPE, \
00181                                                        viennacl::matrix_expression<const matrix_base<SCALARTYPE, viennacl::column_major>, const matrix_base<SCALARTYPE, viennacl::column_major>, \
00182                                                                                    op_element_unary<OPTAG> >(*x.matrix_col_##SCALARTYPE, *x.matrix_col_##SCALARTYPE)); break;
00183 
00184               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   float, op_abs)
00185               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  float, op_acos)
00186               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  float, op_asin)
00187               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  float, op_atan)
00188               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  float, op_ceil)
00189               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   float, op_cos)
00190               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  float, op_cosh)
00191               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   float, op_exp)
00192               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  float, op_fabs)
00193               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, float, op_floor)
00194               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   float, op_log)
00195               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, float, op_log10)
00196               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   float, op_sin)
00197               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  float, op_sinh)
00198               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  float, op_sqrt)
00199               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   float, op_tan)
00200               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  float, op_tanh)
00201             default:
00202               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00203             }
00204 
00205           }
00206           else if (x.numeric_type == DOUBLE_TYPE)
00207           {
00208             switch (op_type)
00209             {
00210               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ABS_TYPE,   double, op_abs)
00211               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ACOS_TYPE,  double, op_acos)
00212               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ASIN_TYPE,  double, op_asin)
00213               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_ATAN_TYPE,  double, op_atan)
00214               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_CEIL_TYPE,  double, op_ceil)
00215               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COS_TYPE,   double, op_cos)
00216               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_COSH_TYPE,  double, op_cosh)
00217               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_EXP_TYPE,   double, op_exp)
00218               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FABS_TYPE,  double, op_fabs)
00219               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_FLOOR_TYPE, double, op_floor)
00220               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG_TYPE,   double, op_log)
00221               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_LOG10_TYPE, double, op_log10)
00222               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SIN_TYPE,   double, op_sin)
00223               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SINH_TYPE,  double, op_sinh)
00224               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_SQRT_TYPE,  double, op_sqrt)
00225               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TAN_TYPE,   double, op_tan)
00226               VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP(OPERATION_UNARY_TANH_TYPE,  double, op_tanh)
00227             default:
00228               throw statement_not_supported_exception("Invalid op_type in unary elementwise operations");
00229             }
00230           }
00231           else
00232             throw statement_not_supported_exception("Invalid numeric type in unary elementwise operator");
00233 
00234 #undef VIENNACL_SCHEDULER_GENERATE_UNARY_ELEMENT_OP
00235         }
00236       }
00237 
00238       // result = element_op(x,y) for vectors or matrices x, y
00239       inline void element_op(lhs_rhs_element result,
00240                              lhs_rhs_element const & x,
00241                              lhs_rhs_element const & y,
00242                              operation_node_type  op_type)
00243       {
00244         assert(      x.numeric_type == y.numeric_type && bool("Numeric type not the same!"));
00245         assert( result.numeric_type == y.numeric_type && bool("Numeric type not the same!"));
00246 
00247         assert(      x.type_family == y.type_family && bool("Subtype not the same!"));
00248         assert( result.type_family == y.type_family && bool("Subtype not the same!"));
00249 
00250         switch (op_type)
00251         {
00252 
00253         case OPERATION_BINARY_ELEMENT_DIV_TYPE:
00254           if (x.subtype == DENSE_VECTOR_TYPE)
00255           {
00256             switch (x.numeric_type)
00257             {
00258               case FLOAT_TYPE:
00259                 viennacl::linalg::element_op(*result.vector_float,
00260                                              vector_expression<const vector_base<float>,
00261                                                                const vector_base<float>,
00262                                                                op_element_binary<op_div> >(*x.vector_float, *y.vector_float));
00263                 break;
00264               case DOUBLE_TYPE:
00265                 viennacl::linalg::element_op(*result.vector_double,
00266                                              vector_expression<const vector_base<double>,
00267                                                                const vector_base<double>,
00268                                                                op_element_binary<op_div> >(*x.vector_double, *y.vector_double));
00269                 break;
00270               default:
00271                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00272             }
00273           }
00274           else if (x.subtype == DENSE_ROW_MATRIX_TYPE)
00275           {
00276             switch (x.numeric_type)
00277             {
00278               case FLOAT_TYPE:
00279                 viennacl::linalg::element_op(*result.matrix_row_float,
00280                                              matrix_expression< const matrix_base<float, row_major>,
00281                                                                 const matrix_base<float, row_major>,
00282                                                                 op_element_binary<op_div> >(*x.matrix_row_float, *y.matrix_row_float));
00283                 break;
00284               case DOUBLE_TYPE:
00285                 viennacl::linalg::element_op(*result.matrix_row_double,
00286                                              matrix_expression< const matrix_base<double, row_major>,
00287                                                                 const matrix_base<double, row_major>,
00288                                                                 op_element_binary<op_div> >(*x.matrix_row_double, *y.matrix_row_double));
00289                 break;
00290               default:
00291                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00292             }
00293           }
00294           else if (x.subtype == DENSE_COL_MATRIX_TYPE)
00295           {
00296             switch (x.numeric_type)
00297             {
00298               case FLOAT_TYPE:
00299                 viennacl::linalg::element_op(*result.matrix_col_float,
00300                                              matrix_expression< const matrix_base<float, column_major>,
00301                                                                 const matrix_base<float, column_major>,
00302                                                                 op_element_binary<op_div> >(*x.matrix_col_float, *y.matrix_col_float));
00303                 break;
00304               case DOUBLE_TYPE:
00305                 viennacl::linalg::element_op(*result.matrix_col_double,
00306                                              matrix_expression< const matrix_base<double, column_major>,
00307                                                                 const matrix_base<double, column_major>,
00308                                                                 op_element_binary<op_div> >(*x.matrix_col_double, *y.matrix_col_double));
00309                 break;
00310               default:
00311                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00312             }
00313           }
00314           else
00315             throw statement_not_supported_exception("Invalid operand type for binary elementwise division");
00316           break;
00317 
00318 
00319         case OPERATION_BINARY_ELEMENT_PROD_TYPE:
00320           if (x.subtype == DENSE_VECTOR_TYPE)
00321           {
00322             switch (x.numeric_type)
00323             {
00324               case FLOAT_TYPE:
00325                 viennacl::linalg::element_op(*result.vector_float,
00326                                              vector_expression<const vector_base<float>,
00327                                                                const vector_base<float>,
00328                                                                op_element_binary<op_prod> >(*x.vector_float, *y.vector_float));
00329                 break;
00330               case DOUBLE_TYPE:
00331                 viennacl::linalg::element_op(*result.vector_double,
00332                                              vector_expression<const vector_base<double>,
00333                                                                const vector_base<double>,
00334                                                                op_element_binary<op_prod> >(*x.vector_double, *y.vector_double));
00335                 break;
00336               default:
00337                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00338             }
00339           }
00340           else if (x.subtype == DENSE_ROW_MATRIX_TYPE)
00341           {
00342             switch (x.numeric_type)
00343             {
00344               case FLOAT_TYPE:
00345                 viennacl::linalg::element_op(*result.matrix_row_float,
00346                                              matrix_expression< const matrix_base<float, row_major>,
00347                                                                 const matrix_base<float, row_major>,
00348                                                                 op_element_binary<op_prod> >(*x.matrix_row_float, *y.matrix_row_float));
00349                 break;
00350               case DOUBLE_TYPE:
00351                 viennacl::linalg::element_op(*result.matrix_row_double,
00352                                              matrix_expression< const matrix_base<double, row_major>,
00353                                                                 const matrix_base<double, row_major>,
00354                                                                 op_element_binary<op_prod> >(*x.matrix_row_double, *y.matrix_row_double));
00355                 break;
00356               default:
00357                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00358             }
00359           }
00360           else if (x.subtype == DENSE_COL_MATRIX_TYPE)
00361           {
00362             switch (x.numeric_type)
00363             {
00364               case FLOAT_TYPE:
00365                 viennacl::linalg::element_op(*result.matrix_col_float,
00366                                              matrix_expression< const matrix_base<float, column_major>,
00367                                                                 const matrix_base<float, column_major>,
00368                                                                 op_element_binary<op_prod> >(*x.matrix_col_float, *y.matrix_col_float));
00369                 break;
00370               case DOUBLE_TYPE:
00371                 viennacl::linalg::element_op(*result.matrix_col_double,
00372                                              matrix_expression< const matrix_base<double, column_major>,
00373                                                                 const matrix_base<double, column_major>,
00374                                                                 op_element_binary<op_prod> >(*x.matrix_col_double, *y.matrix_col_double));
00375                 break;
00376               default:
00377                 throw statement_not_supported_exception("Invalid numeric type for binary elementwise division");
00378             }
00379           }
00380           else
00381             throw statement_not_supported_exception("Invalid operand type for binary elementwise division");
00382           break;
00383         default:
00384           throw statement_not_supported_exception("Invalid operation type for binary elementwise operations");
00385         }
00386       }
00387     }
00388 
00390     inline void execute_element_composite(statement const & s, statement_node const & root_node)
00391     {
00392       statement_node const & leaf = s.array()[root_node.rhs.node_index];
00393 
00394       statement_node new_root_lhs;
00395       statement_node new_root_rhs;
00396 
00397       // check for temporary on lhs:
00398       if (leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY)
00399       {
00400         detail::new_element(new_root_lhs.lhs, root_node.lhs);
00401 
00402         new_root_lhs.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00403         new_root_lhs.op.type        = OPERATION_BINARY_ASSIGN_TYPE;
00404 
00405         new_root_lhs.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00406         new_root_lhs.rhs.subtype      = INVALID_SUBTYPE;
00407         new_root_lhs.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00408         new_root_lhs.rhs.node_index   = leaf.lhs.node_index;
00409 
00410         // work on subexpression:
00411         // TODO: Catch exception, free temporary, then rethrow
00412         detail::execute_composite(s, new_root_lhs);
00413       }
00414 
00415       if (leaf.op.type == OPERATION_BINARY_ELEMENT_PROD_TYPE || leaf.op.type == OPERATION_BINARY_ELEMENT_DIV_TYPE)
00416       {
00417         // check for temporary on rhs:
00418         if (leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY)
00419         {
00420           detail::new_element(new_root_rhs.lhs, root_node.lhs);
00421 
00422           new_root_rhs.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00423           new_root_rhs.op.type        = OPERATION_BINARY_ASSIGN_TYPE;
00424 
00425           new_root_rhs.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00426           new_root_rhs.rhs.subtype      = INVALID_SUBTYPE;
00427           new_root_rhs.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00428           new_root_rhs.rhs.node_index   = leaf.rhs.node_index;
00429 
00430           // work on subexpression:
00431           // TODO: Catch exception, free temporary, then rethrow
00432           detail::execute_composite(s, new_root_rhs);
00433         }
00434 
00435         lhs_rhs_element x = (leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY) ? new_root_lhs.lhs : leaf.lhs;
00436         lhs_rhs_element y = (leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) ? new_root_rhs.lhs : leaf.rhs;
00437 
00438         // compute element-wise operation:
00439         detail::element_op(root_node.lhs, x, y, leaf.op.type);
00440 
00441         if (leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY)
00442           detail::delete_element(new_root_rhs.lhs);
00443       }
00444       else if (leaf.op.type_family  == OPERATION_UNARY_TYPE_FAMILY)
00445       {
00446         lhs_rhs_element x = (leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY) ? new_root_lhs.lhs : leaf.lhs;
00447 
00448         // compute element-wise operation:
00449         detail::element_op(root_node.lhs, x, leaf.op.type);
00450       }
00451       else
00452         throw statement_not_supported_exception("Unsupported elementwise operation.");
00453 
00454       // clean up:
00455       if (leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY)
00456         detail::delete_element(new_root_lhs.lhs);
00457 
00458     }
00459 
00460 
00461   } // namespace scheduler
00462 
00463 } // namespace viennacl
00464 
00465 #endif
00466