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