ViennaCL - The Vienna Computing Library  1.5.2
viennacl/linalg/opencl/kernels/nmf.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_OPENCL_KERNELS_NMF_HPP
00002 #define VIENNACL_LINALG_OPENCL_KERNELS_NMF_HPP
00003 
00004 #include "viennacl/tools/tools.hpp"
00005 #include "viennacl/ocl/kernel.hpp"
00006 #include "viennacl/ocl/platform.hpp"
00007 #include "viennacl/ocl/utils.hpp"
00008 
00011 namespace viennacl
00012 {
00013   namespace linalg
00014   {
00015     namespace opencl
00016     {
00017       namespace kernels
00018       {
00019 
00020         template <typename StringType>
00021         void generate_nmf_el_wise_mul_div(StringType & source, std::string const & numeric_string)
00022         {
00023           source.append("__kernel void el_wise_mul_div( \n");
00024           source.append("          __global "); source.append(numeric_string); source.append(" * matrix1, \n");
00025           source.append("          __global const "); source.append(numeric_string); source.append(" * matrix2, \n");
00026           source.append("          __global const "); source.append(numeric_string); source.append(" * matrix3, \n");
00027           source.append("          unsigned int size) \n");
00028           source.append("{ \n");
00029           source.append("  for (unsigned int i = get_global_id(0); i < size; i += get_global_size(0)) \n");
00030           source.append("  { \n");
00031           source.append("    "); source.append(numeric_string); source.append(" val = matrix1[i] * matrix2[i]; \n");
00032           source.append("    "); source.append(numeric_string); source.append(" divisor = matrix3[i]; \n");
00033           source.append("    matrix1[i] = (divisor > ("); source.append(numeric_string); source.append(")0.00001) ? (val / divisor) : ("); source.append(numeric_string); source.append(")0; \n");
00034           source.append("  } \n");
00035           source.append("} \n");
00036         }
00037 
00038         // main kernel class
00040         template <class NumericT>
00041         struct nmf
00042         {
00043           static std::string program_name()
00044           {
00045             return viennacl::ocl::type_to_string<NumericT>::apply() + "_nmf";
00046           }
00047 
00048           static void init(viennacl::ocl::context & ctx)
00049           {
00050             viennacl::ocl::DOUBLE_PRECISION_CHECKER<NumericT>::apply(ctx);
00051             std::string numeric_string = viennacl::ocl::type_to_string<NumericT>::apply();
00052 
00053             static std::map<cl_context, bool> init_done;
00054             if (!init_done[ctx.handle().get()])
00055             {
00056               std::string source;
00057               source.reserve(8192);
00058 
00059               viennacl::ocl::append_double_precision_pragma<NumericT>(ctx, source);
00060 
00061               // only generate for floating points (forces error for integers)
00062               if (numeric_string == "float" || numeric_string == "double")
00063               {
00064                 generate_nmf_el_wise_mul_div(source, numeric_string);
00065               }
00066 
00067               std::string prog_name = program_name();
00068               #ifdef VIENNACL_BUILD_INFO
00069               std::cout << "Creating program " << prog_name << std::endl;
00070               #endif
00071               ctx.add_program(source, prog_name);
00072               init_done[ctx.handle().get()] = true;
00073             } //if
00074           } //init
00075         };
00076 
00077       }  // namespace kernels
00078     }  // namespace opencl
00079   }  // namespace linalg
00080 }  // namespace viennacl
00081 #endif
00082