00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef _VIENNACL_SCALAR_HPP_
00016 #define _VIENNACL_SCALAR_HPP_
00017
00022 #include "viennacl/forwards.h"
00023 #include "viennacl/ocl/backend.hpp"
00024 #include "viennacl/linalg/kernels/scalar_kernels.h"
00025
00026 #include <iostream>
00027
00028 namespace viennacl
00029 {
00037 template <typename LHS, typename RHS, typename OP>
00038 class scalar_expression
00039 {
00040 typedef typename LHS::value_type DummyType;
00041 public:
00042 typedef typename DummyType::value_type ScalarType;
00043
00044 scalar_expression(LHS & lhs, RHS & rhs) : _lhs(lhs), _rhs(rhs) {}
00045
00047 LHS & get_lhs() const { return _lhs; }
00049 RHS & get_rhs() const { return _rhs; }
00050
00052 operator ScalarType () const
00053 {
00054 viennacl::scalar<ScalarType> temp;
00055 temp = *this;
00056 return temp;
00057 }
00058
00059 private:
00060 LHS & _lhs;
00061 RHS & _rhs;
00062 };
00063
00071 template<class TYPE>
00072 class scalar
00073 {
00074 public:
00076 typedef typename viennacl::tools::CHECK_SCALAR_TEMPLATE_ARGUMENT<TYPE>::ResultType value_type;
00077
00079 scalar()
00080 {
00081 viennacl::linalg::kernels::scalar<TYPE, 1>::init();
00082 val_ = viennacl::ocl::current_context().create_memory(CL_MEM_READ_WRITE, sizeof(TYPE));
00083 }
00085 scalar(TYPE val)
00086 {
00087 viennacl::linalg::kernels::scalar<TYPE, 1>::init();
00088 val_ = viennacl::ocl::current_context().create_memory(CL_MEM_READ_WRITE, sizeof(TYPE), &val);
00089 }
00090
00096 explicit scalar(cl_mem mem, size_t size) : val_(mem) { val_.inc(); }
00097
00099 template <typename T1, typename T2, typename OP>
00100 scalar(scalar_expression<T1, T2, OP> const & proxy)
00101 {
00102 viennacl::linalg::kernels::scalar<TYPE, 1>::init();
00103 val_ = viennacl::ocl::current_context().create_memory(CL_MEM_READ_WRITE, sizeof(TYPE));
00104 *this = proxy;
00105 }
00106
00107
00109 scalar(const scalar & other) : val_(viennacl::ocl::current_context().create_memory(CL_MEM_READ_WRITE, sizeof(TYPE)))
00110 {
00111
00112 cl_int err = clEnqueueCopyBuffer(viennacl::ocl::get_queue().handle(), other.handle(), handle(), 0, 0, sizeof(TYPE), 0, NULL, NULL);
00113 VIENNACL_ERR_CHECK(err);
00114 }
00115
00117 operator TYPE() const
00118 {
00119 TYPE tmp;
00120 cl_int err;
00121 err = clEnqueueReadBuffer(viennacl::ocl::get_queue().handle(), val_, CL_TRUE, 0, sizeof(TYPE), &tmp, 0, NULL, NULL);
00122 VIENNACL_ERR_CHECK(err);
00123 return tmp;
00124 }
00125
00127 scalar<TYPE> & operator= (entry_proxy<TYPE> const & other)
00128 {
00129
00130 cl_int err = clEnqueueCopyBuffer(viennacl::ocl::get_queue().handle(), other.handle(), handle(), other.index() * sizeof(TYPE), 0, sizeof(TYPE), 0, NULL, NULL);
00131 VIENNACL_ERR_CHECK(err);
00132 return *this;
00133 }
00134
00136 scalar<TYPE> & operator= (scalar<TYPE> const & other)
00137 {
00138
00139 cl_int err = clEnqueueCopyBuffer(viennacl::ocl::get_queue().handle(), other.handle(), handle(), 0, 0, sizeof(TYPE), 0, NULL, NULL);
00140 VIENNACL_ERR_CHECK(err);
00141
00142 return *this;
00143 }
00144
00145 scalar<TYPE> & operator= (float cpu_other)
00146 {
00147
00148 TYPE other = cpu_other;
00149 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00150 VIENNACL_ERR_CHECK(err);
00151
00152 return *this;
00153 }
00154
00155 scalar<TYPE> & operator= (double cpu_other)
00156 {
00157
00158 TYPE other = cpu_other;
00159 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00160 VIENNACL_ERR_CHECK(err);
00161
00162 return *this;
00163 }
00164
00165 scalar<TYPE> & operator= (long cpu_other)
00166 {
00167
00168 TYPE other = cpu_other;
00169 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00170 VIENNACL_ERR_CHECK(err);
00171
00172 return *this;
00173 }
00174
00175 scalar<TYPE> & operator= (unsigned long cpu_other)
00176 {
00177
00178 TYPE other = cpu_other;
00179 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00180 VIENNACL_ERR_CHECK(err);
00181
00182 return *this;
00183 }
00184
00185 scalar<TYPE> & operator= (int cpu_other)
00186 {
00187
00188 TYPE other = cpu_other;
00189 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00190 VIENNACL_ERR_CHECK(err);
00191
00192 return *this;
00193 }
00194
00195 scalar<TYPE> & operator= (unsigned int cpu_other)
00196 {
00197
00198 TYPE other = cpu_other;
00199 cl_int err = clEnqueueWriteBuffer(viennacl::ocl::get_queue().handle(), handle(), CL_TRUE, 0, sizeof(TYPE), &other, 0, NULL, NULL);
00200 VIENNACL_ERR_CHECK(err);
00201
00202 return *this;
00203 }
00205 template <typename T1, typename T2>
00206 scalar<TYPE> & operator= (scalar_expression<T1, T2, op_inner_prod> const & proxy)
00207 {
00208 viennacl::linalg::inner_prod_impl(proxy.get_lhs(), proxy.get_rhs(), *this);
00209 return *this;
00210 }
00211
00213 template <typename T1, typename T2>
00214 scalar<TYPE> & operator= (scalar_expression<T1, T2, op_norm_1> const & proxy)
00215 {
00216 viennacl::linalg::norm_1_impl(proxy.get_lhs(), *this);
00217 return *this;
00218 }
00219
00221 template <typename T1, typename T2>
00222 scalar<TYPE> & operator= (scalar_expression<T1, T2, op_norm_2> const & proxy)
00223 {
00224 viennacl::linalg::norm_2_impl(proxy.get_lhs(), *this);
00225 return *this;
00226 }
00227
00229 template <typename T1, typename T2>
00230 scalar<TYPE> & operator= (scalar_expression<T1, T2, op_norm_inf> const & proxy)
00231 {
00232 viennacl::linalg::norm_inf_impl(proxy.get_lhs(), *this);
00233 return *this;
00234 }
00235
00237 scalar<TYPE> & operator += (scalar<TYPE> const & other)
00238 {
00239
00240 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "inplace_add");
00241 k.local_work_size(0, 1);
00242 k.global_work_size(0, 1);
00243
00244 viennacl::ocl::enqueue(k(val_, other.val_));
00245 return *this;
00246 }
00248 scalar<TYPE> & operator += (TYPE other)
00249 {
00250
00251 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_inplace_add");
00252 k.local_work_size(0, 1);
00253 k.global_work_size(0, 1);
00254
00255 viennacl::ocl::enqueue(k(val_, other.val_));
00256 return *this;
00257 }
00258
00259
00261 scalar<TYPE> & operator -= (scalar<TYPE> const & other)
00262 {
00263
00264 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "inplace_sub");
00265 k.local_work_size(0, 1);
00266 k.global_work_size(0, 1);
00267
00268 viennacl::ocl::enqueue(k(val_, other.val_));
00269 return *this;
00270 }
00272 scalar<TYPE> & operator -= (TYPE other)
00273 {
00274
00275 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_inplace_sub");
00276 k.local_work_size(0, 1);
00277 k.global_work_size(0, 1);
00278
00279 viennacl::ocl::enqueue(k(val_, other.val_));
00280 return *this;
00281 }
00282
00283
00285 scalar<TYPE> & operator *= (scalar<TYPE> const & other)
00286 {
00287
00288 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "inplace_mul");
00289 k.local_work_size(0, 1);
00290 k.global_work_size(0, 1);
00291
00292 viennacl::ocl::enqueue(k(val_, other.val_));
00293 return *this;
00294 }
00296 scalar<TYPE> & operator *= (TYPE other)
00297 {
00298
00299 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_inplace_mul");
00300 k.local_work_size(0, 1);
00301 k.global_work_size(0, 1);
00302
00303 viennacl::ocl::enqueue(k(val_, other.val_));
00304 return *this;
00305 }
00306
00307
00309
00310 scalar<TYPE> & operator /= (scalar<TYPE> const & other)
00311 {
00312
00313 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "inplace_div");
00314 k.local_work_size(0, 1);
00315 k.global_work_size(0, 1);
00316
00317 viennacl::ocl::enqueue(k(val_, other.val_));
00318 return *this;
00319 }
00321 scalar<TYPE> & operator /= (TYPE other)
00322 {
00323
00324 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_inplace_div");
00325 k.local_work_size(0, 1);
00326 k.global_work_size(0, 1);
00327
00328 viennacl::ocl::enqueue(k(val_, other.val_));
00329 return *this;
00330 }
00331
00332
00334
00335 scalar<TYPE> operator + (scalar<TYPE> const & other)
00336 {
00337 scalar<TYPE> result;
00338
00339 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "add");
00340 k.local_work_size(0, 1);
00341 k.global_work_size(0, 1);
00342
00343 viennacl::ocl::enqueue(k(val_, other.val_, result));
00344 return result;
00345 }
00347 template <typename T1, typename T2, typename OP>
00348 scalar<TYPE> operator + (scalar_expression<T1, T2, OP> const & proxy) const
00349 {
00350 scalar<TYPE> result = proxy;
00351
00352 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "add");
00353 k.local_work_size(0, 1);
00354 k.global_work_size(0, 1);
00355
00356 viennacl::ocl::enqueue(k(val_, result, result));
00357 return result;
00358 }
00360 scalar<TYPE> operator + (TYPE other)
00361 {
00362 scalar<TYPE> result;
00363
00364 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_add");
00365 k.local_work_size(0, 1);
00366 k.global_work_size(0, 1);
00367
00368 viennacl::ocl::enqueue(k(val_, other, result));
00369 return result;
00370 }
00371
00372
00374
00375 scalar<TYPE> operator - (scalar<TYPE> const & other) const
00376 {
00377 scalar<TYPE> result;
00378
00379 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "sub");
00380 k.local_work_size(0, 1);
00381 k.global_work_size(0, 1);
00382
00383 viennacl::ocl::enqueue(k(val_, other.val_, result));
00384 return result;
00385 }
00387 template <typename T1, typename T2, typename OP>
00388 scalar<TYPE> operator - (scalar_expression<T1, T2, OP> const & proxy) const
00389 {
00390 scalar<TYPE> result = *this;
00391
00392 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "sub");
00393 k.local_work_size(0, 1);
00394 k.global_work_size(0, 1);
00395
00396 viennacl::ocl::enqueue(k(val_, result, result));
00397 return result;
00398 }
00400 scalar<TYPE> operator - (TYPE other) const
00401 {
00402 scalar<TYPE> result;
00403
00404 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_sub");
00405 k.local_work_size(0, 1);
00406 k.global_work_size(0, 1);
00407
00408 viennacl::ocl::enqueue(k(val_, other, result));
00409 return result;
00410
00411 return result;
00412 }
00413
00415
00416 scalar<TYPE> operator * (scalar<TYPE> const & other) const
00417 {
00418 scalar<TYPE> result;
00419
00420 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "mul");
00421 k.local_work_size(0, 1);
00422 k.global_work_size(0, 1);
00423
00424 viennacl::ocl::enqueue(k(val_, other.val_, result));
00425 return result;
00426 }
00428 template <typename T1, typename T2, typename OP>
00429 scalar<TYPE> operator * (scalar_expression<T1, T2, OP> const & proxy) const
00430 {
00431 scalar<TYPE> result = proxy;
00432
00433 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "mul");
00434 k.local_work_size(0, 1);
00435 k.global_work_size(0, 1);
00436
00437 viennacl::ocl::enqueue(k(val_, result, result));
00438 return result;
00439 }
00441 scalar<TYPE> operator * (TYPE other) const
00442 {
00443 scalar<TYPE> result;
00444
00445 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_mul");
00446 k.local_work_size(0, 1);
00447 k.global_work_size(0, 1);
00448
00449 viennacl::ocl::enqueue(k(val_, other, result));
00450 return result;
00451 }
00452
00454
00455 scalar<TYPE> operator / (scalar<TYPE> const & other) const
00456 {
00457 scalar<TYPE> result;
00458
00459 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "divide");
00460 k.local_work_size(0, 1);
00461 k.global_work_size(0, 1);
00462
00463 viennacl::ocl::enqueue(k(val_, other.val_, result));
00464 return result;
00465 }
00467 template <typename T1, typename T2, typename OP>
00468 scalar<TYPE> operator / (scalar_expression<T1, T2, OP> const & proxy) const
00469 {
00470 scalar<TYPE> result = proxy;
00471
00472 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "divide");
00473 k.local_work_size(0, 1);
00474 k.global_work_size(0, 1);
00475
00476 viennacl::ocl::enqueue(k(val_, result, result));
00477 return result;
00478 }
00480 scalar<TYPE> operator / (TYPE other) const
00481 {
00482 scalar<TYPE> result;
00483
00484 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(viennacl::linalg::kernels::scalar<TYPE, 1>::program_name(), "cpu_div");
00485 k.local_work_size(0, 1);
00486 k.global_work_size(0, 1);
00487
00488 viennacl::ocl::enqueue(k(val_, other, result));
00489 return result;
00490 }
00491
00493 const viennacl::ocl::handle<cl_mem> & handle() const { return val_; }
00494
00495 private:
00496 viennacl::ocl::handle<cl_mem> val_;
00497 };
00498
00499
00500
00502 template<class SCALARTYPE>
00503 std::ostream & operator<<(std::ostream & s, const scalar<SCALARTYPE> & val)
00504 {
00505 SCALARTYPE temp = val;
00506 s << temp;
00507 return s;
00508 }
00509
00511 template<class SCALARTYPE>
00512 std::istream & operator>>(std::istream & s, const scalar<SCALARTYPE> & val)
00513 {
00514 SCALARTYPE temp;
00515 s >> temp;
00516 val = temp;
00517 return s;
00518 }
00519
00520 }
00521
00522 #endif