ViennaCL - The Vienna Computing Library  1.5.1
viennacl/generator/mapped_objects.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_GENERATOR_MAPPED_TYPE_HPP
00002 #define VIENNACL_GENERATOR_MAPPED_TYPE_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, 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 <string>
00027 
00028 #include "viennacl/scheduler/forwards.h"
00029 #include "viennacl/generator/forwards.h"
00030 #include "viennacl/generator/utils.hpp"
00031 
00032 namespace viennacl{
00033 
00034   namespace generator{
00035 
00036     namespace detail{
00037 
00038 
00041       class mapped_object{
00042         protected:
00044           struct node_info{
00045               node_info() : mapping(NULL), statement(NULL), root_node(NULL) { }
00046               mapping_type const * mapping;
00047               scheduler::statement const * statement;
00048               scheduler::statement_node const * root_node;
00049           };
00051           virtual std::string generate_default(std::pair<std::string, std::string> const & index) const = 0;
00052           virtual std::string append_vector_size(std::string const & scalartype, unsigned int) const { return scalartype; }
00053 
00054         public:
00055           mapped_object(std::string const & scalartype) : scalartype_(scalartype){          }
00056           virtual std::string & append_kernel_arguments(std::set<std::string> &, std::string & str, unsigned int) const{ return str; }
00057           std::string const & scalartype() const { return scalartype_; }
00058           void access_name(std::string const & str) { access_name_ = str; }
00059           std::string const & access_name() const { return access_name_; }
00060           virtual std::string generate(std::pair<std::string, std::string> const & index, int) const{
00061             if(!access_name_.empty())
00062               return access_name_;
00063             else
00064               return generate_default(index);
00065           }
00066           virtual ~mapped_object(){ }
00067         protected:
00068           std::string access_name_;
00069           std::string scalartype_;
00070       };
00071 
00074       class mapped_binary_leaf : public mapped_object{
00075         public:
00076           mapped_binary_leaf(std::string const & scalartype) : mapped_object(scalartype){ }
00077           mapping_type const & mapping() const { return *info_.mapping; }
00078           scheduler::statement const & statement() const { return *info_.statement; }
00079           scheduler::statement_node const & root_node() const { return *info_.root_node; }
00080           std::string generate_default(std::pair<std::string, std::string> const &) const { return "";}
00081         protected:
00082           node_info info_;
00083       };
00084 
00086       class mapped_matrix_product : public mapped_binary_leaf{
00087           friend class map_functor;
00088         public:
00089           mapped_matrix_product(std::string const & scalartype) : mapped_binary_leaf(scalartype){ }
00090       };
00091 
00093       class mapped_reduction : public mapped_binary_leaf{
00094         public:
00095           mapped_reduction(std::string const & scalartype) : mapped_binary_leaf(scalartype){ }
00096           viennacl::scheduler::operation_node_type reduction_type() const { return reduction_type_; }
00097         private:
00098           viennacl::scheduler::operation_node_type reduction_type_;
00099       };
00100 
00102       class mapped_scalar_reduction : public mapped_reduction{
00103           friend class map_functor;
00104         public:
00105           mapped_scalar_reduction(std::string const & scalartype) : mapped_reduction(scalartype){ }
00106       };
00107 
00109       class mapped_vector_reduction : public mapped_reduction{
00110           friend class map_functor;
00111         public:
00112           mapped_vector_reduction(std::string const & scalartype) : mapped_reduction(scalartype){ }
00113       };
00114 
00116       class mapped_host_scalar : public mapped_object{
00117           friend class map_functor;
00118           std::string generate_default(std::pair<std::string, std::string> const &) const{ return name_;  }
00119         public:
00120           mapped_host_scalar(std::string const & scalartype) : mapped_object(scalartype){ }
00121           std::string const & name() { return name_; }
00122           std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int) const{
00123             if(already_generated.insert(name_).second)
00124               str += detail::generate_value_kernel_argument(scalartype_, name_);
00125             return str;
00126           }
00127 
00128         private:
00129           std::string name_;
00130       };
00131 
00133       class mapped_handle : public mapped_object{
00134           virtual std::string offset(std::pair<std::string, std::string> const & index) const = 0;
00135           virtual void append_optional_arguments(std::string &) const{ }
00136           std::string generate_default(std::pair<std::string, std::string> const & index) const{ return name_  + '[' + offset(index) + ']'; }
00137         public:
00138           mapped_handle(std::string const & scalartype) : mapped_object(scalartype){ }
00139 
00140           std::string const & name() const { return name_; }
00141 
00142           void fetch(std::pair<std::string, std::string> const & index, unsigned int vectorization, std::set<std::string> & fetched, utils::kernel_generation_stream & stream) {
00143             std::string new_access_name = name_ + "_private";
00144             if(fetched.find(name_)==fetched.end()){
00145               stream << scalartype_;
00146               if(vectorization > 1) stream << vectorization;
00147               stream << " " << new_access_name << " = " << generate_default(index) << ';' << std::endl;
00148               fetched.insert(name_);
00149             }
00150             access_name_ = new_access_name;
00151           }
00152 
00153           void write_back(std::pair<std::string, std::string> const & index, std::set<std::string> & fetched, utils::kernel_generation_stream & stream) {
00154             std::string old_access_name = access_name_ ;
00155             access_name_ = "";
00156             if(fetched.find(name_)!=fetched.end()){
00157               stream << generate_default(index) << " = " << old_access_name << ';' << std::endl;
00158               fetched.erase(name_);
00159             }
00160           }
00161 
00162           std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int vector_size) const{
00163             if(already_generated.insert(name_).second){
00164               std::string vector_scalartype = append_vector_size(scalartype_, vector_size);
00165               str += detail::generate_pointer_kernel_argument("__global", vector_scalartype, name_);
00166               append_optional_arguments(str);
00167             }
00168             return str;
00169           }
00170 
00171         protected:
00172           std::string name_;
00173       };
00174 
00176       class mapped_scalar : public mapped_handle{
00177           friend class map_functor;
00178         private:
00179           std::string offset(std::pair<std::string, std::string> const &)  const { return "0"; }
00180         public:
00181           mapped_scalar(std::string const & scalartype) : mapped_handle(scalartype){ }
00182       };
00183 
00184 
00186       class mapped_buffer : public mapped_handle{
00187         protected:
00188           std::string append_vector_size(std::string const & scalartype, unsigned int vector_size) const {
00189             if(vector_size>1)
00190               return scalartype + utils::to_string(vector_size);
00191             else
00192               return scalartype;
00193           }
00194         public:
00195           mapped_buffer(std::string const & scalartype) : mapped_handle(scalartype){ }
00196           virtual std::string generate(std::pair<std::string, std::string> const & index, int vector_element) const{
00197             if(vector_element>-1)
00198               return mapped_object::generate(index, vector_element)+".s"+utils::to_string(vector_element);
00199             return mapped_object::generate(index, vector_element);
00200           }
00201 
00202       };
00203 
00205       class mapped_vector : public mapped_buffer{
00206           friend class map_functor;
00207           std::string offset(std::pair<std::string, std::string> const & index) const {
00208             if(info_.statement){
00209               std::string str;
00210               detail::generate_all_rhs(*info_.statement, *info_.root_node, index, -1, str, *info_.mapping);
00211               return str;
00212             }
00213             else
00214               return index.first;
00215           }
00216 
00217           void append_optional_arguments(std::string & str) const{
00218             if(!start_name_.empty())
00219               str += detail::generate_value_kernel_argument("unsigned int", start_name_);
00220             if(!stride_name_.empty())
00221               str += detail::generate_value_kernel_argument("unsigned int", stride_name_);
00222             if(!shift_name_.empty())
00223               str += detail::generate_value_kernel_argument("unsigned int", shift_name_);
00224           }
00225         public:
00226           mapped_vector(std::string const & scalartype) : mapped_buffer(scalartype){ }
00227         private:
00228           node_info info_;
00229 
00230           std::string start_name_;
00231           std::string stride_name_;
00232           std::string shift_name_;
00233       };
00234 
00236       class mapped_matrix : public mapped_buffer{
00237           friend class map_functor;
00238           void append_optional_arguments(std::string & str) const{
00239             if(!start1_name_.empty())
00240               str += detail::generate_value_kernel_argument("unsigned int", start1_name_);
00241             if(!stride1_name_.empty())
00242               str += detail::generate_value_kernel_argument("unsigned int", stride1_name_);
00243             if(!start2_name_.empty())
00244               str += detail::generate_value_kernel_argument("unsigned int", start2_name_);
00245             if(!stride2_name_.empty())
00246               str += detail::generate_value_kernel_argument("unsigned int", stride2_name_);
00247           }
00248         public:
00249           mapped_matrix(std::string const & scalartype) : mapped_buffer(scalartype){ }
00250 
00251           bool is_row_major() const { return is_row_major_; }
00252 
00253           std::string const & size1() const { return size1_; }
00254 
00255           std::string const & size2() const { return size2_; }
00256 
00257           void bind_sizes(std::string const & size1, std::string const & size2) const{
00258             size1_ = size1;
00259             size2_ = size2;
00260           }
00261 
00262           std::string offset(std::pair<std::string, std::string> const & index) const {
00263             std::string i = index.first;
00264             std::string j = index.second;
00265             if(is_row_major_)
00266               if(j=="0")
00267                 return '(' + i + ')' + '*' + size2_;
00268               else
00269                 return '(' + i + ')' + '*' + size2_ + "+ (" + j + ')';
00270             else
00271               if(i=="0")
00272                 return  "(" + j + ')' + '*' + size1_;
00273               else
00274                 return  '(' + i + ')' + "+ (" + j + ')' + '*' + size1_;
00275           }
00276 
00277         private:
00278           mutable std::string size1_;
00279           mutable std::string size2_;
00280 
00281           std::string start1_name_;
00282           std::string stride1_name_;
00283           std::string shift1_name_;
00284           std::string start2_name_;
00285           std::string stride2_name_;
00286           std::string shift2_name_;
00287           bool is_row_major_;
00288       };
00289 
00291       class mapped_implicit_vector : public mapped_object{
00292           friend class map_functor;
00293           std::string value_name_;
00294           std::string index_name_;
00295         public:
00296           mapped_implicit_vector(std::string const & scalartype) : mapped_object(scalartype){ }
00297           std::string generate_default(std::pair<std::string, std::string> const & /*index*/) const{
00298             return value_name_;
00299           }
00300           std::string & append_kernel_arguments(std::set<std::string> & /*already_generated*/, std::string & str, unsigned int /*vector_size*/) const{
00301             if(!value_name_.empty())
00302               str += detail::generate_value_kernel_argument(scalartype_, value_name_);
00303             if(!index_name_.empty())
00304               str += detail::generate_value_kernel_argument("unsigned int", index_name_);
00305             return str;
00306           }
00307       };
00308 
00310       class mapped_implicit_matrix : public mapped_object{
00311           friend class map_functor;
00312           std::string value_name_;
00313         public:
00314           mapped_implicit_matrix(std::string const & scalartype) : mapped_object(scalartype){ }
00315           std::string generate_default(std::pair<std::string, std::string> const & /* index */) const{
00316             return value_name_;
00317           }
00318           std::string & append_kernel_arguments(std::set<std::string> & /*already generated*/, std::string & str, unsigned int /*vector size*/) const{
00319             if(!value_name_.empty())
00320               str += detail::generate_value_kernel_argument(scalartype_, value_name_);
00321             return str;
00322           }
00323       };
00324 
00325       inline std::string generate(std::pair<std::string, std::string> const & index, int vector_element, mapped_object const & s){
00326         return s.generate(index, vector_element);
00327       }
00328 
00329       static void fetch(std::pair<std::string, std::string> const & index, unsigned int vectorization, std::set<std::string> & fetched, utils::kernel_generation_stream & stream, mapped_object & s){
00330         if(mapped_handle * p = dynamic_cast<mapped_handle  *>(&s))
00331           p->fetch(index, vectorization, fetched, stream);
00332       }
00333 
00334       static std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int vector_size, mapped_object const & s){
00335         return s.append_kernel_arguments(already_generated, str, vector_size);
00336       }
00337 
00338     }
00339 
00340   }
00341 
00342 }
00343 #endif