|
libpsynth 0.2.1
|
00001 00017 /* 00018 * Copyright (C) 2010 Juan Pedro Bolivar Puente 00019 * 00020 * This file is part of Psychosynth. 00021 * 00022 * Psychosynth is free software: you can redistribute it and/or modify 00023 * it under the terms of the GNU General Public License as published by 00024 * the Free Software Foundation, either version 3 of the License, or 00025 * (at your option) any later version. 00026 * 00027 * Psychosynth is distributed in the hope that it will be useful, 00028 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00030 * GNU General Public License for more details. 00031 * 00032 * You should have received a copy of the GNU General Public License 00033 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00034 * 00035 */ 00036 00037 /* 00038 * Copyright 2005-2007 Adobe Systems Incorporated 00039 * 00040 * Use, modification and distribution are subject to the Boost 00041 * Software License, Version 1.0. (See accompanying file 00042 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 00043 */ 00044 00045 #ifndef PSYNTH_SOUND_APPLY_OPERATION_BASE_HPP 00046 #define PSYNTH_SOUND_APPLY_OPERATION_BASE_HPP 00047 00048 #include <psynth/base/compat.hpp> 00049 #include <psynth/sound/util.hpp> 00050 00051 #include <boost/mpl/begin.hpp> 00052 #include <boost/mpl/next.hpp> 00053 #include <boost/mpl/deref.hpp> 00054 #include <boost/mpl/size.hpp> 00055 #include <boost/preprocessor/repeat.hpp> 00056 00057 namespace psynth 00058 { 00059 namespace sound 00060 { 00061 00062 /* 00063 GENERATE_APPLY_FWD_OPS 00064 generates for every N functions that look like this (for N==2): 00065 00066 template <> struct apply_operation_fwd_fn<3> { 00067 template <typename Types, typename Bits, typename UnaryOp> 00068 typename UnaryOp::result_type apply(Bits& bits, 00069 std::size_t index, UnaryOp op) const 00070 { 00071 typedef typename boost::mpl::begin<Types>::type T0; 00072 typedef typename boost::mpl::next<T0>::type T1; 00073 typedef typename boost::mpl::next<T1>::type T2; 00074 00075 switch (index) { 00076 case 0: return op( 00077 reinterpret_cast<typename boost::mpl::deref<T0>::type&>(bits)); 00078 case 1: return op( 00079 reinterpret_cast<typename boost::mpl::deref<T1>::type&>(bits)); 00080 case 2: return op( 00081 reinterpret_cast<typename boost::mpl::deref<T2>::type&>(bits)); 00082 } 00083 throw; 00084 } 00085 00086 template <typename Types, typename Bits, typename UnaryOp> 00087 typename UnaryOp::result_type applyc ( 00088 const Bits& bits, std::size_t index, UnaryOp op) const 00089 { 00090 typedef typename boost::mpl::begin<Types>::type T0; 00091 typedef typename boost::mpl::next<T0>::type T1; 00092 typedef typename boost::mpl::next<T1>::type T2; 00093 00094 switch (index) 00095 { 00096 case 0: return op( 00097 reinterpret_cast<const typename boost::mpl::deref<T0>::type&>(bits)); 00098 case 1: return op( 00099 reinterpret_cast<const typename boost::mpl::deref<T1>::type&>(bits)); 00100 case 2: return op( 00101 reinterpret_cast<const typename boost::mpl::deref<T2>::type&>(bits)); 00102 } 00103 throw; 00104 } 00105 }; 00106 */ 00107 00108 #define PSYNTH_FWD_TYPEDEFS(z, N, text) \ 00109 T##N; \ 00110 typedef typename boost::mpl::next<T##N>::type 00111 00112 #define PSYNTH_FWD_CASE(z, N, SUM) \ 00113 case N: return op( \ 00114 *psynth_reinterpret_cast<typename boost::mpl::deref<T##N>::type*>( \ 00115 &bits)); 00116 00117 #define PSYNTH_FWD_CONST_CASE(z, N, SUM) \ 00118 case N: return op( \ 00119 *psynth_reinterpret_cast_c<const typename boost::mpl::deref<T##N>::type*>( \ 00120 &bits)); 00121 00122 #define PSYNTH_FWD_CASE_WITH_INFO(z, N, SUM) \ 00123 case N: return op( \ 00124 *psynth_reinterpret_cast<typename boost::mpl::deref<T##N>::type*>( \ 00125 &bits), info); 00126 00127 #define PSYNTH_FWD_CONST_CASE_WITH_INFO(z, N, SUM) \ 00128 case N: return op( \ 00129 *psynth_reinterpret_cast_c<const typename boost::mpl::deref<T##N>::type*>( \ 00130 &bits), info); 00131 00132 #define PSYNTH_APPLY_FWD_OP(z, N, text) \ 00133 template <> struct apply_operation_fwd_fn<BOOST_PP_ADD(N,1)> { \ 00134 template <typename Types, typename Bits, typename UnaryOp> \ 00135 typename UnaryOp::result_type apply ( \ 00136 Bits& bits, std::size_t index, UnaryOp op) const \ 00137 { \ 00138 typedef typename boost::mpl::begin<Types>::type \ 00139 BOOST_PP_REPEAT(N, PSYNTH_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ 00140 T##N; \ 00141 switch (index) { \ 00142 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), PSYNTH_FWD_CASE, \ 00143 BOOST_PP_EMPTY) \ 00144 } \ 00145 throw; \ 00146 } \ 00147 template <typename Types, typename Bits, typename UnaryOp> \ 00148 typename UnaryOp::result_type applyc ( \ 00149 const Bits& bits, std::size_t index, UnaryOp op) const \ 00150 { \ 00151 typedef typename boost::mpl::begin<Types>::type \ 00152 BOOST_PP_REPEAT(N, PSYNTH_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ 00153 T##N; \ 00154 switch (index) { \ 00155 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), PSYNTH_FWD_CONST_CASE, \ 00156 BOOST_PP_EMPTY) \ 00157 } \ 00158 throw; \ 00159 } \ 00160 template <typename Types, typename Info, \ 00161 typename Bits, typename UnaryOp> \ 00162 typename UnaryOp::result_type apply ( \ 00163 Bits& bits, std::size_t index, \ 00164 const Info& info, UnaryOp op) const \ 00165 { \ 00166 typedef typename boost::mpl::begin<Types>::type \ 00167 BOOST_PP_REPEAT(N, PSYNTH_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ 00168 T##N; \ 00169 switch (index) { \ 00170 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), PSYNTH_FWD_CASE_WITH_INFO, \ 00171 BOOST_PP_EMPTY) \ 00172 } \ 00173 throw; \ 00174 } \ 00175 template <typename Types, typename Bits, typename Info, typename UnaryOp> \ 00176 typename UnaryOp::result_type applyc( \ 00177 const Bits& bits, std::size_t index, \ 00178 const Info& info, UnaryOp op) const { \ 00179 typedef typename boost::mpl::begin<Types>::type \ 00180 BOOST_PP_REPEAT(N, PSYNTH_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ 00181 T##N; \ 00182 switch (index) { \ 00183 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), \ 00184 PSYNTH_FWD_CONST_CASE_WITH_INFO,BOOST_PP_EMPTY) \ 00185 } \ 00186 throw; \ 00187 } \ 00188 }; 00189 00190 #define PSYNTH_GENERATE_APPLY_FWD_OPS(N) \ 00191 BOOST_PP_REPEAT(N, PSYNTH_APPLY_FWD_OP, BOOST_PP_EMPTY) 00192 00193 namespace detail 00194 { 00195 00196 template <std::size_t N> 00197 struct apply_operation_fwd_fn {}; 00198 00199 // Create specializations of apply_operation_fn for each N 0..100 00200 PSYNTH_GENERATE_APPLY_FWD_OPS(10) 00201 00202 } /* namespace detail */ 00203 00204 // unary application 00205 template <typename Types, typename Bits, typename Op> 00206 typename Op::result_type PSYNTH_FORCEINLINE 00207 apply_operation_basec (const Bits& bits, std::size_t index, Op op) 00208 { 00209 return detail::apply_operation_fwd_fn< 00210 boost::mpl::size<Types>::value>().template applyc<Types> ( 00211 bits, index, op); 00212 } 00213 00214 // unary application 00215 template <typename Types, typename Bits, typename Op> 00216 typename Op::result_type PSYNTH_FORCEINLINE 00217 apply_operation_base (Bits& bits, std::size_t index, Op op) 00218 { 00219 return detail::apply_operation_fwd_fn< 00220 boost::mpl::size<Types>::value>().template apply<Types> ( 00221 bits,index,op); 00222 } 00223 00224 namespace detail 00225 { 00226 00227 template <typename T2, typename Op> 00228 struct reduce_bind1 00229 { 00230 const T2& _t2; 00231 Op& _op; 00232 00233 typedef typename Op::result_type result_type; 00234 00235 reduce_bind1(const T2& t2, Op& op) 00236 : _t2(t2), _op(op) {} 00237 00238 template <typename T1> PSYNTH_FORCEINLINE 00239 result_type operator () (const T1& t1) 00240 { return _op(t1, _t2); } 00241 }; 00242 00243 template <typename Types1, typename Bits1, typename Op> 00244 struct reduce_bind2 00245 { 00246 const Bits1& _bits1; 00247 std::size_t _index1; 00248 Op& _op; 00249 00250 typedef typename Op::result_type result_type; 00251 00252 reduce_bind2 (const Bits1& bits1, std::size_t index1, Op& op) 00253 : _bits1 (bits1) 00254 , _index1 (index1) 00255 , _op (op) 00256 {} 00257 00258 template <typename T2> PSYNTH_FORCEINLINE 00259 result_type operator () (const T2& t2) 00260 { 00261 return apply_operation_basec<Types1> ( 00262 _bits1, _index1, reduce_bind1<T2,Op> (t2, _op)); 00263 } 00264 }; 00265 00266 } /* namespace detail */ 00267 00268 // Binary application by applying on each dimension separately 00269 template <typename Types1, typename Types2, 00270 typename Bits1, typename Bits2, typename Op> 00271 static PSYNTH_FORCEINLINE 00272 typename Op::result_type apply_operation_base ( 00273 const Bits1& bits1, std::size_t index1, 00274 const Bits2& bits2, std::size_t index2, Op op) 00275 { 00276 return apply_operation_basec<Types2> ( 00277 bits2, index2, detail::reduce_bind2<Types1,Bits1,Op>( 00278 bits1, index1, op)); 00279 } 00280 00281 #undef PSYNTH_FWD_TYPEDEFS 00282 #undef PSYNTH_FWD_CASE 00283 #undef PSYNTH_FWD_CONST_CASE 00284 #undef PSYNTH_APPLY_FWD_OP 00285 #undef PSYNTH_GENERATE_APPLY_FWD_OPS 00286 00287 } /* namespace sound */ 00288 } /* namespace psynth */ 00289 00290 #endif /* PSYNTH_SOUND_APPLY_OPERATION_BASE */
1.7.4