File: vsip/impl/sal/eval_elementwise.hpp
    1| /* Copyright (c) 2006 by CodeSourcery, LLC.  All rights reserved. */
    2| 
    3| /** @file    vsip/impl/sal/eval.hpp
    4|     @author  Jules Bergmann
    5|     @date    2006-05-26
    6|     @brief   VSIPL++ Library: Dispatch for Mercury SAL.
    7| */
    8| 
    9| #ifndef VSIP_IMPL_SAL_EVAL_HPP
   10| #define VSIP_IMPL_SAL_EVAL_HPP
   11| 
   12| /***********************************************************************
   13|   Included Files
   14| ***********************************************************************/
   15| 
   16| #include <vsip/impl/expr_serial_evaluator.hpp>
   17| #include <vsip/impl/expr_scalar_block.hpp>
   18| #include <vsip/impl/expr_unary_block.hpp>
   19| #include <vsip/impl/expr_binary_block.hpp>
   20| #include <vsip/impl/expr_ternary_block.hpp>
   21| #include <vsip/impl/expr_operations.hpp>
   22| #include <vsip/impl/fns_elementwise.hpp>
   23| #include <vsip/impl/extdata.hpp>
   24| #include <vsip/impl/metaprogramming.hpp>
   25| #include <vsip/impl/sal/eval_util.hpp>
   26| #include <vsip/impl/adjust-layout.hpp>
   27| 
   28| 
   29| 
   30| /***********************************************************************
   31|   Declarations
   32| ***********************************************************************/
   33| 
   34| namespace vsip
   35| {
   36| namespace impl
   37| {
   38| namespace sal
   39| {
   40| 
   41| /// Traits class to help determine when SAL supports a given
   42| /// binary operation.
   43| ///
   44| /// Requirements:
   45| ///   OPERATOR is the Operator template class for the operation
   46| ///      (from the vsip::impl::op namespace).
   47| ///   LTYPE is the type of the left operand.
   48| ///   RTYPE is the type of the right operand.
   49| ///   RTYPE is the type of the result.
   50| ///
   51| /// For LTYPE, RTYPE, and DSTTYPE, vector operands should be represented
   52| /// by a pointer type (for example: float*, complex<float>*, and
   53| /// std::pair<float*, float*>).  scalar operand should be represented
   54| /// by a value type, such as float, complex<float>, std::pair<float, float>.
   55| 
   56| template <template <typename, typename> class Operator,
   57|           typename                            LType,
   58|           typename                            RType,
   59|           typename                            DstType>
   60| struct Is_op2_supported
   61| {
   62|   static bool const value = false;
   63| };
   64| 
   65| template <template <typename> class Operator,
   66|           typename                  SrcType,
   67|           typename                  DstType>
   68| struct Is_op1_supported
   69| {
   70|   static bool const value = false;
   71| };
   72| 
   73| template <template <typename, typename, typename> class Operator,
   74|           typename                            Type1,
   75|           typename                            Type2,
   76|           typename                            Type3,
   77|           typename                            DstType>
   78| struct Is_op3_supported
   79| {
   80|   static bool const value = false;
   81| };
   82| 
   83| 
   84| template <typename, typename, typename> struct cma_token;
   85| template <typename> struct copy_token;
   86| 
   87| #define VSIP_IMPL_OP1SUP(Op, T1, DT)           
   88|   template <> struct Is_op1_supported<Op, T1, DT >      
   89|   { static bool const value = true; }
   90| 
   91| #define VSIP_IMPL_OP2SUP(Op, LT, RT, DT)        
   92|   template <> struct Is_op2_supported<Op, LT, RT, DT >         
   93|   { static bool const value = true; }
   94| 
   95| #define VSIP_IMPL_OP3SUP(Op, T1, T2, T3, DT)    
   96|   template <> struct Is_op3_supported<Op, T1, T2, T3, DT >      
   97|   { static bool const value = true; }
   98| 
   99| typedef std::pair<float*, float*>   split_float;
  100| typedef std::pair<double*, double*> split_double;
  101| 
  102| 
  103| /***********************************************************************
  104|   Unary operators and functions provided by SAL
  105| ***********************************************************************/
  106| 
  107| VSIP_IMPL_OP1SUP(magsq_functor, complex<float>*,  float*);
  108| VSIP_IMPL_OP1SUP(magsq_functor, complex<double>*, double*);
  109| VSIP_IMPL_OP1SUP(magsq_functor, split_float,      float*);
  110| VSIP_IMPL_OP1SUP(magsq_functor, split_double,     double*);
  111| 
  112| VSIP_IMPL_OP1SUP(op::Minus,     int*,             int*);
  113| VSIP_IMPL_OP1SUP(op::Minus,     float*,           float*);
  114| VSIP_IMPL_OP1SUP(op::Minus,     double*,          double*);
  115| VSIP_IMPL_OP1SUP(op::Minus,     complex<float>*,  complex<float>*);
  116| VSIP_IMPL_OP1SUP(op::Minus,     complex<double>*, complex<double>*);
  117| VSIP_IMPL_OP1SUP(op::Minus,     split_float,      split_float);
  118| VSIP_IMPL_OP1SUP(op::Minus,     split_double,     split_double);
  119| 
  120| VSIP_IMPL_OP1SUP(mag_functor,   int*,             int*);
  121| VSIP_IMPL_OP1SUP(mag_functor,   float*,           float*);
  122| VSIP_IMPL_OP1SUP(mag_functor,   double*,          double*);
  123| VSIP_IMPL_OP1SUP(mag_functor,   complex<float>*,  float*);
  124| VSIP_IMPL_OP1SUP(mag_functor,   split_float,      float*);
  125| 
  126| VSIP_IMPL_OP1SUP(cos_functor,   float*,           float*);
  127| VSIP_IMPL_OP1SUP(cos_functor,   double*,          double*);
  128| 
  129| VSIP_IMPL_OP1SUP(sin_functor,   float*,           float*);
  130| VSIP_IMPL_OP1SUP(sin_functor,   double*,          double*);
  131| 
  132| VSIP_IMPL_OP1SUP(tan_functor,   float*,           float*);
  133| 
  134| VSIP_IMPL_OP1SUP(atan_functor,  float*,           float*);
  135| VSIP_IMPL_OP1SUP(atan_functor,  double*,          double*);
  136| 
  137| VSIP_IMPL_OP1SUP(log_functor,   float*,           float*);
  138| VSIP_IMPL_OP1SUP(log_functor,   double*,          double*);
  139| 
  140| VSIP_IMPL_OP1SUP(log10_functor, float*,           float*);
  141| VSIP_IMPL_OP1SUP(log10_functor, double*,          double*);
  142| 
  143| VSIP_IMPL_OP1SUP(exp_functor,   float*,           float*);
  144| VSIP_IMPL_OP1SUP(exp_functor,   double*,          double*);
  145| 
  146| VSIP_IMPL_OP1SUP(exp10_functor, float*,           float*);
  147| VSIP_IMPL_OP1SUP(exp10_functor, double*,          double*);
  148| 
  149| VSIP_IMPL_OP1SUP(sqrt_functor,  float*,           float*);
  150| VSIP_IMPL_OP1SUP(sqrt_functor,  double*,          double*);
  151| VSIP_IMPL_OP1SUP(sqrt_functor,  complex<float>*,  complex<float>*);
  152| VSIP_IMPL_OP1SUP(sqrt_functor,  split_float,      split_float);
  153| 
  154| VSIP_IMPL_OP1SUP(rsqrt_functor, float*,           float*);
  155| VSIP_IMPL_OP1SUP(rsqrt_functor, double*,          double*);
  156| 
  157| VSIP_IMPL_OP1SUP(sq_functor,    float*,           float*);
  158| VSIP_IMPL_OP1SUP(sq_functor,    double*,          double*);
  159| 
  160| VSIP_IMPL_OP1SUP(recip_functor, float*,           float*);
  161| // no scalar double
  162| VSIP_IMPL_OP1SUP(recip_functor, complex<float>*,  complex<float>*);
  163| VSIP_IMPL_OP1SUP(recip_functor, split_float,      split_float);
  164| VSIP_IMPL_OP1SUP(recip_functor, complex<double>*, complex<double>*);
  165| VSIP_IMPL_OP1SUP(recip_functor, split_double,     split_double);
  166| 
  167| VSIP_IMPL_OP1SUP(copy_token,    float*,           float*);
  168| VSIP_IMPL_OP1SUP(copy_token,    complex<float>*,  complex<float>*);
  169| VSIP_IMPL_OP1SUP(copy_token,    split_float,      split_float);
  170| VSIP_IMPL_OP1SUP(copy_token,    complex<double>*, complex<double>*);
  171| VSIP_IMPL_OP1SUP(copy_token,    split_double,     split_double);
  172| 
  173| VSIP_IMPL_OP1SUP(copy_token,    split_float,      complex<float>*);
  174| VSIP_IMPL_OP1SUP(copy_token,    complex<float>*,  split_float);
  175| VSIP_IMPL_OP1SUP(copy_token,    split_double,     complex<double>*);
  176| VSIP_IMPL_OP1SUP(copy_token,    complex<double>*, split_double);
  177| 
  178| 
  179| 
  180| /***********************************************************************
  181|   Binary operators and functions provided by SAL
  182| ***********************************************************************/
  183| 
  184| // straight-up vector add
  185| VSIP_IMPL_OP2SUP(op::Add, int*,             int*,            int*);
  186| VSIP_IMPL_OP2SUP(op::Add, float*,           float*,          float*);
  187| VSIP_IMPL_OP2SUP(op::Add, double*,          double*,         double*);
  188| VSIP_IMPL_OP2SUP(op::Add, complex<float>*,  complex<float>*, complex<float>*);
  189| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, complex<double>*,complex<double>*);
  190| VSIP_IMPL_OP2SUP(op::Add, split_float,      split_float,     split_float);
  191| VSIP_IMPL_OP2SUP(op::Add, split_double,     split_double,    split_double);
  192| 
  193| VSIP_IMPL_OP2SUP(op::Add, float*,           complex<float>*, complex<float>*);
  194| VSIP_IMPL_OP2SUP(op::Add, complex<float>*,  float*,          complex<float>*);
  195| VSIP_IMPL_OP2SUP(op::Add, float*,           split_float,     split_float);
  196| VSIP_IMPL_OP2SUP(op::Add, split_float,      float*,          split_float);
  197| // not crvadddx in SAL
  198| 
  199| // scalar-vector vector add
  200| VSIP_IMPL_OP2SUP(op::Add, int,              int*,            int*);
  201| VSIP_IMPL_OP2SUP(op::Add, int*,             int,             int*);
  202| VSIP_IMPL_OP2SUP(op::Add, float,            float*,          float*);
  203| VSIP_IMPL_OP2SUP(op::Add, float*,           float,           float*);
  204| VSIP_IMPL_OP2SUP(op::Add, double,           double*,         double*);
  205| VSIP_IMPL_OP2SUP(op::Add, double*,          double,          double*);
  206| VSIP_IMPL_OP2SUP(op::Add, complex<float>,   complex<float>*, complex<float>*);
  207| VSIP_IMPL_OP2SUP(op::Add, complex<float>*,  complex<float>,  complex<float>*);
  208| VSIP_IMPL_OP2SUP(op::Add, complex<double>,  complex<double>*,complex<double>*);
  209| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, complex<double>, complex<double>*);
  210| VSIP_IMPL_OP2SUP(op::Add, complex<float>,   split_float,     split_float);
  211| VSIP_IMPL_OP2SUP(op::Add, split_float,      complex<float>,  split_float);
  212| VSIP_IMPL_OP2SUP(op::Add, complex<double>,  split_double,    split_double);
  213| VSIP_IMPL_OP2SUP(op::Add, split_double,     complex<double>, split_double);
  214| 
  215| VSIP_IMPL_OP2SUP(op::Add, float,            complex<float>*, complex<float>*);
  216| VSIP_IMPL_OP2SUP(op::Add, complex<float>*,  float,           complex<float>*);
  217| VSIP_IMPL_OP2SUP(op::Add, double,           complex<double>*,complex<double>*);
  218| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, double,          complex<double>*);
  219| 
  220| VSIP_IMPL_OP2SUP(op::Add, float,            split_float,     split_float);
  221| VSIP_IMPL_OP2SUP(op::Add, split_float,      float,           split_float);
  222| VSIP_IMPL_OP2SUP(op::Add, double,           split_double,    split_double);
  223| VSIP_IMPL_OP2SUP(op::Add, split_double,     double,          split_double);
  224| 
  225| 
  226| // straight-up vector sub
  227| VSIP_IMPL_OP2SUP(op::Sub, int*,             int*,            int*);
  228| VSIP_IMPL_OP2SUP(op::Sub, float*,           float*,          float*);
  229| VSIP_IMPL_OP2SUP(op::Sub, double*,          double*,         double*);
  230| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*,  complex<float>*, complex<float>*);
  231| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, complex<double>*,complex<double>*);
  232| VSIP_IMPL_OP2SUP(op::Sub, split_float,      split_float,     split_float);
  233| VSIP_IMPL_OP2SUP(op::Sub, split_double,     split_double,    split_double);
  234| 
  235| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*,  float*,          complex<float>*);
  236| VSIP_IMPL_OP2SUP(op::Sub, split_float,      float*,          split_float);
  237| 
  238| // scalar-vector vector sub
  239| VSIP_IMPL_OP2SUP(op::Sub, int*,             int,             int*);
  240| // not in sal   (op::Sub, float,            float*,          float*);
  241| VSIP_IMPL_OP2SUP(op::Sub, float*,           float,           float*);
  242| // not in sal   (op::Sub, double,           double*,         double*);
  243| VSIP_IMPL_OP2SUP(op::Sub, double*,          double,          double*);
  244| // not in sal   (op::Sub, complex<float>,   complex<float>*, complex<float>*);
  245| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*,  complex<float>,  complex<float>*);
  246| // not in sal   (op::Sub, complex<double>,  complex<double>*,complex<double>*);
  247| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, complex<double>, complex<double>*);
  248| // not in sal   (op::Sub, complex<float>,   split_float,     split_float);
  249| VSIP_IMPL_OP2SUP(op::Sub, split_float,      complex<float>,  split_float);
  250| // not in sal   (op::Sub, complex<double>,  split_double,    split_double);
  251| VSIP_IMPL_OP2SUP(op::Sub, split_double,     complex<double>, split_double);
  252| 
  253| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*,  float,           complex<float>*);
  254| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, double,          complex<double>*);
  255| VSIP_IMPL_OP2SUP(op::Sub, split_float,      float,           split_float);
  256| VSIP_IMPL_OP2SUP(op::Sub, split_double,     double,          split_double);
  257| 
  258| 
  259| // straight-up vector multiply
  260| VSIP_IMPL_OP2SUP(op::Mult, int*,            int*,            int*);
  261| VSIP_IMPL_OP2SUP(op::Mult, float*,          float*,          float*);
  262| VSIP_IMPL_OP2SUP(op::Mult, double*,         double*,         double*);
  263| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, complex<float>*, complex<float>*);
  264| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,complex<double>*,complex<double>*);
  265| VSIP_IMPL_OP2SUP(op::Mult, split_float,     split_float,     split_float);
  266| VSIP_IMPL_OP2SUP(op::Mult, split_double,    split_double,    split_double);
  267| 
  268| // real-complex vector multiply
  269| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, float*,          complex<float>*);
  270| VSIP_IMPL_OP2SUP(op::Mult, float*,          complex<float>*, complex<float>*);
  271| VSIP_IMPL_OP2SUP(op::Mult, split_float,     float*,          split_float);
  272| VSIP_IMPL_OP2SUP(op::Mult, float*,          split_float,     split_float);
  273| 
  274| // scalar-vector vector multiply
  275| VSIP_IMPL_OP2SUP(op::Mult, int,             int*,            int*);
  276| VSIP_IMPL_OP2SUP(op::Mult, int*,            int,             int*);
  277| VSIP_IMPL_OP2SUP(op::Mult, float,           float*,          float*);
  278| VSIP_IMPL_OP2SUP(op::Mult, float*,          float,           float*);
  279| VSIP_IMPL_OP2SUP(op::Mult, double,          double*,         double*);
  280| VSIP_IMPL_OP2SUP(op::Mult, double*,         double,          double*);
  281| VSIP_IMPL_OP2SUP(op::Mult, complex<float>,  complex<float>*, complex<float>*);
  282| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, complex<float>,  complex<float>*);
  283| VSIP_IMPL_OP2SUP(op::Mult, complex<double>, complex<double>*,complex<double>*);
  284| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,complex<double>, complex<double>*);
  285| VSIP_IMPL_OP2SUP(op::Mult, complex<float>,  split_float,     split_float);
  286| VSIP_IMPL_OP2SUP(op::Mult, split_float,     complex<float>,  split_float);
  287| VSIP_IMPL_OP2SUP(op::Mult, complex<double>, split_double,    split_double);
  288| VSIP_IMPL_OP2SUP(op::Mult, split_double,    complex<double>, split_double);
  289| 
  290| VSIP_IMPL_OP2SUP(op::Mult, float,           complex<float>*, complex<float>*);
  291| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, float,           complex<float>*);
  292| VSIP_IMPL_OP2SUP(op::Mult, double,          complex<double>*,complex<double>*);
  293| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,double,          complex<double>*);
  294| 
  295| VSIP_IMPL_OP2SUP(op::Mult, float,           split_float,     split_float);
  296| VSIP_IMPL_OP2SUP(op::Mult, split_float,     float,           split_float);
  297| VSIP_IMPL_OP2SUP(op::Mult, double,          split_double,    split_double);
  298| VSIP_IMPL_OP2SUP(op::Mult, split_double,    double,          split_double);
  299| 
  300| 
  301| 
  302| // straight-up vector division
  303| VSIP_IMPL_OP2SUP(op::Div, int*,             int*,            int*);
  304| VSIP_IMPL_OP2SUP(op::Div, float*,           float*,          float*);
  305| VSIP_IMPL_OP2SUP(op::Div, double*,          double*,         double*);
  306| VSIP_IMPL_OP2SUP(op::Div, complex<float>*,  complex<float>*, complex<float>*);
  307| VSIP_IMPL_OP2SUP(op::Div, complex<double>*, complex<double>*,complex<double>*);
  308| VSIP_IMPL_OP2SUP(op::Div, split_float,      split_float,     split_float);
  309| VSIP_IMPL_OP2SUP(op::Div, split_double,     split_double,    split_double);
  310| 
  311| VSIP_IMPL_OP2SUP(op::Div, complex<float>*,  float*,          complex<float>*);
  312| VSIP_IMPL_OP2SUP(op::Div, split_float,      float*,          split_float);
  313| 
  314| // scalar-vector vector division
  315| // not in sal  (op::Div, int,             int*,            int*);
  316| VSIP_IMPL_OP2SUP(op::Div, int*,            int,             int*);
  317| VSIP_IMPL_OP2SUP(op::Div, float,           float*,          float*);
  318| VSIP_IMPL_OP2SUP(op::Div, float*,          float,           float*);
  319| // not in sal   (op::Div, complex<float>,  complex<float>*, complex<float>*);
  320| // not in sal   (op::Div, complex<float>*, complex<float>,  complex<float>*);
  321| // not in sal   (op::Div, double,          double*,         double*);
  322| VSIP_IMPL_OP2SUP(op::Div, double*,         double,          double*);
  323| // not in sal   (op::Div, complex<double>, complex<double>*,complex<double>*);
  324| // not in sal   (op::Div, complex<double>*,complex<double>, complex<double>*);
  325| 
  326| 
  327| // Logical
  328| 
  329| VSIP_IMPL_OP2SUP(band_functor, int*,             int*,            int*);
  330| VSIP_IMPL_OP2SUP(bor_functor,  int*,             int*,            int*);
  331| 
  332| 
  333| // vector comparisons
  334| 
  335| VSIP_IMPL_OP2SUP(max_functor, float*,             float*,            float*);
  336| VSIP_IMPL_OP2SUP(max_functor, double*,            double*,           double*);
  337| 
  338| VSIP_IMPL_OP2SUP(min_functor, float*,             float*,            float*);
  339| VSIP_IMPL_OP2SUP(min_functor, double*,            double*,           double*);
  340| 
  341| 
  342| 
  343| /***********************************************************************
  344|   Ternary operators and functions provided by SAL.
  345| ***********************************************************************/
  346| 
  347| // Multiply-add
  348| 
  349| VSIP_IMPL_OP3SUP(ma_functor, float,   float*,  float*, float*);
  350| VSIP_IMPL_OP3SUP(ma_functor, float*,  float,   float*, float*);
  351| VSIP_IMPL_OP3SUP(ma_functor, float*,  float*,  float,  float*);
  352| VSIP_IMPL_OP3SUP(ma_functor, float*,  float*,  float*, float*);
  353| 
  354| VSIP_IMPL_OP3SUP(ma_functor, complex<float>*, complex<float>, complex<float>*,
  355|                 complex<float>*);
  356| VSIP_IMPL_OP3SUP(ma_functor, complex<float>, complex<float>*, complex<float>*,
  357|                 complex<float>*);
  358| VSIP_IMPL_OP3SUP(ma_functor, split_float, complex<float>, split_float,
  359|                split_float);
  360| VSIP_IMPL_OP3SUP(ma_functor, complex<float>, split_float, split_float,
  361|                split_float);
  362| 
  363| VSIP_IMPL_OP3SUP(ma_functor, double,   double*,  double*, double*);
  364| VSIP_IMPL_OP3SUP(ma_functor, double*,  double,   double*, double*);
  365| VSIP_IMPL_OP3SUP(ma_functor, double*,  double*,  double,  double*);
  366| VSIP_IMPL_OP3SUP(ma_functor, double*,  double*,  double*, double*);
  367| 
  368| VSIP_IMPL_OP3SUP(ma_functor,
  369|                 complex<double>*, complex<double>, complex<double>*,
  370|                 complex<double>*);
  371| VSIP_IMPL_OP3SUP(ma_functor,
  372|                 complex<double>, complex<double>*, complex<double>*,
  373|                 complex<double>*);
  374| 
  375| 
  376| // Multiply-subtract
  377| 
  378| VSIP_IMPL_OP3SUP(msb_functor, float,   float*,  float*, float*);
  379| VSIP_IMPL_OP3SUP(msb_functor, float*,  float,   float*, float*);
  380| // not in sal   (msb_functor, float*,  float*,  float,  float*);
  381| VSIP_IMPL_OP3SUP(msb_functor, float*,  float*,  float*, float*);
  382| 
  383| VSIP_IMPL_OP3SUP(msb_functor, double,   double*,  double*, double*);
  384| VSIP_IMPL_OP3SUP(msb_functor, double*,  double,   double*, double*);
  385| // not in sal   (msb_functor, double*,  double*,  double,  double*);
  386| VSIP_IMPL_OP3SUP(msb_functor, double*,  double*,  double*, double*);
  387| 
  388| // no complex msb in SAL
  389| 
  390| 
  391| // Add-multiply
  392| 
  393| // not in SAL   (am_functor, float,   float*,  float*, float*);
  394| // not in SAL   (am_functor, float*,  float,   float*, float*);
  395| VSIP_IMPL_OP3SUP(am_functor, float*,  float*,  float,  float*);
  396| VSIP_IMPL_OP3SUP(am_functor, float*,  float*,  float*, float*);
  397| 
  398| // not in SAL   (am_functor, double,  double*, double*,double*);
  399| // not in SAL   (am_functor, double*, double,  double*,double*);
  400| // not in SAL   (am_functor, double*, double*, double, double*);
  401| VSIP_IMPL_OP3SUP(am_functor, double*, double*, double*,double*);
  402| 
  403| 
  404| // Subtract-multiply
  405| VSIP_IMPL_OP3SUP(sbm_functor, float*,  float*,  float,  float*);
  406| VSIP_IMPL_OP3SUP(sbm_functor, float*,  float*,  float*, float*);
  407| VSIP_IMPL_OP3SUP(sbm_functor, double*, double*, double*,double*);
  408| 
  409| 
  410| // Conjugate(multiply)-add
  411| 
  412| VSIP_IMPL_OP3SUP(cma_token, complex<float>*, complex<float>*, complex<float>*,
  413|                 complex<float>*);
  414| VSIP_IMPL_OP3SUP(cma_token, split_float*, split_float*, split_float*,
  415|                split_float*);
  416| 
  417| 
  418| 
  419| #undef VSIP_IMPL_OP1SUP
  420| #undef VSIP_IMPL_OP2SUP
  421| #undef VSIP_IMPL_OP3SUP
  422| 
  423| 
  424| 
  425| /***********************************************************************
  426|   Serial expression evaluator base classes
  427| ***********************************************************************/
  428| 
  429| /// Evaluator base class for view-view expressions with mixed value types
  430| /// I.e. complex<float> = float * complex<float>
  431| 
  432| template <template <typename, typename> class Operator,
  433|           typename DstBlock,
  434|           typename LBlock,
  435|           typename RBlock,
  436|           typename LType,
  437|           typename RType>
  438| struct Serial_expr_evaluator_base_mixed
  439| {
  440|   typedef Binary_expr_block<1, Operator, LBlock, LType, RBlock, RType>
  441|     SrcBlock;
  442| 
  443|   typedef typename DstBlock::value_type dst_type;
  444| 
  445|   typedef typename sal::Effective_value_type<DstBlock>::type d_eff_t;
  446|   typedef typename sal::Effective_value_type<LBlock>::type l_eff_t;
  447|   typedef typename sal::Effective_value_type<RBlock>::type r_eff_t;
  448| 
  449|   static bool const ct_valid = 
  450|     Type_equal<typename LBlock::value_type, LType>::value &&
  451|     Type_equal<typename RBlock::value_type, RType>::value &&
  452|     (!Is_expr_block<LBlock>::value || Is_scalar_block<LBlock>::value) &&
  453|     (!Is_expr_block<RBlock>::value || Is_scalar_block<RBlock>::value) &&
  454|      Is_op2_supported<Operator, l_eff_t, r_eff_t, d_eff_t>::value &&
  455|      // check that direct access is supported
  456|      Ext_data_cost<DstBlock>::value == 0 &&
  457|      (Ext_data_cost<LBlock>::value == 0 || Is_scalar_block<LBlock>::value) &&
  458|      (Ext_data_cost<RBlock>::value == 0 || Is_scalar_block<RBlock>::value);
  459|   
  460|   static bool rt_valid(DstBlock&, SrcBlock const&)
  461|   {
  462|     // SAL supports all strides
  463|     return true;
  464|   }
  465| };
  466| 
  467| // namespace vsip::impl::sal
  468| 
  469| 
  470| 
  471| /***********************************************************************
  472|   Copy expression evaluators
  473| ***********************************************************************/
  474| 
  475| #define VSIP_IMPL_SAL_COPY_EXPR(OP, FUN)        
  476| template <typename DstBlock,           
  477|           typename SrcBlock>          
  478| struct Serial_expr_evaluator<          
  479|          1, DstBlock,          
  480|          SrcBlock,             
  481|          typename Type_if<Mercury_sal_tag,      
  482|                           Is_leaf_block<SrcBlock>::value>::type>        
  483| {              
  484|   static char const* name() { return "Expr_SAL_COPY"; }        
  485|                \
  486|   typedef typename DstBlock::value_type dst_type;       
  487|                \
  488|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  489|   typedef typename sal::Effective_value_type<SrcBlock>::type eff_src_t; 
  490|                \
  491|   typedef typename Adjust_layout_dim<          
  492|       1, typename Block_layout<DstBlock>::layout_type>::type    
  493|     dst_lp;            
  494|                \
  495|   typedef typename Adjust_layout_dim<          
  496|       1, typename Block_layout<SrcBlock>::layout_type>::type    
  497|     src_lp;            
  498|                \
  499|   static bool const ct_valid =         
  500|     (!Is_expr_block<SrcBlock>::value || Is_scalar_block<SrcBlock>::value) &&\
  501|      sal::Is_op1_supported<OP, eff_src_t, eff_dst_t>::value&&   
  502|      /* check that direct access is supported */        
  503|      Ext_data_cost<DstBlock>::value == 0 &&     
  504|      (Ext_data_cost<SrcBlock>::value == 0 ||    
  505|       Is_scalar_block<SrcBlock>::value);        
  506|                \
  507|   static bool rt_valid(DstBlock&, SrcBlock const&)      
  508|   {            
  509|     /* SAL supports all strides */      
  510|     return true;        
  511|   }            
  512|                \
  513|   static void exec(DstBlock& dst, SrcBlock const& src)         
  514|   {            
  515|     sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);  
  516|     sal::Ext_wrapper<SrcBlock, src_lp> ext_src(src, SYNC_IN);   
  517|     FUN(typename sal::Ext_wrapper<SrcBlock, dst_lp>::sal_type(ext_src), 
  518|         typename sal::Ext_wrapper<DstBlock, src_lp>::sal_type(ext_dst),        
  519|         dst.size());          
  520|   }            
  521| };
  522| 
  523| VSIP_IMPL_SAL_COPY_EXPR(sal::copy_token, vcopy)
  524| 
  525| 
  526| 
  527| /***********************************************************************
  528|   Unary expression evaluators
  529| ***********************************************************************/
  530| 
  531| #define VSIP_IMPL_SAL_V_EXPR(OP, FUN)          
  532| template <typename DstBlock,           
  533|           typename Block1,            
  534|           typename Type1>      
  535| struct Serial_expr_evaluator<          
  536|          1, DstBlock,          
  537|          Unary_expr_block<1, OP, Block1, Type1> const,         
  538|          typename Type_if<Mercury_sal_tag,      
  539|                           Is_leaf_block<Block1>::value>::type>  
  540| {              
  541|   static char const* name() { return "Expr_SAL_V"; }    
  542|                \
  543|   typedef Unary_expr_block<1, OP, Block1, Type1> const         
  544|         SrcBlock;             
  545|                \
  546|   typedef typename DstBlock::value_type dst_type;       
  547|                \
  548|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  549|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
  550|                \
  551|   typedef typename Adjust_layout_dim<          
  552|       1, typename Block_layout<DstBlock>::layout_type>::type    
  553|     dst_lp;            
  554|                \
  555|   typedef typename Adjust_layout_dim<          
  556|       1, typename Block_layout<Block1>::layout_type>::type      
  557|     block1_lp;         
  558|                \
  559|   static bool const ct_valid =         
  560|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
  561|      sal::Is_op1_supported<OP, eff_1_t, eff_dst_t>::value&&     
  562|      /* check that direct access is supported */        
  563|      Ext_data_cost<DstBlock>::value == 0 &&     
  564|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value);\
  565|                \
  566|   static bool rt_valid(DstBlock&, SrcBlock const&)      
  567|   {            
  568|     /* SAL supports all strides */      
  569|     return true;        
  570|   }            
  571|                \
  572|   static void exec(DstBlock& dst, SrcBlock const& src)         
  573|   {            
  574|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,     SYNC_OUT);     
  575|     sal::Ext_wrapper<Block1, block1_lp> ext_1(src.op(),  SYNC_IN);      
  576|     FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
  577|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
  578|         dst.size());          
  579|   }            
  580| };
  581| 
  582| VSIP_IMPL_SAL_V_EXPR(magsq_functor, sal::vmagsq)
  583| VSIP_IMPL_SAL_V_EXPR(mag_functor,   sal::vmag)
  584| VSIP_IMPL_SAL_V_EXPR(op::Minus,     sal::vneg)
  585| VSIP_IMPL_SAL_V_EXPR(cos_functor,   sal::vcos)
  586| VSIP_IMPL_SAL_V_EXPR(sin_functor,   sal::vsin)
  587| VSIP_IMPL_SAL_V_EXPR(tan_functor,   sal::vtan)
  588| VSIP_IMPL_SAL_V_EXPR(atan_functor,  sal::vatan)
  589| VSIP_IMPL_SAL_V_EXPR(log_functor,   sal::vlog)
  590| VSIP_IMPL_SAL_V_EXPR(log10_functor, sal::vlog10)
  591| VSIP_IMPL_SAL_V_EXPR(exp_functor,   sal::vexp)
  592| VSIP_IMPL_SAL_V_EXPR(exp10_functor, sal::vexp10)
  593| VSIP_IMPL_SAL_V_EXPR(sqrt_functor,  sal::vsqrt)
  594| VSIP_IMPL_SAL_V_EXPR(rsqrt_functor, sal::vrsqrt)
  595| VSIP_IMPL_SAL_V_EXPR(sq_functor,    sal::vsq)
  596| VSIP_IMPL_SAL_V_EXPR(recip_functor, sal::vrecip)
  597| 
  598| 
  599| 
  600| /***********************************************************************
  601|   Binary expression evaluators
  602| ***********************************************************************/
  603| 
  604| #define VSIP_IMPL_SAL_VV_EXPR(OP, FUN)         
  605| template <typename DstBlock,           
  606|           typename LBlock,            
  607|           typename RBlock,            
  608|           typename LType,      
  609|           typename RType>      
  610| struct Serial_expr_evaluator<          
  611|     1, DstBlock,        
  612|     const Binary_expr_block<1, OP, LBlock, LType, RBlock, RType>,       
  613|     typename Type_if<Mercury_sal_tag,          
  614|                      Is_leaf_block<LBlock>::value &&    
  615|                      Is_leaf_block<RBlock>::value>::type>       
  616|   : sal::Serial_expr_evaluator_base_mixed<OP, DstBlock, LBlock, RBlock, LType, RType>   
  617| {              
  618|   static char const* name() { return "Expr_SAL_VV"; }   
  619|                \
  620|   typedef Binary_expr_block<1, OP, LBlock, LType, RBlock, RType>        
  621|     SrcBlock;          
  622|                \
  623|   typedef typename Adjust_layout_dim<          
  624|       1, typename Block_layout<DstBlock>::layout_type>::type    
  625|     dst_lp;            
  626|                \
  627|   typedef typename Adjust_layout_dim<          
  628|       1, typename Block_layout<LBlock>::layout_type>::type      
  629|     lblock_lp;         
  630|                \
  631|   typedef typename Adjust_layout_dim<          
  632|       1, typename Block_layout<RBlock>::layout_type>::type      
  633|     rblock_lp;         
  634|                \
  635|   static void exec(DstBlock& dst, SrcBlock const& src)         
  636|   {            
  637|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,       SYNC_OUT);   
  638|     sal::Ext_wrapper<LBlock, lblock_lp> ext_l(src.left(),  SYNC_IN);    
  639|     sal::Ext_wrapper<RBlock, rblock_lp> ext_r(src.right(), SYNC_IN);    
  640|                \
  641|     assert(dst.size() <= src.left().size());    
  642|     assert(dst.size() <= src.right().size());          
  643|                \
  644|     VSIP_IMPL_COVER_BLK("SAL_VV", SrcBlock);    
  645|     FUN(        
  646|       typename sal::Ext_wrapper<LBlock, lblock_lp>::sal_type(ext_l),    
  647|       typename sal::Ext_wrapper<RBlock, lblock_lp>::sal_type(ext_r),    
  648|       typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),   
  649|       dst.size()        
  650|     );         
  651|   }            
  652| };
  653| 
  654| VSIP_IMPL_SAL_VV_EXPR(op::Add,  sal::vadd)
  655| VSIP_IMPL_SAL_VV_EXPR(op::Sub,  sal::vsub)
  656| VSIP_IMPL_SAL_VV_EXPR(op::Mult, sal::vmul)
  657| VSIP_IMPL_SAL_VV_EXPR(op::Div,  sal::vdiv)
  658| 
  659| VSIP_IMPL_SAL_VV_EXPR(max_functor, sal::vmax)
  660| VSIP_IMPL_SAL_VV_EXPR(min_functor, sal::vmin)
  661| 
  662| VSIP_IMPL_SAL_VV_EXPR(band_functor, sal::vband)
  663| VSIP_IMPL_SAL_VV_EXPR(bor_functor,  sal::vbor)
  664| 
  665| 
  666| /***********************************************************************
  667|   Ternary expression evaluators
  668| ***********************************************************************/
  669| 
  670| #define VSIP_IMPL_SAL_VVV_EXPR(OP, FUN)        
  671| template <typename DstBlock,           
  672|           typename Block1,            
  673|           typename Type1,      
  674|           typename Block2,            
  675|           typename Type2,      
  676|           typename Block3,            
  677|           typename Type3>      
  678| struct Serial_expr_evaluator<          
  679|          1, DstBlock,          
  680|          const Ternary_expr_block<1, OP,        
  681|                                  Block1, Type1,        
  682|                                  Block2, Type2,        
  683|                                  Block3, Type3>,        
  684|          Mercury_sal_tag>       
  685| {              
  686|   static char const* name() { return "Expr_SAL_VVV"; }         
  687|                \
  688|   typedef Ternary_expr_block<1, OP,     
  689|                                  Block1, Type1,        
  690|                                  Block2, Type2,        
  691|                                  Block3, Type3>        
  692|         SrcBlock;             
  693|                \
  694|   typedef typename DstBlock::value_type dst_type;       
  695|                \
  696|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  697|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
  698|   typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
  699|   typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
  700|                \
  701|   typedef typename Adjust_layout_dim<          
  702|       1, typename Block_layout<DstBlock>::layout_type>::type    
  703|     dst_lp;            
  704|                \
  705|   typedef typename Adjust_layout_dim<          
  706|       1, typename Block_layout<Block1>::layout_type>::type      
  707|     block1_lp;         
  708|                \
  709|   typedef typename Adjust_layout_dim<          
  710|       1, typename Block_layout<Block2>::layout_type>::type      
  711|     block2_lp;         
  712|                \
  713|   typedef typename Adjust_layout_dim<          
  714|       1, typename Block_layout<Block3>::layout_type>::type      
  715|     block3_lp;         
  716|                \
  717|   static bool const ct_valid =         
  718|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
  719|     (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
  720|     (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
  721|      sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
  722|      /* check that direct access is supported */        
  723|      Ext_data_cost<DstBlock>::value == 0 &&     
  724|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
  725|      (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
  726|      (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
  727|                \
  728|   static bool rt_valid(DstBlock&, SrcBlock const&)      
  729|   {            
  730|     /* SAL supports all strides */      
  731|     return true;        
  732|   }            
  733|                \
  734|   static void exec(DstBlock& dst, SrcBlock const& src)         
  735|   {            
  736|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,        SYNC_OUT);  
  737|     sal::Ext_wrapper<Block1, block1_lp> ext_1(src.first(),  SYNC_IN);   
  738|     sal::Ext_wrapper<Block2, block2_lp> ext_2(src.second(), SYNC_IN);   
  739|     sal::Ext_wrapper<Block3, block3_lp> ext_3(src.third(),  SYNC_IN);   
  740|     FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
  741|         typename sal::Ext_wrapper<Block2, block1_lp>::sal_type(ext_2),  
  742|         typename sal::Ext_wrapper<Block3, block1_lp>::sal_type(ext_3),  
  743|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
  744|         dst.size());          
  745|   }            
  746| };
  747| 
  748| VSIP_IMPL_SAL_VVV_EXPR(ma_functor,  sal::vma)
  749| VSIP_IMPL_SAL_VVV_EXPR(msb_functor, sal::vmsb)
  750| VSIP_IMPL_SAL_VVV_EXPR(am_functor,  sal::vam)
  751| VSIP_IMPL_SAL_VVV_EXPR(sbm_functor, sal::vsbm)
  752| 
  753| 
  754| 
  755| // Ternary expressions, F(V).V.V
  756| 
  757| #define VSIP_IMPL_SAL_fVVV_EXPR(OP, UOP, FUN, LOOKUP_OP)        
  758| template <typename DstBlock,           
  759|           typename Block1,            
  760|           typename Type1,      
  761|           typename Block2,            
  762|           typename Type2,      
  763|           typename Block3,            
  764|           typename Type3>      
  765| struct Serial_expr_evaluator<          
  766|          1, DstBlock,          
  767|          Ternary_expr_block<1, OP,      
  768|            Unary_expr_block<1, UOP, Block1, Type1> const, Type1,        
  769|            Block2, Type2,       
  770|            Block3, Type3> const,        
  771|          Mercury_sal_tag>       
  772| {              
  773|   static char const* name() { return "Expr_SAL_fVVV"; }        
  774|                \
  775|   typedef Ternary_expr_block<1, OP,     
  776|            Unary_expr_block<1, UOP, Block1, Type1> const, Type1,        
  777|            Block2, Type2,       
  778|            Block3, Type3>       
  779|         SrcBlock;             
  780|                \
  781|   typedef typename DstBlock::value_type dst_type;       
  782|                \
  783|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  784|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
  785|   typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
  786|   typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
  787|                \
  788|   typedef typename Adjust_layout_dim<          
  789|       1, typename Block_layout<DstBlock>::layout_type>::type    
  790|     dst_lp;            
  791|                \
  792|   typedef typename Adjust_layout_dim<          
  793|       1, typename Block_layout<Block1>::layout_type>::type      
  794|     block1_lp;         
  795|                \
  796|   typedef typename Adjust_layout_dim<          
  797|       1, typename Block_layout<Block2>::layout_type>::type      
  798|     block2_lp;         
  799|                \
  800|   typedef typename Adjust_layout_dim<          
  801|       1, typename Block_layout<Block3>::layout_type>::type      
  802|     block3_lp;         
  803|                \
  804|   static bool const ct_valid =         
  805|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
  806|     (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
  807|     (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
  808|      sal::Is_op3_supported<LOOKUP_OP, eff_1_t, eff_2_t, eff_3_t,        
  809|                            eff_dst_t>::value&&         
  810|      /* check that direct access is supported */        
  811|      Ext_data_cost<DstBlock>::value == 0 &&     
  812|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
  813|      (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
  814|      (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
  815|                \
  816|   static bool rt_valid(DstBlock&, SrcBlock const&)      
  817|   {            
  818|     /* SAL supports all strides */      
  819|     return true;        
  820|   }            
  821|                \
  822|   static void exec(DstBlock& dst, SrcBlock const& src)         
  823|   {            
  824|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,            SYNC_OUT);\
  825|     sal::Ext_wrapper<Block1, block1_lp> ext_1(src.first().op(), SYNC_IN);\
  826|     sal::Ext_wrapper<Block2, block2_lp> ext_2(src.second(),     SYNC_IN);\
  827|     sal::Ext_wrapper<Block3, block3_lp> ext_3(src.third(),      SYNC_IN);\
  828|     FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
  829|         typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),  
  830|         typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),  
  831|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
  832|         dst.size());          
  833|   }            
  834| };
  835| 
  836| VSIP_IMPL_SAL_fVVV_EXPR(ma_functor, conj_functor, sal::vcma, sal::cma_token)
  837| 
  838| 
  839| 
  840| // Nested binary expressions, VV_V
  841| 
  842| #define VSIP_IMPL_SAL_VV_V_EXPR(OP, OP1, OP2, FUN)      
  843| template <typename DstBlock,           
  844|           typename Block1,            
  845|           typename Type1,      
  846|           typename Block2,            
  847|           typename Type2,      
  848|           typename Block3,            
  849|           typename Type3,      
  850|           typename TypeB>      
  851| struct Serial_expr_evaluator<          
  852|          1, DstBlock,          
  853|          Binary_expr_block<            
  854|                  1, OP2,        
  855|                  Binary_expr_block<     
  856|                          1, OP1,        
  857|                          Block1, Type1,        
  858|                          Block2, Type2> const, TypeB,   
  859|                  Block3, Type3> const,         
  860|          typename Type_if<Mercury_sal_tag,      
  861|                      Is_leaf_block<Block1>::value &&    
  862|                      Is_leaf_block<Block2>::value &&    
  863|                      Is_leaf_block<Block3>::value>::type>       
  864| {              
  865|   static char const* name() { return "Expr_SAL_VV_V"; }        
  866|                \
  867|   typedef Binary_expr_block<           
  868|                  1, OP2,        
  869|                  Binary_expr_block<     
  870|                          1, OP1,        
  871|                          Block1, Type1,        
  872|                          Block2, Type2> const, TypeB,   
  873|                  Block3, Type3>        
  874|         SrcBlock;             
  875|                \
  876|   typedef typename DstBlock::value_type dst_type;       
  877|                \
  878|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  879|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
  880|   typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
  881|   typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
  882|                \
  883|   typedef typename Adjust_layout_dim<          
  884|       1, typename Block_layout<DstBlock>::layout_type>::type    
  885|     dst_lp;            
  886|                \
  887|   typedef typename Adjust_layout_dim<          
  888|       1, typename Block_layout<Block1>::layout_type>::type      
  889|     block1_lp;         
  890|                \
  891|   typedef typename Adjust_layout_dim<          
  892|       1, typename Block_layout<Block2>::layout_type>::type      
  893|     block2_lp;         
  894|                \
  895|   typedef typename Adjust_layout_dim<          
  896|       1, typename Block_layout<Block3>::layout_type>::type      
  897|     block3_lp;         
  898|                \
  899|   static bool const ct_valid =         
  900|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
  901|     (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
  902|     (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
  903|      sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
  904|      /* check that direct access is supported */        
  905|      Ext_data_cost<DstBlock>::value == 0 &&     
  906|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
  907|      (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
  908|      (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
  909|                \
  910|   static bool rt_valid(DstBlock&, SrcBlock const&)      
  911|   {            
  912|     /* SAL supports all strides */      
  913|     return true;        
  914|   }            
  915|                \
  916|   static void exec(DstBlock& dst, SrcBlock const& src)         
  917|   {            
  918|     sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst,        SYNC_OUT);   
  919|     sal::Ext_wrapper<Block1, block1_lp>   ext_1(src.left().left(),  SYNC_IN);\
  920|     sal::Ext_wrapper<Block2, block2_lp>   ext_2(src.left().right(), SYNC_IN);\
  921|     sal::Ext_wrapper<Block3, block3_lp>   ext_3(src.right(),  SYNC_IN); 
  922|     FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
  923|         typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),  
  924|         typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),  
  925|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
  926|         dst.size());          
  927|   }            
  928| };
  929| 
  930| // Nested binary expressions, V_VV
  931| 
  932| #define VSIP_IMPL_SAL_V_VV_EXPR(OP, OP1, OP2, FUN)      
  933| template <typename DstBlock,           
  934|           typename Block1,            
  935|           typename Type1,      
  936|           typename Block2,            
  937|           typename Type2,      
  938|           typename Block3,            
  939|           typename Type3,      
  940|           typename TypeB>      
  941| struct Serial_expr_evaluator<          
  942|          1, DstBlock,          
  943|          Binary_expr_block<            
  944|                  1, OP2,        
  945|                  Block1, Type1,        
  946|                  Binary_expr_block<     
  947|                          1, OP1,        
  948|                          Block2, Type2,        
  949|                          Block3, Type3> const, TypeB> const,    
  950|          typename Type_if<Mercury_sal_tag,      
  951|                      Is_leaf_block<Block1>::value &&    
  952|                      Is_leaf_block<Block2>::value &&    
  953|                      Is_leaf_block<Block3>::value>::type>       
  954| {              
  955|   static char const* name() { return "Expr_SAL_V_VV"; }        
  956|                \
  957|   typedef Binary_expr_block<           
  958|                  1, OP2,        
  959|                  Block1, Type1,        
  960|                  Binary_expr_block<     
  961|                          1, OP1,        
  962|                          Block2, Type2,        
  963|                          Block3, Type3> const, TypeB>   
  964|         SrcBlock;             
  965|                \
  966|   typedef typename DstBlock::value_type dst_type;       
  967|                \
  968|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
  969|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
  970|   typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
  971|   typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
  972|                \
  973|   typedef typename Adjust_layout_dim<          
  974|       1, typename Block_layout<DstBlock>::layout_type>::type    
  975|     dst_lp;            
  976|                \
  977|   typedef typename Adjust_layout_dim<          
  978|       1, typename Block_layout<Block1>::layout_type>::type      
  979|     block1_lp;         
  980|                \
  981|   typedef typename Adjust_layout_dim<          
  982|       1, typename Block_layout<Block2>::layout_type>::type      
  983|     block2_lp;         
  984|                \
  985|   typedef typename Adjust_layout_dim<          
  986|       1, typename Block_layout<Block3>::layout_type>::type      
  987|     block3_lp;         
  988|                \
  989|   static bool const ct_valid =         
  990|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
  991|     (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
  992|     (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
  993|      sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
  994|      /* check that direct access is supported */        
  995|      Ext_data_cost<DstBlock>::value == 0 &&     
  996|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
  997|      (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
  998|      (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
  999|                \
 1000|   static bool rt_valid(DstBlock&, SrcBlock const&)      
 1001|   {            
 1002|     /* SAL supports all strides */      
 1003|     return true;        
 1004|   }            
 1005|                \
 1006|   static void exec(DstBlock& dst, SrcBlock const& src)         
 1007|   {            
 1008|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,               SYNC_OUT);\
 1009|     sal::Ext_wrapper<Block1, block1_lp> ext_1(src.left(),          SYNC_IN);\
 1010|     sal::Ext_wrapper<Block2, block2_lp> ext_2(src.right().left(),  SYNC_IN);\
 1011|     sal::Ext_wrapper<Block3, block3_lp> ext_3(src.right().right(), SYNC_IN);\
 1012|     FUN(typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),  
 1013|         typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),  
 1014|         typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
 1015|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
 1016|         dst.size());          
 1017|   }            
 1018| };
 1019| 
 1020| VSIP_IMPL_SAL_VV_V_EXPR(ma_functor,  op::Mult, op::Add,  sal::vma)
 1021| VSIP_IMPL_SAL_VV_V_EXPR(msb_functor, op::Mult, op::Sub,  sal::vmsb)
 1022| VSIP_IMPL_SAL_VV_V_EXPR(am_functor,  op::Add,  op::Mult, sal::vam)
 1023| VSIP_IMPL_SAL_VV_V_EXPR(sbm_functor, op::Sub,  op::Mult, sal::vsbm)
 1024| 
 1025| VSIP_IMPL_SAL_V_VV_EXPR(ma_functor,  op::Mult, op::Add,  sal::vma)
 1026| VSIP_IMPL_SAL_V_VV_EXPR(msb_functor, op::Mult, op::Sub,  sal::vmsb)
 1027| VSIP_IMPL_SAL_V_VV_EXPR(am_functor,  op::Add,  op::Mult, sal::vam)
 1028| VSIP_IMPL_SAL_V_VV_EXPR(sbm_functor, op::Sub,  op::Mult, sal::vsbm)
 1029| 
 1030| 
 1031| 
 1032| // Nested binary expressions, f(V)V_V
 1033| 
 1034| #define VSIP_IMPL_SAL_fVV_V_EXPR(OP, OP1, OP2, UOP, FUN)        
 1035| template <typename DstBlock,           
 1036|           typename Block1,            
 1037|           typename Type1,      
 1038|           typename Block2,            
 1039|           typename Type2,      
 1040|           typename Block3,            
 1041|           typename Type3,      
 1042|           typename TypeB>      
 1043| struct Serial_expr_evaluator<          
 1044|          1, DstBlock,          
 1045|          Binary_expr_block<            
 1046|            1, OP2,             
 1047|            Binary_expr_block<          
 1048|              1, OP1,           
 1049|              Unary_expr_block<1, UOP, Block1, Type1> const, Type1,      
 1050|              Block2, Type2> const, TypeB,       
 1051|            Block3, Type3> const,        
 1052|          Mercury_sal_tag>       
 1053| {              
 1054|   static char const* name() { return "Expr_SAL_fVV_V"; }        
 1055|                \
 1056|   typedef Binary_expr_block<           
 1057|             1, OP2,            
 1058|             Binary_expr_block<         
 1059|               1, OP1,          
 1060|               Unary_expr_block<1, UOP, Block1, Type1> const, Type1,     
 1061|               Block2, Type2> const, TypeB,      
 1062|             Block3, Type3>      
 1063|         SrcBlock;             
 1064|                \
 1065|   typedef typename DstBlock::value_type dst_type;       
 1066|                \
 1067|   typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t; 
 1068|   typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
 1069|   typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
 1070|   typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
 1071|                \
 1072|   typedef typename Adjust_layout_dim<          
 1073|       1, typename Block_layout<DstBlock>::layout_type>::type    
 1074|     dst_lp;            
 1075|                \
 1076|   typedef typename Adjust_layout_dim<          
 1077|       1, typename Block_layout<Block1>::layout_type>::type      
 1078|     block1_lp;         
 1079|                \
 1080|   typedef typename Adjust_layout_dim<          
 1081|       1, typename Block_layout<Block2>::layout_type>::type      
 1082|     block2_lp;         
 1083|                \
 1084|   typedef typename Adjust_layout_dim<          
 1085|       1, typename Block_layout<Block3>::layout_type>::type      
 1086|     block3_lp;         
 1087|                \
 1088|   static bool const ct_valid =         
 1089|     (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
 1090|     (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
 1091|     (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
 1092|      sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
 1093|      /* check that direct access is supported */        
 1094|      Ext_data_cost<DstBlock>::value == 0 &&     
 1095|      (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
 1096|      (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
 1097|      (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
 1098|                \
 1099|   static bool rt_valid(DstBlock&, SrcBlock const&)      
 1100|   {            
 1101|     /* SAL supports all strides */      
 1102|     return true;        
 1103|   }            
 1104|                \
 1105|   static void exec(DstBlock& dst, SrcBlock const& src)         
 1106|   {            
 1107|     sal::Ext_wrapper<DstBlock, dst_lp>  ext_dst(dst,        SYNC_OUT);  
 1108|     sal::Ext_wrapper<Block1, block1_lp> ext_1(src.left().left().op(),SYNC_IN);\
 1109|     sal::Ext_wrapper<Block2, block2_lp> ext_2(src.left().right(),    SYNC_IN);\
 1110|     sal::Ext_wrapper<Block3, block3_lp> ext_3(src.right(),           SYNC_IN);\
 1111|     FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),  
 1112|         typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),  
 1113|         typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),  
 1114|         typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),        
 1115|         dst.size());          
 1116|   }            
 1117| };
 1118| 
 1119| VSIP_IMPL_SAL_fVV_V_EXPR(sal::cma_token, op::Mult, op::Add, conj_functor,
 1120|                sal::vcma)
 1121| 
 1122| // namespace vsip::impl
 1123| // namespace vsip
 1124| 
 1125| #endif // VSIP_IMPL_SAL_EVAL_HPP