ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 #ifndef IVL_CORE_DETAILS_TYPES_SCALAR_HPP 00025 #define IVL_CORE_DETAILS_TYPES_SCALAR_HPP 00026 00027 namespace ivl { 00028 00029 // ------------------- 00030 00031 template<class T> 00032 struct copyscalar : public types::copyscalar_identifier 00033 { 00034 T t; 00035 copyscalar(T t) : t(t) {} 00036 copyscalar() {} 00037 copyscalar(const copyscalar& o) : t(o.t) {} 00038 copyscalar& operator=(const copyscalar& o) { t = o.t; return *this; } 00039 }; 00040 // ------------------- 00041 00042 00043 template<class T, T V> 00044 class fixed_scalar : public types::scalar_identifier 00045 { 00046 typedef T prv_elem_type; 00047 public: 00048 typedef prv_elem_type elem_type; 00049 fixed_scalar() {} 00050 fixed_scalar(const fixed_scalar& s) {} 00051 template<class J> 00052 fixed_scalar(const J& ) {} 00053 operator prv_elem_type() const { return V; } 00054 prv_elem_type base() const { return V; } 00055 }; 00056 00057 template<int V> 00058 class fixed_scalar<int, V> : public types::scalar_identifier 00059 { 00060 typedef int prv_elem_type; 00061 public: 00062 typedef prv_elem_type elem_type; 00063 fixed_scalar() {} 00064 fixed_scalar(const fixed_scalar& s) {} 00065 template<class J> 00066 fixed_scalar(const J& ) {} 00067 operator prv_elem_type() const { return V; } 00068 prv_elem_type base() const { return V; } 00069 }; 00070 00071 // ------------------------------------------------------------------------- 00072 00073 // scalar of class!! 00074 template<class A, class TP> 00075 struct memberfunc_constructor; 00076 00077 template<class T> 00078 class scalar : public T, 00079 public types::t_if<types::is_base<types::scalar_identifier, T>, 00080 types::nop_base<T>, types::scalar_identifier>::type 00081 { 00082 typedef T prv_elem_type; 00083 public: 00084 typedef prv_elem_type elem_type; 00085 scalar() { } 00086 scalar(const scalar& s) : T(static_cast<const T&>(s)) { } 00087 template <class J> 00088 scalar(const scalar<J>& s) : T(static_cast<const J&>(s)) { } 00089 scalar(const T& s) : T(s) { } 00090 T& base() { return static_cast<T&>(*this); } 00091 const prv_elem_type& base() const { return static_cast<const T&>(*this); } 00092 00093 00094 // ---------------------------------------------- 00095 template<class R, class A1, class Z> 00096 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) 00097 { 00098 return internal::reftpl(*this, m); 00099 } 00100 template<class R, class A1, class Z> 00101 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) const 00102 { 00103 return internal::reftpl(*this, m); 00104 } 00105 // 00106 template<class R, class A1, class Z> 00107 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) 00108 { 00109 return internal::reftpl(*this, m); 00110 } 00111 template<class R, class A1, class Z> 00112 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) const 00113 { 00114 return internal::reftpl(*this, m); 00115 } 00116 00117 // ---------------------------------------------- 00118 00119 template<class R, class A1, class Z> 00120 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) 00121 { 00122 return internal::reftpl(*this, m); 00123 } 00124 template<class R, class A1, class Z> 00125 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) const 00126 { 00127 return internal::reftpl(*this, m); 00128 } 00129 // 00130 template<class R, class A1, class Z> 00131 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) 00132 { 00133 return internal::reftpl(*this, m); 00134 } 00135 template<class R, class A1, class Z> 00136 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) const 00137 { 00138 return internal::reftpl(*this, m); 00139 } 00140 // ---------------------------------------------- 00141 00142 }; 00143 00144 template<class T> 00145 class scalar<T&> : 00146 public types::scalar_identifier 00147 { 00148 typedef typename types::remove_const<T>::type prv_elem_type; 00149 T* ref; 00150 public: 00151 typedef prv_elem_type elem_type; 00152 scalar() : ref(0) { } 00153 scalar(const scalar& s) : ref(s.ref) { } 00154 template <class J> 00155 scalar(const scalar<J>& s) : ref(&static_cast<T&>(s)) { } 00156 scalar(T& s) : ref(&s) { } 00157 T& base() const { return *ref; } 00158 //const prv_elem_type& base() const { return static_cast<const T&>(*ref); } 00159 operator T&() const { return *ref; } 00160 //operator const prv_elem_type&() const { return *ref; } 00161 scalar& operator=(const scalar& s) 00162 { if(!ref) ref=s.ref; else *ref = *s.ref; return *this; } 00163 scalar& operator=(T& s) { if(!ref) ref=&s; else *ref = s; return *this; } 00164 template <class J> 00165 scalar& operator=(const J& o) { *ref = o; return *this; } 00166 00167 00168 // ---------------------------------------------- 00169 template<class R, class A1, class Z> 00170 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) 00171 { 00172 return internal::reftpl(*this, m); 00173 } 00174 template<class R, class A1, class Z> 00175 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) const 00176 { 00177 return internal::reftpl(*this, m); 00178 } 00179 // 00180 template<class R, class A1, class Z> 00181 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) 00182 { 00183 return internal::reftpl(*this, m); 00184 } 00185 template<class R, class A1, class Z> 00186 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) const 00187 { 00188 return internal::reftpl(*this, m); 00189 } 00190 00191 // ---------------------------------------------- 00192 template<class R, class A1, class Z> 00193 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) 00194 { 00195 return internal::reftpl(*this, m); 00196 } 00197 template<class R, class A1, class Z> 00198 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) const 00199 { 00200 return internal::reftpl(*this, m); 00201 } 00202 // 00203 template<class R, class A1, class Z> 00204 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) 00205 { 00206 return internal::reftpl(*this, m); 00207 } 00208 template<class R, class A1, class Z> 00209 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) const 00210 { 00211 return internal::reftpl(*this, m); 00212 } 00213 }; 00214 00215 template<class T> 00216 class scalar<const T&> : 00217 public types::scalar_identifier 00218 { 00219 typedef typename types::remove_const<T>::type prv_elem_type; 00220 const T* ref; 00221 public: 00222 typedef prv_elem_type elem_type; 00223 scalar() : ref(0) { } 00224 scalar(const scalar& s) : ref(s.ref) { } 00225 template <class J> 00226 scalar(const scalar<J>& s) : ref(&static_cast<const T&>(s)) { } 00227 scalar(const T& s) : ref(&s) { } 00228 const T& base() const { return static_cast<const T&>(*ref); } 00229 operator const T&() const { return *ref; } 00230 scalar& operator=(const scalar& s) { ref=s.ref; return *this; } 00231 scalar& operator=(T& s) { ref=&s; return *this; } 00232 00233 00234 // ---------------------------------------------- 00235 template<class R, class A1, class Z> 00236 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) 00237 { 00238 return internal::reftpl(*this, m); 00239 } 00240 template<class R, class A1, class Z> 00241 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > operator[](R (Z::*m)(A1)) const 00242 { 00243 return internal::reftpl(*this, m); 00244 } 00245 // 00246 template<class R, class A1, class Z> 00247 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) 00248 { 00249 return internal::reftpl(*this, m); 00250 } 00251 template<class R, class A1, class Z> 00252 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > operator[](R (Z::*m)(A1) const) const 00253 { 00254 return internal::reftpl(*this, m); 00255 } 00256 00257 // ---------------------------------------------- 00258 template<class R, class A1, class Z> 00259 memberfunc_constructor<scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) 00260 { 00261 return internal::reftpl(*this, m); 00262 } 00263 template<class R, class A1, class Z> 00264 memberfunc_constructor<const scalar, internal::tuple<Z, R, A1> > in(R (Z::*m)(A1)) const 00265 { 00266 return internal::reftpl(*this, m); 00267 } 00268 // 00269 template<class R, class A1, class Z> 00270 memberfunc_constructor<scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) 00271 { 00272 return internal::reftpl(*this, m); 00273 } 00274 template<class R, class A1, class Z> 00275 memberfunc_constructor<const scalar, internal::tuple<const Z, R, A1> > in(R (Z::*m)(A1) const) const 00276 { 00277 return internal::reftpl(*this, m); 00278 } 00279 }; 00280 00281 template<class T> 00282 class scalar<T*> : 00283 public types::scalar_identifier 00284 { 00285 typedef T* prv_elem_type; 00286 T* v; 00287 public: 00288 typedef prv_elem_type elem_type; 00289 scalar() : v(0) { } 00290 scalar(const scalar& s) : v(s.v) { } 00291 template <class J> 00292 scalar(const scalar<J>& s) : v(s) { } 00293 scalar(T* s) : v(s) { } 00294 T* base() const { return v; } 00295 operator T*() const { return v; } 00296 scalar& operator=(const scalar& s) { v = s.v; return *this; } 00297 scalar& operator=(T* s) { v = s; return *this; } 00298 template <class J> 00299 scalar& operator=(const J& o) { v = o; return *this; } 00300 }; 00301 00302 template<class T> 00303 class scalar<const T*> : 00304 public types::scalar_identifier 00305 { 00306 typedef const T* prv_elem_type; 00307 const T* v; 00308 public: 00309 typedef prv_elem_type elem_type; 00310 scalar() : v(0) { } 00311 scalar(const scalar& s) : v(s.v) { } 00312 template <class J> 00313 scalar(const scalar<J>& s) : v(s) { } 00314 scalar(const T* s) : v(s) { } 00315 T* base() const { return v; } 00316 //const prv_elem_type& base() const { return static_cast<const T&>(*ref); } 00317 operator const T*() const { return v; } 00318 //operator const prv_elem_type&() const { return *ref; } 00319 scalar& operator=(const scalar& s) { v = s.v; return *this; } 00320 scalar& operator=(const T* s) { v = s; return *this; } 00321 template <class J> 00322 scalar& operator=(const J& o) { v = o; return *this; } 00323 }; 00324 00325 template<> 00326 class scalar<float> : public types::scalar_identifier 00327 { 00328 typedef float prv_elem_type; 00329 prv_elem_type v; 00330 public: 00331 typedef prv_elem_type elem_type; 00332 scalar() { } 00333 scalar(const scalar& s) : v(static_cast<const prv_elem_type&>(s)) { } 00334 template <class J> 00335 scalar(const scalar<J>& s) : v(static_cast<const J&>(s)) { } 00336 scalar(const prv_elem_type& s) : v(s) { } 00337 operator prv_elem_type&() { return v; } 00338 operator const prv_elem_type&() const { return v; } 00339 prv_elem_type& base() { return v; } 00340 const prv_elem_type& base() const { return v; } 00341 }; 00342 00343 template<> 00344 class scalar<double> : public types::scalar_identifier 00345 { 00346 typedef double prv_elem_type; 00347 prv_elem_type v; 00348 public: 00349 typedef prv_elem_type elem_type; 00350 scalar() { } 00351 scalar(const scalar& s) : v(static_cast<const prv_elem_type&>(s)) { } 00352 template <class J> 00353 scalar(const scalar<J>& s) : v(static_cast<const J&>(s)) { } 00354 scalar(const prv_elem_type& s) : v(s) { } 00355 operator prv_elem_type&() { return v; } 00356 operator const prv_elem_type&() const { return v; } 00357 prv_elem_type& base() { return v; } 00358 const prv_elem_type& base() const { return v; } 00359 }; 00360 00361 //TODO: placed here until reference face issue is fixed. 00362 namespace math { 00363 00364 template <class T, class S> 00365 inline T power(const T& x, const S& y) 00366 { 00367 using std::pow; // TODO: definition of pow in right place. This line may not be needed if this is made. 00368 return pow(x, y); 00369 } 00370 00371 inline int power(int x, int y) 00372 { 00373 // TODO: fix this well, for all types. Also add integer power with different algorithm. 00374 return std::pow((double)x, y); 00375 } 00376 } 00377 00378 #include "platform_specific/scalar_int_impl.hpp" 00379 00380 template<class T> 00381 scalar<T> operator->*(const scalar<T>& x, unsigned int y) 00382 { 00383 return ivl::math::power(x.base(), y); 00384 } 00385 00386 template<class T> 00387 scalar<typename types::to_floating<T>::type> operator->*(const scalar<T>& x, 00388 int y) 00389 { 00390 return ivl::math::power(x.base(), y); 00391 } 00392 00393 template<class T> 00394 scalar<typename types::to_floating<T>::type> operator->*(const scalar<T>& x, 00395 float y) 00396 { 00397 return ivl::math::power(x.base(), y); 00398 } 00399 00400 template<class T> 00401 scalar<typename types::to_floating<T>::type> operator->*(const scalar<T>& x, 00402 double y) 00403 { 00404 return ivl::math::power(x.base(), y); 00405 } 00406 00407 // ---------------------------------------------------- 00408 00409 namespace types { 00410 00411 namespace types_details 00412 { 00413 00414 template <class DESCALARIZE, class T> 00415 struct descalarize_tool { }; 00416 00417 template <class T> 00418 struct descalarize_tool<types::t_false, T> 00419 { 00420 typedef T& type; 00421 static inline type f(T& t) { return t; } 00422 }; 00423 00424 template <class T> 00425 struct descalarize_tool<types::t_true, T> 00426 { 00427 typedef typename types::bare_type<T>::type t_bare; 00428 typedef typename t_bare::elem_type& bare_type; 00429 typedef typename types::apply_const<bare_type, 00430 types::is_const<T> >::type type; 00431 00432 static inline type f(T& t) { return t.base(); } 00433 }; 00434 } /* namespace types_details */ 00435 00436 template<class DESCALARIZE, class T> 00437 typename types_details::descalarize_tool<DESCALARIZE, T> 00438 ::type r_descalarize(T& t) 00439 { 00440 return types_details::descalarize_tool<DESCALARIZE, T>::f(t); 00441 } 00442 template<class DESCALARIZE, class T> 00443 typename types_details::descalarize_tool<DESCALARIZE, const T> 00444 ::type r_descalarize(const T& t) 00445 { 00446 return types_details::descalarize_tool<DESCALARIZE, const T>::f(t); 00447 } 00448 00449 } /* namespace types */ 00450 00451 } /* namespace ivl */ 00452 00453 #endif // IVL_CORE_DETAILS_TYPES_SCALAR_HPP