libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/apply_operation_base.hpp
Go to the documentation of this file.
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 */