ViennaCL - The Vienna Computing Library
1.5.1
|
00001 #ifndef VIENNACL_SCALAR_HPP_ 00002 #define VIENNACL_SCALAR_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 00025 #include <iostream> 00026 00027 #include "viennacl/forwards.h" 00028 #include "viennacl/backend/memory.hpp" 00029 #include "viennacl/meta/result_of.hpp" 00030 #include "viennacl/linalg/scalar_operations.hpp" 00031 #include "viennacl/traits/handle.hpp" 00032 00033 #ifdef VIENNACL_WITH_OPENCL 00034 #include "viennacl/ocl/backend.hpp" 00035 #endif 00036 00037 namespace viennacl 00038 { 00046 template <typename LHS, typename RHS, typename OP> 00047 class scalar_expression 00048 { 00049 typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00050 public: 00051 typedef typename viennacl::result_of::cpu_value_type<DummyType>::type ScalarType; 00052 00053 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00054 00056 LHS & lhs() const { return lhs_; } 00058 RHS & rhs() const { return rhs_; } 00059 00061 operator ScalarType () const 00062 { 00063 viennacl::scalar<ScalarType> temp; 00064 temp = *this; 00065 return temp; 00066 } 00067 00068 private: 00069 LHS & lhs_; 00070 RHS & rhs_; 00071 }; 00072 00073 00081 template <typename LHS, typename RHS> 00082 class scalar_expression<LHS, RHS, op_inner_prod> 00083 { 00084 //typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00085 public: 00086 typedef typename viennacl::result_of::cpu_value_type<LHS>::type ScalarType; 00087 00088 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00089 00091 LHS & lhs() const { return lhs_; } 00093 RHS & rhs() const { return rhs_; } 00094 00096 operator ScalarType () const 00097 { 00098 ScalarType result; 00099 viennacl::linalg::inner_prod_cpu(lhs_, rhs_, result); 00100 return result; 00101 } 00102 00103 private: 00104 LHS & lhs_; 00105 RHS & rhs_; 00106 }; 00107 00108 00114 template <typename LHS, typename RHS> 00115 class scalar_expression<LHS, RHS, op_norm_1> 00116 { 00117 //typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00118 public: 00119 typedef typename viennacl::result_of::cpu_value_type<LHS>::type ScalarType; 00120 00121 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00122 00124 LHS & lhs() const { return lhs_; } 00126 RHS & rhs() const { return rhs_; } 00127 00129 operator ScalarType () const 00130 { 00131 ScalarType result; 00132 viennacl::linalg::norm_1_cpu(lhs_, result); 00133 return result; 00134 } 00135 00136 private: 00137 LHS & lhs_; 00138 RHS & rhs_; 00139 }; 00140 00146 template <typename LHS, typename RHS> 00147 class scalar_expression<LHS, RHS, op_norm_2> 00148 { 00149 //typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00150 public: 00151 typedef typename viennacl::result_of::cpu_value_type<LHS>::type ScalarType; 00152 00153 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00154 00156 LHS & lhs() const { return lhs_; } 00158 RHS & rhs() const { return rhs_; } 00159 00161 operator ScalarType () const 00162 { 00163 ScalarType result; 00164 viennacl::linalg::norm_2_cpu(lhs_, result); 00165 return result; 00166 } 00167 00168 private: 00169 LHS & lhs_; 00170 RHS & rhs_; 00171 }; 00172 00173 00179 template <typename LHS, typename RHS> 00180 class scalar_expression<LHS, RHS, op_norm_inf> 00181 { 00182 //typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00183 public: 00184 typedef typename viennacl::result_of::cpu_value_type<LHS>::type ScalarType; 00185 00186 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00187 00189 LHS & lhs() const { return lhs_; } 00191 RHS & rhs() const { return rhs_; } 00192 00194 operator ScalarType () const 00195 { 00196 ScalarType result; 00197 viennacl::linalg::norm_inf_cpu(lhs_, result); 00198 return result; 00199 } 00200 00201 private: 00202 LHS & lhs_; 00203 RHS & rhs_; 00204 }; 00205 00211 template <typename LHS, typename RHS> 00212 class scalar_expression<LHS, RHS, op_norm_frobenius> 00213 { 00214 //typedef typename LHS::value_type DummyType; //Visual C++ 2005 does not allow to write LHS::value_type::value_type 00215 public: 00216 typedef typename viennacl::result_of::cpu_value_type<LHS>::type ScalarType; 00217 00218 scalar_expression(LHS & lhs, RHS & rhs) : lhs_(lhs), rhs_(rhs) {} 00219 00221 LHS & lhs() const { return lhs_; } 00223 RHS & rhs() const { return rhs_; } 00224 00226 operator ScalarType () const 00227 { 00228 ScalarType result; 00229 viennacl::linalg::norm_frobenius_cpu(lhs_, result); 00230 return result; 00231 } 00232 00233 private: 00234 LHS & lhs_; 00235 RHS & rhs_; 00236 }; 00237 00238 00239 00240 00248 template<class SCALARTYPE> 00249 class scalar 00250 { 00251 typedef scalar<SCALARTYPE> self_type; 00252 public: 00253 typedef viennacl::backend::mem_handle handle_type; 00254 typedef vcl_size_t size_type; 00255 00257 typedef SCALARTYPE value_type; 00258 00260 scalar() {} 00261 00263 scalar(SCALARTYPE val, viennacl::context ctx = viennacl::context()) 00264 { 00265 viennacl::backend::memory_create(val_, sizeof(SCALARTYPE), ctx, &val); 00266 } 00267 00268 #ifdef VIENNACL_WITH_OPENCL 00269 00274 explicit scalar(cl_mem mem, size_type /*size*/) 00275 { 00276 val_.switch_active_handle_id(viennacl::OPENCL_MEMORY); 00277 val_.opencl_handle() = mem; 00278 val_.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the vector object is destroyed. 00279 } 00280 #endif 00281 00283 template <typename T1, typename T2, typename OP> 00284 scalar(scalar_expression<T1, T2, OP> const & proxy) 00285 { 00286 val_.switch_active_handle_id(viennacl::traits::handle(proxy.lhs()).get_active_handle_id()); 00287 viennacl::backend::memory_create(val_, sizeof(SCALARTYPE), viennacl::traits::context(proxy)); 00288 *this = proxy; 00289 } 00290 00291 //copy constructor 00293 scalar(const scalar & other) 00294 { 00295 if (other.handle().get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED) 00296 { 00297 //copy value: 00298 val_.switch_active_handle_id(other.handle().get_active_handle_id()); 00299 viennacl::backend::memory_create(val_, sizeof(SCALARTYPE), viennacl::traits::context(other)); 00300 viennacl::backend::memory_copy(other.handle(), val_, 0, 0, sizeof(SCALARTYPE)); 00301 } 00302 } 00303 00305 operator SCALARTYPE() const 00306 { 00307 // make sure the scalar contains reasonable data: 00308 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized, cannot read!")); 00309 00310 SCALARTYPE tmp; 00311 viennacl::backend::memory_read(val_, 0, sizeof(SCALARTYPE), &tmp); 00312 return tmp; 00313 } 00314 00316 self_type & operator= (entry_proxy<SCALARTYPE> const & other) 00317 { 00318 init_if_necessary(viennacl::traits::context(other)); 00319 viennacl::backend::memory_copy(other.handle(), val_, other.index() * sizeof(SCALARTYPE), 0, sizeof(SCALARTYPE)); 00320 return *this; 00321 } 00322 00324 self_type & operator= (scalar<SCALARTYPE> const & other) 00325 { 00326 init_if_necessary(viennacl::traits::context(other)); 00327 viennacl::backend::memory_copy(other.handle(), val_, 0, 0, sizeof(SCALARTYPE)); 00328 return *this; 00329 } 00330 00331 self_type & operator= (float cpu_other) 00332 { 00333 init_if_necessary(viennacl::context()); 00334 00335 //copy value: 00336 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00337 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00338 return *this; 00339 } 00340 00341 self_type & operator= (double cpu_other) 00342 { 00343 init_if_necessary(viennacl::context()); 00344 00345 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00346 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00347 return *this; 00348 } 00349 00350 self_type & operator= (long cpu_other) 00351 { 00352 init_if_necessary(viennacl::context()); 00353 00354 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00355 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00356 return *this; 00357 } 00358 00359 self_type & operator= (unsigned long cpu_other) 00360 { 00361 init_if_necessary(viennacl::context()); 00362 00363 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00364 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00365 return *this; 00366 } 00367 00368 self_type & operator= (int cpu_other) 00369 { 00370 init_if_necessary(viennacl::context()); 00371 00372 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00373 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00374 return *this; 00375 } 00376 00377 self_type & operator= (unsigned int cpu_other) 00378 { 00379 init_if_necessary(viennacl::context()); 00380 00381 SCALARTYPE value = static_cast<SCALARTYPE>(cpu_other); 00382 viennacl::backend::memory_write(val_, 0, sizeof(SCALARTYPE), &value); 00383 return *this; 00384 } 00385 00387 template <typename T1, typename T2> 00388 self_type & operator= (scalar_expression<T1, T2, op_inner_prod> const & proxy) 00389 { 00390 init_if_necessary(viennacl::traits::context(proxy)); 00391 00392 viennacl::linalg::inner_prod_impl(proxy.lhs(), proxy.rhs(), *this); 00393 return *this; 00394 } 00395 00397 template <typename T1, typename T2> 00398 self_type & operator= (scalar_expression<T1, T2, op_norm_1> const & proxy) 00399 { 00400 init_if_necessary(viennacl::traits::context(proxy)); 00401 00402 viennacl::linalg::norm_1_impl(proxy.lhs(), *this); 00403 return *this; 00404 } 00405 00407 template <typename T1, typename T2> 00408 self_type & operator= (scalar_expression<T1, T2, op_norm_2> const & proxy) 00409 { 00410 init_if_necessary(viennacl::traits::context(proxy)); 00411 00412 viennacl::linalg::norm_2_impl(proxy.lhs(), *this); 00413 return *this; 00414 } 00415 00417 template <typename T1, typename T2> 00418 self_type & operator= (scalar_expression<T1, T2, op_norm_inf> const & proxy) 00419 { 00420 init_if_necessary(viennacl::traits::context(proxy)); 00421 00422 viennacl::linalg::norm_inf_impl(proxy.lhs(), *this); 00423 return *this; 00424 } 00425 00427 template <typename T1, typename T2> 00428 self_type & operator= (scalar_expression<T1, T2, op_norm_frobenius> const & proxy) 00429 { 00430 init_if_necessary(viennacl::traits::context(proxy)); 00431 00432 viennacl::linalg::norm_frobenius_impl(proxy.lhs(), *this); 00433 return *this; 00434 } 00435 00437 template <typename T1, typename T2> 00438 self_type & operator= (scalar_expression<T1, T2, op_flip_sign> const & proxy) 00439 { 00440 init_if_necessary(viennacl::traits::context(proxy)); 00441 00442 viennacl::linalg::as(*this, proxy.lhs(), SCALARTYPE(-1.0), 1, false, true); 00443 return *this; 00444 } 00445 00446 00448 self_type & operator += (scalar<SCALARTYPE> const & other) 00449 { 00450 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00451 00452 viennacl::linalg::asbs(*this, // s1 = 00453 *this, SCALARTYPE(1.0), 1, false, false, // s1 * 1.0 00454 other, SCALARTYPE(1.0), 1, false, false); // + s2 * 1.0 00455 return *this; 00456 } 00458 self_type & operator += (SCALARTYPE other) 00459 { 00460 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00461 00462 viennacl::linalg::asbs(*this, // s1 = 00463 *this, SCALARTYPE(1.0), 1, false, false, // s1 * 1.0 00464 other, SCALARTYPE(1.0), 1, false, false); // + s2 * 1.0 00465 return *this; 00466 } 00467 00468 00470 self_type & operator -= (scalar<SCALARTYPE> const & other) 00471 { 00472 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00473 00474 viennacl::linalg::asbs(*this, // s1 = 00475 *this, SCALARTYPE(1.0), 1, false, false, // s1 * 1.0 00476 other, SCALARTYPE(-1.0), 1, false, false); // + s2 * (-1.0) 00477 return *this; 00478 } 00480 self_type & operator -= (SCALARTYPE other) 00481 { 00482 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00483 00484 viennacl::linalg::asbs(*this, // s1 = 00485 *this, SCALARTYPE(1.0), 1, false, false, // s1 * 1.0 00486 other, SCALARTYPE(-1.0), 1, false, false); // + s2 * (-1.0) 00487 return *this; 00488 } 00489 00490 00492 self_type & operator *= (scalar<SCALARTYPE> const & other) 00493 { 00494 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00495 00496 viennacl::linalg::as(*this, // s1 = 00497 *this, other, 1, false, false); // s1 * s2 00498 return *this; 00499 } 00501 self_type & operator *= (SCALARTYPE other) 00502 { 00503 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00504 00505 viennacl::linalg::as(*this, // s1 = 00506 *this, other, 1, false, false); // s1 * s2 00507 return *this; 00508 } 00509 00510 00512 00513 self_type & operator /= (scalar<SCALARTYPE> const & other) 00514 { 00515 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00516 00517 viennacl::linalg::as(*this, // s1 = 00518 *this, other, 1, true, false); // s1 / s2 00519 return *this; 00520 } 00522 self_type & operator /= (SCALARTYPE other) 00523 { 00524 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00525 00526 viennacl::linalg::as(*this, // s1 = 00527 *this, other, 1, true, false); // s1 / s2 00528 return *this; 00529 } 00530 00531 00533 00534 self_type operator + (scalar<SCALARTYPE> const & other) 00535 { 00536 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00537 00538 self_type result = 0; 00539 00540 viennacl::linalg::asbs(result, // result = 00541 *this, SCALARTYPE(1.0), 1, false, false, // *this * 1.0 00542 other, SCALARTYPE(1.0), 1, false, false); // + other * 1.0 00543 00544 return result; 00545 } 00547 template <typename T1, typename T2, typename OP> 00548 self_type operator + (scalar_expression<T1, T2, OP> const & proxy) const 00549 { 00550 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00551 00552 self_type result = proxy; 00553 00554 viennacl::linalg::asbs(result, // result = 00555 *this, SCALARTYPE(1.0), 1, false, false, // *this * 1.0 00556 result, SCALARTYPE(1.0), 1, false, false); // + result * 1.0 00557 00558 return result; 00559 } 00561 self_type operator + (SCALARTYPE other) 00562 { 00563 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00564 00565 self_type result = 0; 00566 00567 viennacl::linalg::asbs(result, // result = 00568 *this, SCALARTYPE(1.0), 1, false, false, // *this * 1.0 00569 other, SCALARTYPE(1.0), 1, false, false); // + other * 1.0 00570 00571 return result; 00572 } 00573 00574 00576 00578 scalar_expression<const self_type, const self_type, op_flip_sign> operator-() const 00579 { 00580 return scalar_expression<const self_type, const self_type, op_flip_sign>(*this, *this); 00581 } 00582 00583 00585 self_type operator - (scalar<SCALARTYPE> const & other) const 00586 { 00587 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00588 00589 self_type result = 0; 00590 00591 viennacl::linalg::asbs(result, // result = 00592 *this, SCALARTYPE(1.0), 1, false, false, // *this * 1.0 00593 other, SCALARTYPE(-1.0), 1, false, false); // + other * (-1.0) 00594 00595 return result; 00596 } 00598 template <typename T1, typename T2, typename OP> 00599 self_type operator - (scalar_expression<T1, T2, OP> const & proxy) const 00600 { 00601 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00602 00603 self_type result = proxy; 00604 00605 viennacl::linalg::asbs(result, // result = 00606 *this, SCALARTYPE(1.0), 1 , false, false, // *this * 1.0 00607 result, SCALARTYPE(-1.0), 1, false, false); // + result * (-1.0) 00608 00609 return result; 00610 } 00612 scalar<SCALARTYPE> operator - (SCALARTYPE other) const 00613 { 00614 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00615 00616 self_type result = 0; 00617 00618 viennacl::linalg::asbs(result, // result = 00619 *this, SCALARTYPE(1.0), 1, false, false, // *this * 1.0 00620 other, SCALARTYPE(-1.0), 1, false, false); // + other * (-1.0) 00621 00622 return result; 00623 } 00624 00626 00627 self_type operator * (scalar<SCALARTYPE> const & other) const 00628 { 00629 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00630 00631 scalar<SCALARTYPE> result = 0; 00632 00633 viennacl::linalg::as(result, // result = 00634 *this, other, 1, false, false); // *this * other 00635 00636 return result; 00637 } 00639 template <typename T1, typename T2, typename OP> 00640 self_type operator * (scalar_expression<T1, T2, OP> const & proxy) const 00641 { 00642 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00643 00644 self_type result = proxy; 00645 00646 viennacl::linalg::as(result, // result = 00647 *this, result, 1, false, false); // *this * proxy 00648 00649 return result; 00650 } 00652 self_type operator * (SCALARTYPE other) const 00653 { 00654 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00655 00656 scalar<SCALARTYPE> result = 0; 00657 00658 viennacl::linalg::as(result, // result = 00659 *this, other, 1, false, false); // *this * other 00660 00661 return result; 00662 } 00663 00665 00666 self_type operator / (scalar<SCALARTYPE> const & other) const 00667 { 00668 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00669 00670 self_type result = 0; 00671 00672 viennacl::linalg::as(result, // result = 00673 *this, other, 1, true, false); // *this / other 00674 00675 return result; 00676 } 00678 template <typename T1, typename T2, typename OP> 00679 self_type operator / (scalar_expression<T1, T2, OP> const & proxy) const 00680 { 00681 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00682 00683 self_type result = proxy; 00684 00685 viennacl::linalg::as(result, // result = 00686 *this, result, 1, true, false); // *this / proxy 00687 00688 return result; 00689 } 00691 self_type operator / (SCALARTYPE other) const 00692 { 00693 assert( val_.get_active_handle_id() != viennacl::MEMORY_NOT_INITIALIZED && bool("Scalar not initialized!")); 00694 00695 self_type result = 0; 00696 00697 viennacl::linalg::as(result, // result = 00698 *this, other, 1, true, false); // *this / other 00699 00700 return result; 00701 } 00702 00704 handle_type & handle() { return val_; } 00705 00707 const handle_type & handle() const { return val_; } 00708 00709 private: 00710 00711 void init_if_necessary(viennacl::context ctx) 00712 { 00713 if (val_.get_active_handle_id() == viennacl::MEMORY_NOT_INITIALIZED) 00714 { 00715 viennacl::backend::memory_create(val_, sizeof(SCALARTYPE), ctx); 00716 } 00717 } 00718 00719 handle_type val_; 00720 }; 00721 00722 00723 //stream operators: 00725 template<class SCALARTYPE> 00726 std::ostream & operator<<(std::ostream & s, const scalar<SCALARTYPE> & val) 00727 { 00728 SCALARTYPE temp = val; 00729 s << temp; 00730 return s; 00731 } 00732 00734 template<class SCALARTYPE> 00735 std::istream & operator>>(std::istream & s, const scalar<SCALARTYPE> & val) 00736 { 00737 SCALARTYPE temp; 00738 s >> temp; 00739 val = temp; 00740 return s; 00741 } 00742 00743 } //namespace viennacl 00744 00745 #endif