ivl 679
ivl/details/core/types/scalar.hpp
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations