ViennaCL - The Vienna Computing Library  1.5.0
viennacl/scheduler/execute_axbx.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_SCHEDULER_EXECUTE_AXBX_HPP
00002 #define VIENNACL_SCHEDULER_EXECUTE_AXBX_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 
00029 #include "viennacl/scheduler/execute_scalar_assign.hpp"
00030 #include "viennacl/scheduler/execute_generic_dispatcher.hpp"
00031 
00032 namespace viennacl
00033 {
00034   namespace scheduler
00035   {
00036     namespace detail
00037     {
00039       inline void execute_axbx(statement const & s, statement_node const & root_node)
00040       {
00041         statement::container_type const & expr = s.array();
00042 
00043         statement_node const & leaf = expr[root_node.rhs.node_index];
00044 
00045         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
00046         {
00047           bool flip_sign_z = (leaf.op.type  == OPERATION_BINARY_SUB_TYPE);
00048 
00049           if (   leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00050               && leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY)
00051           {
00052             lhs_rhs_element u = root_node.lhs;
00053             lhs_rhs_element v = leaf.lhs;
00054             lhs_rhs_element w = leaf.rhs;
00055             switch (root_node.op.type)
00056             {
00057               case OPERATION_BINARY_ASSIGN_TYPE:
00058                 detail::axbx(u,
00059                              v, 1.0, 1, false, false,
00060                              w, 1.0, 1, false, flip_sign_z);
00061                 break;
00062               case OPERATION_BINARY_INPLACE_ADD_TYPE:
00063                 detail::axbx_x(u,
00064                                v, 1.0, 1, false, false,
00065                                w, 1.0, 1, false, flip_sign_z);
00066                 break;
00067               case OPERATION_BINARY_INPLACE_SUB_TYPE:
00068                 detail::axbx_x(u,
00069                                v, 1.0, 1, false, true,
00070                                w, 1.0, 1, false, !flip_sign_z);
00071                 break;
00072               default:
00073                 throw statement_not_supported_exception("Unsupported binary operator for operation in root note (should be =, +=, or -=)");
00074             }
00075           }
00076           else if (  leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
00077                   && leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY) // x = (y) + z, y being a subtree itself, z being a scalar, vector, or matrix
00078           {
00079             statement_node const & y = expr[leaf.lhs.node_index];
00080 
00081             if (y.op.type_family == OPERATION_BINARY_TYPE_FAMILY)
00082             {
00083               // y might be  'v * alpha' or 'v / alpha' with {scalar|vector|matrix} v
00084               if (   (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
00085                   &&  y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00086                   &&  y.rhs.type_family == SCALAR_TYPE_FAMILY)
00087               {
00088                 lhs_rhs_element u = root_node.lhs;
00089                 lhs_rhs_element v = y.lhs;
00090                 lhs_rhs_element w = leaf.rhs;
00091                 lhs_rhs_element alpha = y.rhs;
00092 
00093                 bool is_division = (y.op.type == OPERATION_BINARY_DIV_TYPE);
00094                 switch (root_node.op.type)
00095                 {
00096                   case OPERATION_BINARY_ASSIGN_TYPE:
00097                     detail::axbx(u,
00098                                  v, alpha, 1, is_division, false,
00099                                  w,   1.0, 1, false,       flip_sign_z);
00100                     break;
00101                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00102                     detail::axbx_x(u,
00103                                    v, alpha, 1, is_division, false,
00104                                    w,   1.0, 1, false,       flip_sign_z);
00105                     break;
00106                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00107                     detail::axbx_x(u,
00108                                    v, alpha, 1, is_division, true,
00109                                    w,   1.0, 1, false,       !flip_sign_z);
00110                     break;
00111                   default:
00112                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00113                 }
00114               }
00115               else // no built-in kernel, we use a temporary.
00116               {
00117                 statement_node new_root_y;
00118 
00119                 detail::new_element(new_root_y.lhs, root_node.lhs);
00120 
00121                 new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00122                 new_root_y.op.type        = OPERATION_BINARY_ASSIGN_TYPE;
00123 
00124                 new_root_y.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00125                 new_root_y.rhs.subtype      = INVALID_SUBTYPE;
00126                 new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00127                 new_root_y.rhs.node_index   = leaf.lhs.node_index;
00128 
00129                 // work on subexpression:
00130                 // TODO: Catch exception, free temporary, then rethrow
00131                 execute_composite(s, new_root_y);
00132 
00133                 // now add:
00134                 lhs_rhs_element u = root_node.lhs;
00135                 lhs_rhs_element v = new_root_y.lhs;
00136                 lhs_rhs_element w = leaf.rhs;
00137                 switch (root_node.op.type)
00138                 {
00139                   case OPERATION_BINARY_ASSIGN_TYPE:
00140                     detail::axbx(u,
00141                                  v, 1.0, 1, false, false,
00142                                  w, 1.0, 1, false, flip_sign_z);
00143                     break;
00144                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00145                     detail::axbx_x(u,
00146                                    v, 1.0, 1, false, false,
00147                                    w, 1.0, 1, false, flip_sign_z);
00148                     break;
00149                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00150                     detail::axbx_x(u,
00151                                    v, 1.0, 1, false, true,
00152                                    w, 1.0, 1, false, !flip_sign_z);
00153                     break;
00154                   default:
00155                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00156                 }
00157 
00158                 detail::delete_element(new_root_y.lhs);
00159               }
00160             }
00161             else
00162               throw statement_not_supported_exception("Cannot deal with unary operations on vectors");
00163 
00164           }
00165           else if (  leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00166                   && leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = y + (z), y being vector, z being a subtree itself
00167           {
00168             statement_node const & z = expr[leaf.rhs.node_index];
00169 
00170             if (z.op.type_family == OPERATION_BINARY_TYPE_FAMILY)
00171             {
00172               // z might be  'v * alpha' or 'v / alpha' with vector v
00173               if (   (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
00174                   &&  z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00175                   &&  z.rhs.type_family == SCALAR_TYPE_FAMILY)
00176               {
00177                 lhs_rhs_element u = root_node.lhs;
00178                 lhs_rhs_element v = leaf.lhs;
00179                 lhs_rhs_element w = z.lhs;
00180                 lhs_rhs_element beta = z.rhs;
00181 
00182                 bool is_division = (z.op.type == OPERATION_BINARY_DIV_TYPE);
00183                 switch (root_node.op.type)
00184                 {
00185                   case OPERATION_BINARY_ASSIGN_TYPE:
00186                     detail::axbx(u,
00187                                  v,  1.0, 1, false, false,
00188                                  w, beta, 1, is_division, flip_sign_z);
00189                     break;
00190                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00191                     detail::axbx_x(u,
00192                                    v,  1.0, 1, false, false,
00193                                    w, beta, 1, is_division, flip_sign_z);
00194                     break;
00195                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00196                     detail::axbx_x(u,
00197                                    v,  1.0, 1, false, true,
00198                                    w, beta, 1, is_division, !flip_sign_z);
00199                     break;
00200                   default:
00201                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00202                 }
00203               }
00204               else // no built-in kernel, we use a temporary.
00205               {
00206                 statement_node new_root_z;
00207 
00208                 detail::new_element(new_root_z.lhs, root_node.lhs);
00209 
00210                 new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00211                 new_root_z.op.type        = OPERATION_BINARY_ASSIGN_TYPE;
00212 
00213                 new_root_z.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00214                 new_root_z.rhs.subtype      = INVALID_SUBTYPE;
00215                 new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00216                 new_root_z.rhs.node_index   = leaf.rhs.node_index;
00217 
00218                 // work on subexpression:
00219                 // TODO: Catch exception, free temporary, then rethrow
00220                 execute_composite(s, new_root_z);
00221 
00222                 // now add:
00223                 lhs_rhs_element u = root_node.lhs;
00224                 lhs_rhs_element v = leaf.lhs;
00225                 lhs_rhs_element w = new_root_z.lhs;
00226                 switch (root_node.op.type)
00227                 {
00228                   case OPERATION_BINARY_ASSIGN_TYPE:
00229                     detail::axbx(u,
00230                                  v, 1.0, 1, false, false,
00231                                  w, 1.0, 1, false, flip_sign_z);
00232                     break;
00233                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00234                     detail::axbx_x(u,
00235                                    v, 1.0, 1, false, false,
00236                                    w, 1.0, 1, false, flip_sign_z);
00237                     break;
00238                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00239                     detail::axbx_x(u,
00240                                    v, 1.0, 1, false, true,
00241                                    w, 1.0, 1, false, !flip_sign_z);
00242                     break;
00243                   default:
00244                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00245                 }
00246 
00247                 detail::delete_element(new_root_z.lhs);
00248               }
00249             }
00250             else
00251               throw statement_not_supported_exception("Cannot deal with unary operations on vectors");
00252 
00253           }
00254           else if (  leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
00255                   && leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = (y) + (z), y and z being subtrees
00256           {
00257             statement_node const & y = expr[leaf.lhs.node_index];
00258             statement_node const & z = expr[leaf.rhs.node_index];
00259 
00260             if (   y.op.type_family == OPERATION_BINARY_TYPE_FAMILY
00261                 && z.op.type_family == OPERATION_BINARY_TYPE_FAMILY)
00262             {
00263               // z might be  'v * alpha' or 'v / alpha' with vector v
00264               if (   (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
00265                   &&  y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00266                   &&  y.rhs.type_family == SCALAR_TYPE_FAMILY
00267                   && (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
00268                   &&  z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
00269                   &&  z.rhs.type_family == SCALAR_TYPE_FAMILY)
00270               {
00271                 lhs_rhs_element u = root_node.lhs;
00272                 lhs_rhs_element v = y.lhs;
00273                 lhs_rhs_element w = z.lhs;
00274                 lhs_rhs_element alpha = y.rhs;
00275                 lhs_rhs_element beta  = z.rhs;
00276 
00277                 bool is_division_y = (y.op.type == OPERATION_BINARY_DIV_TYPE);
00278                 bool is_division_z = (z.op.type == OPERATION_BINARY_DIV_TYPE);
00279                 switch (root_node.op.type)
00280                 {
00281                   case OPERATION_BINARY_ASSIGN_TYPE:
00282                     detail::axbx(u,
00283                                  v, alpha, 1, is_division_y, false,
00284                                  w,  beta, 1, is_division_z, flip_sign_z);
00285                     break;
00286                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00287                     detail::axbx_x(u,
00288                                    v, alpha, 1, is_division_y, false,
00289                                    w,  beta, 1, is_division_z, flip_sign_z);
00290                     break;
00291                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00292                     detail::axbx_x(u,
00293                                    v, alpha, 1, is_division_y, true,
00294                                    w,  beta, 1, is_division_z, !flip_sign_z);
00295                     break;
00296                   default:
00297                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00298                 }
00299               }
00300               else // no built-in kernel, we use a temporary.
00301               {
00302                 statement_node new_root_y;
00303 
00304                 detail::new_element(new_root_y.lhs, root_node.lhs);
00305 
00306                 new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00307                 new_root_y.op.type   = OPERATION_BINARY_ASSIGN_TYPE;
00308 
00309                 new_root_y.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00310                 new_root_y.rhs.subtype      = INVALID_SUBTYPE;
00311                 new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00312                 new_root_y.rhs.node_index   = leaf.lhs.node_index;
00313 
00314                 // work on subexpression:
00315                 // TODO: Catch exception, free temporary, then rethrow
00316                 execute_composite(s, new_root_y);
00317 
00318                 statement_node new_root_z;
00319 
00320                 detail::new_element(new_root_z.lhs, root_node.lhs);
00321 
00322                 new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
00323                 new_root_z.op.type        = OPERATION_BINARY_ASSIGN_TYPE;
00324 
00325                 new_root_z.rhs.type_family  = COMPOSITE_OPERATION_FAMILY;
00326                 new_root_z.rhs.subtype      = INVALID_SUBTYPE;
00327                 new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
00328                 new_root_z.rhs.node_index   = leaf.rhs.node_index;
00329 
00330                 // work on subexpression:
00331                 // TODO: Catch exception, free temporaries, then rethrow
00332                 execute_composite(s, new_root_z);
00333 
00334                 // now add:
00335                 lhs_rhs_element u = root_node.lhs;
00336                 lhs_rhs_element v = new_root_y.lhs;
00337                 lhs_rhs_element w = new_root_z.lhs;
00338 
00339                 switch (root_node.op.type)
00340                 {
00341                   case OPERATION_BINARY_ASSIGN_TYPE:
00342                     detail::axbx(u,
00343                                  v, 1.0, 1, false, false,
00344                                  w, 1.0, 1, false, flip_sign_z);
00345                     break;
00346                   case OPERATION_BINARY_INPLACE_ADD_TYPE:
00347                     detail::axbx_x(u,
00348                                    v, 1.0, 1, false, false,
00349                                    w, 1.0, 1, false, flip_sign_z);
00350                     break;
00351                   case OPERATION_BINARY_INPLACE_SUB_TYPE:
00352                     detail::axbx_x(u,
00353                                    v, 1.0, 1, false, true,
00354                                    w, 1.0, 1, false, !flip_sign_z);
00355                     break;
00356                   default:
00357                     throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
00358                 }
00359 
00360                 detail::delete_element(new_root_y.lhs);
00361                 detail::delete_element(new_root_z.lhs);
00362               }
00363             }
00364             else
00365               throw statement_not_supported_exception("Cannot deal with unary operations on vectors");
00366           }
00367           else
00368             throw statement_not_supported_exception("Cannot deal with addition of vectors");
00369         }
00370         else
00371           throw statement_not_supported_exception("Unsupported binary operator for vector operations");
00372       }
00373 
00374     } // namespace detail
00375   } // namespace scheduler
00376 } // namespace viennacl
00377 
00378 #endif
00379