ivl 679
ivl/details/core/math/cast.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_MATH_CAST_HPP
00025 #define IVL_CORE_DETAILS_MATH_CAST_HPP
00026 
00027 namespace ivl {
00028 
00029 // ... unfortunately here we need forward declarations
00030 template <class J, class K> class cast_class;
00031 
00032 template<class R, template<typename, typename> class F, class A>
00033 struct unary_elem_func_result;
00034 
00035 /* TODO: this was there. uncomment to play.
00036 template<class R, class A>
00037 inline
00038 typename unary_elem_func_result<
00039         typename types::get_value<R>::type, cast_class, A>::type cast(const A& in);
00040         */
00041 // ...
00042 /*
00043 template<class R, class A>
00044 inline
00045 typename unary_elem_func_result<
00046         typename types::get_value<R>::type, cast_class, A>::type cast(const A& in);
00047 */
00048 
00049 template<class R, class A>
00050 inline
00051 typename unary_elem_func_result<
00052         typename types::change_data_class_set_rec<data::fixed<1>, R>::type,
00053                 cast_class, A>::type cast(const A& in);
00054 
00055 
00056 namespace math {
00057 namespace math_details {
00058 
00059 // -----------------------------------------------------------
00060 
00061 template <class T, bool BUILTIN>
00062 struct spec_cast_complex_initializer { };
00063 
00064 // converting an integer or floating-point type to complex requires .real()
00065 template <class T>
00066 struct spec_cast_complex_initializer<T, true>
00067 {
00068         template <class S>
00069         static inline S from(const std::complex<S>& x) { return x.real(); }
00070 };
00071 
00072 // any other type should be implicitly converted if conversion is supported.
00073 template <class T>
00074 struct spec_cast_complex_initializer<T, false>
00075 {
00076         template <class S>
00077         static inline const std::complex<S>& from(const std::complex<S>& x)
00078         { return x; }
00079 };
00080 
00081 // conversion of complex to non-complex, not bool type, requires specialization
00082 template <class T>
00083 struct cast_complex_initializer
00084 : public spec_cast_complex_initializer<T, types::is_builtin<T>::value>
00085 {
00086 };
00087 
00088 // conversion of complex to bool returns true if .real() or .imag() is != 0
00089 template <>
00090 struct cast_complex_initializer<bool>
00091 {
00092         template <class S>
00093         static inline bool from(const std::complex<S>& x)
00094         { return x.real() || x.imag(); }
00095 };
00096 
00097 // -----------------------------------------------------------
00098 
00099 template <class T>
00100 struct cast_initializer : public cast_complex_initializer<T>
00101 {
00102         using cast_complex_initializer<T>::from;
00103 
00104         template <class S>
00105         static inline const S& from(const S& x) { return x; }
00106 };
00107 
00108 template <class T>
00109 struct cast_initializer<std::complex<T> >
00110 {
00111         template <class S>
00112         static inline T from(const S& x) { return T(x); }
00113 
00114         template <class S>
00115         static inline std::complex<T> from(const std::complex<S>& x)
00116         { return std::complex<T>(T(x.real()), T(x.imag())); }
00117 };
00118 
00119 // -----------------------------------------------------------
00120 
00121 } /* namespace math_details */
00122 
00123 template <class T, class S>
00124 inline
00125 T cast(const S& x)
00126 {
00127         return T(math_details::cast_initializer<T>::from(x));
00128 }
00129 
00130 // -----------------------------------------------------------
00131 
00132 namespace math_details {
00133 
00134 template <class T, bool IS_ARRAY>
00135 struct spec_elem_cast_result
00136 {
00137 };
00138 
00139 template <class T>
00140 struct spec_elem_cast_result<T, false>
00141 {
00142         typedef T type;
00143         typedef T elem_type;
00144         template <class S>
00145         inline type from(const S& x)
00146         {
00147                 return type(math_details::cast_initializer<T>::from(x));
00148         }
00149 };
00150 
00151 template <class A>
00152 struct spec_elem_cast_result<A, true>
00153 {
00154         typedef typename A::derived_type type;
00155         typedef typename A::elem_type elem_type;
00156         template <class S>
00157         inline type from(const S& x)
00158         {
00159                 // note: need to have ivl::cast predeclared.
00160                 // (which is defined in unary_elem_functions)
00161                 return type(ivl::cast<elem_type>(x));
00162         }
00163 };
00164 
00165 /*
00166 // on : todo.
00167 // also decide like array<int> = array<double>;
00168 
00169 template<class T>
00170 struct elem_cast_result
00171 : public spec_elem_cast_result<T, types::is_array<T>::value>
00172 {
00173 };
00174 */
00175 
00176 } /* namespace math_details */
00177 
00178 /*
00179 // same as cast for simple elements
00180 template <class T, class S>
00181 inline
00182 typename types_details::elem_cast_result<T>::type elem_cast(const S& x)
00183 {
00184         return types_details::elem_cast_result<T>::from(x);
00185 }
00186 */
00187 
00188 
00189 } /* namespace math */
00190 } /* namespace ivl */
00191 
00192 #endif // IVL_CORE_DETAILS_MATH_CAST_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations