libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/channel_base_algorithm.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 /*
00032  *  Copyright 2005-2007 Adobe Systems Incorporated
00033  * 
00034  *  Use, modification and distribution are subject to the Boost
00035  *  Software License, Version 1.0. (See accompanying file
00036  *  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
00037  */
00038 
00039 
00040 #ifndef PSYNTH_SOUND_CHANNEL_BASE_ALGORITHM_HPP
00041 #define PSYNTH_SOUND_CHANNEL_BASE_ALGORITHM_HPP
00042 
00043 #include <algorithm>
00044 #include <boost/type_traits.hpp>
00045 #include <boost/utility/enable_if.hpp>
00046 #include <boost/mpl/contains.hpp>
00047 #include <boost/mpl/at.hpp>
00048 
00049 #include <psynth/base/compat.hpp>
00050 #include <psynth/sound/concept.hpp>
00051 #include <psynth/sound/util.hpp>
00052 
00053 namespace psynth
00054 {
00055 namespace sound
00056 {
00057 
00058 /*
00059  *
00060  *   size:   Semantic sample size
00061  *
00062  */
00063 
00083 template <typename ChannelBase>
00084 struct size : public boost::mpl::size<
00085     typename ChannelBase::layout::channel_space> {};
00086 
00087 
00088 /*
00089  *
00090  *    semantic_at_c:   Semantic sample accessors
00091  *
00092  */
00093 
00140 template <typename ChannelBase, int K>
00141 struct kth_semantic_element_type
00142 {
00143     BOOST_STATIC_CONSTANT(
00144         int, semantic_index = (
00145             boost::mpl::at_c<typename ChannelBase::layout::sample_mapping,
00146                       K>::type::value));
00147     typedef typename kth_element_type <ChannelBase, semantic_index>::type type;
00148 };
00149 
00155 template <typename ChannelBase, int K>
00156 struct kth_semantic_element_reference_type
00157 {
00158     BOOST_STATIC_CONSTANT(
00159         int, semantic_index = (
00160             boost::mpl::at_c<typename ChannelBase::layout::sample_mapping,
00161                       K>::type::value));
00162     typedef typename kth_element_reference_type<
00163         ChannelBase, semantic_index>::type type;
00164 
00165     static type get (ChannelBase& cb)
00166     {
00167         return sound::at_c<semantic_index>(cb);
00168     }
00169 };
00170 
00171 
00178 template <typename ChannelBase, int K>
00179 struct kth_semantic_element_const_reference_type
00180 {
00181     BOOST_STATIC_CONSTANT(
00182         int, semantic_index = (
00183             boost::mpl::at_c<typename ChannelBase::layout::sample_mapping,
00184                       K>::type::value));
00185     typedef typename kth_element_const_reference_type<
00186         ChannelBase, semantic_index>::type type;
00187 
00188     static type get (const ChannelBase& cb)
00189     {
00190         return sound::at_c<semantic_index> (cb);
00191     }
00192 };
00193 
00199 template <int K, typename ChannelBase> inline
00200 typename boost::disable_if<
00201     boost::is_const<ChannelBase>,
00202     typename kth_semantic_element_reference_type<ChannelBase,K>::type>::type
00203 semantic_at_c (ChannelBase& p)
00204 { 
00205     return kth_semantic_element_reference_type<ChannelBase, K>::get (p);
00206 }
00207 
00213 template <int K, typename ChannelBase> inline
00214 typename kth_semantic_element_const_reference_type<ChannelBase,K>::type
00215 semantic_at_c (const ChannelBase& p)
00216 { 
00217     return kth_semantic_element_const_reference_type<ChannelBase,K>::get (p); 
00218 }
00219 
00220 
00221 /*
00222  *
00223  *   get_channel:   Named sample accessors
00224  *
00225  */
00226 
00257 template <typename ChannelBase, typename Channel>
00258 struct contains_channel :
00259     public boost::mpl::contains<typename ChannelBase::layout::channel_space,
00260                          Channel> {};
00261 
00262 template <typename ChannelBase, typename Channel>
00263 struct channel_index_type :
00264     public detail::type_to_index<typename ChannelBase::layout::channel_space,
00265                                  Channel> {};
00266 
00272 template <typename ChannelBase, typename Channel>
00273 struct channel_element_type : public kth_semantic_element_type<
00274     ChannelBase, channel_index_type<ChannelBase,Channel>::value> {};
00275 
00282 template <typename ChannelBase, typename Channel>
00283 struct channel_element_reference_type :
00284     public kth_semantic_element_reference_type<
00285     ChannelBase, channel_index_type<ChannelBase, Channel>::value> {};
00286 
00293 template <typename ChannelBase, typename Channel>
00294 struct channel_element_const_reference_type :
00295     public kth_semantic_element_const_reference_type<
00296     ChannelBase, channel_index_type<ChannelBase, Channel>::value> {};
00297 
00303 template <typename ChannelBase, typename Channel> 
00304 typename channel_element_reference_type<ChannelBase,Channel>::type
00305 get_channel (ChannelBase& cb, Channel = Channel())
00306 {
00307     return channel_element_reference_type<ChannelBase, Channel>::get (cb);
00308 }
00309 
00314 template <typename ChannelBase, typename Channel> 
00315 typename channel_element_const_reference_type<ChannelBase,Channel>::type
00316 get_channel (const ChannelBase& cb, Channel=Channel())
00317 {
00318     return channel_element_const_reference_type<ChannelBase,Channel>::get (cb);
00319 }
00320 
00321 
00322 /*
00323  *
00324  *    element_type, element_reference_type,
00325  *    element_const_reference_type: Support for homogeneous channel
00326  *    bases
00327  *
00328  */
00329 
00348 template <typename ChannelBase>
00349 struct element_type : public kth_element_type<ChannelBase, 0> {};
00350 
00357 template <typename ChannelBase>
00358 struct element_reference_type :
00359     public kth_element_reference_type<ChannelBase, 0> {};
00360 
00367 template <typename ChannelBase>
00368 struct element_const_reference_type :
00369     public kth_element_const_reference_type<ChannelBase, 0> {};
00370 
00371 
00372 namespace detail
00373 {
00374 
00375 /* compile-time recursion for per-element operations on channel bases */
00376 template <int N>
00377 struct element_recursion
00378 {
00379     // static_equal
00380     template <typename P1,typename P2>
00381     static bool static_equal (const P1& p1, const P2& p2)
00382     { 
00383         return element_recursion<N-1>::static_equal(p1,p2) &&
00384                semantic_at_c<N-1>(p1) == semantic_at_c<N-1>(p2); 
00385     }
00386     
00387     //static_copy
00388     template <typename P1,typename P2>
00389     static void static_copy(const P1& p1, P2& p2)
00390     {
00391         element_recursion<N-1>::static_copy(p1,p2);
00392         semantic_at_c<N-1>(p2) = semantic_at_c<N-1>(p1);
00393     }
00394     
00395     //static_fill
00396     template <typename P,typename T2>
00397     static void static_fill(P& p, T2 v)
00398     {
00399         element_recursion<N-1>::static_fill (p,v);
00400         semantic_at_c<N-1>(p) = v;
00401     }
00402     
00403     //static_generate
00404     template <typename Dst,typename Op> 
00405     static void static_generate (Dst& dst, Op op)
00406     {
00407         element_recursion<N-1>::static_generate (dst, op);
00408         semantic_at_c<N-1>(dst) = op();
00409     }
00410     
00411     //static_for_each with one source
00412     template <typename P1,typename Op> 
00413     static Op static_for_each (P1& p1, Op op)
00414     {
00415         Op op2 (element_recursion<N-1>::static_for_each (p1,op));
00416         op2 (semantic_at_c<N-1> (p1));
00417         return op2;
00418     }
00419     
00420     template <typename P1,typename Op> 
00421     static Op static_for_each (const P1& p1, Op op)
00422     {
00423         Op op2 (element_recursion<N-1>::static_for_each (p1,op));
00424         op2 (semantic_at_c<N-1> (p1));
00425         return op2;
00426     }
00427     
00428     //static_for_each with two sources
00429     template <typename P1,typename P2,typename Op> 
00430     static Op static_for_each (P1& p1, P2& p2, Op op)
00431     {
00432         Op op2(element_recursion<N-1>::static_for_each (p1, p2, op));
00433         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00434         return op2;
00435     }
00436     
00437     template <typename P1,typename P2,typename Op> 
00438     static Op static_for_each(P1& p1, const P2& p2, Op op)
00439     {
00440         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00441         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00442         return op2;
00443     }
00444 
00445     template <typename P1,typename P2,typename Op> 
00446     static Op static_for_each(const P1& p1, P2& p2, Op op)
00447     {
00448         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00449         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00450         return op2;
00451     }
00452 
00453     template <typename P1,typename P2,typename Op> 
00454     static Op static_for_each(const P1& p1, const P2& p2, Op op)
00455     {
00456         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00457         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00458         return op2;
00459     }
00460 
00461     //static_for_each with three sources
00462     template <typename P1,typename P2,typename P3,typename Op>
00463     static Op static_for_each (P1& p1, P2& p2, P3& p3, Op op)
00464     {
00465         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00466         op2(semantic_at_c<N-1>(p1),
00467             semantic_at_c<N-1>(p2),
00468             semantic_at_c<N-1>(p3));
00469         return op2;
00470     }
00471     
00472     template <typename P1,typename P2,typename P3,typename Op>
00473     static Op static_for_each (P1& p1, P2& p2, const P3& p3, Op op)
00474     {
00475         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00476         op2 (semantic_at_c<N-1>(p1),
00477              semantic_at_c<N-1>(p2),
00478              semantic_at_c<N-1>(p3));
00479         return op2;
00480     }
00481     
00482     template <typename P1,typename P2,typename P3,typename Op>
00483     static Op static_for_each (P1& p1, const P2& p2, P3& p3, Op op)
00484     {
00485         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00486         op2 (semantic_at_c<N-1>(p1),
00487              semantic_at_c<N-1>(p2),
00488              semantic_at_c<N-1>(p3));
00489         return op2;
00490     }
00491     
00492     template <typename P1,typename P2,typename P3,typename Op>
00493     static Op static_for_each (P1& p1, const P2& p2, const P3& p3, Op op)
00494     {
00495         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00496         op2 (semantic_at_c<N-1>(p1),
00497              semantic_at_c<N-1>(p2),
00498              semantic_at_c<N-1>(p3));
00499         return op2;
00500     }
00501     
00502     template <typename P1,typename P2,typename P3,typename Op>
00503     static Op static_for_each (const P1& p1, P2& p2, P3& p3, Op op)
00504     {
00505         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00506         op2 (semantic_at_c<N-1>(p1),
00507              semantic_at_c<N-1>(p2),
00508              semantic_at_c<N-1>(p3));
00509         return op2;
00510     }
00511     
00512     template <typename P1,typename P2,typename P3,typename Op>
00513     static Op static_for_each (const P1& p1, P2& p2, const P3& p3, Op op)
00514     {
00515         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00516         op2 (semantic_at_c<N-1>(p1),
00517              semantic_at_c<N-1>(p2),
00518              semantic_at_c<N-1>(p3));
00519         return op2;
00520     }
00521     
00522     template <typename P1,typename P2,typename P3,typename Op>
00523     static Op static_for_each (const P1& p1, const P2& p2, P3& p3, Op op)
00524     {
00525         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00526         op2 (semantic_at_c<N-1>(p1),
00527              semantic_at_c<N-1>(p2),
00528              semantic_at_c<N-1>(p3));
00529         return op2;
00530     }
00531     
00532     template <typename P1,typename P2,typename P3,typename Op>
00533     static Op static_for_each (const P1& p1, const P2& p2, const P3& p3, Op op)
00534     {
00535         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00536         op2 (semantic_at_c<N-1>(p1),
00537              semantic_at_c<N-1>(p2),
00538              semantic_at_c<N-1>(p3));
00539         return op2;
00540     }
00541     
00542     //static_transform with one source
00543     template <typename P1,typename Dst,typename Op> 
00544     static Op static_transform (P1& src, Dst& dst, Op op)
00545     {
00546         Op op2 (element_recursion<N-1>::static_transform (src,dst,op));
00547         semantic_at_c<N-1> (dst) = op2 (semantic_at_c<N-1> (src));
00548         return op2;
00549     }
00550     
00551     template <typename P1,typename Dst,typename Op> 
00552     static Op static_transform (const P1& src, Dst& dst, Op op)
00553     {
00554         Op op2(element_recursion<N-1>::static_transform(src,dst,op));
00555         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
00556         return op2;
00557     }
00558     
00559     //static_transform with two sources
00560     template <typename P1,typename P2,typename Dst,typename Op>
00561     static Op static_transform (P1& src1, P2& src2, Dst& dst, Op op)
00562     {
00563         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00564         semantic_at_c<N-1>(dst) = op2 (semantic_at_c<N-1>(src1),
00565                                        semantic_at_c<N-1>(src2));
00566         return op2;
00567     }
00568     
00569     template <typename P1,typename P2,typename Dst,typename Op>
00570     static Op static_transform (P1& src1, const P2& src2, Dst& dst, Op op) {
00571         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00572         semantic_at_c<N-1>(dst) = op2 (semantic_at_c<N-1>(src1),
00573                                        semantic_at_c<N-1>(src2));
00574         return op2;
00575     }
00576     
00577     template <typename P1,typename P2,typename Dst,typename Op>
00578     static Op static_transform (const P1& src1, P2& src2, Dst& dst, Op op)
00579     {
00580         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00581         semantic_at_c<N-1>(dst) = op2 (semantic_at_c<N-1>(src1),
00582                                        semantic_at_c<N-1>(src2));
00583         return op2;
00584     }
00585     
00586     template <typename P1,typename P2,typename Dst,typename Op>
00587     static Op static_transform (const P1& src1, const P2& src2, Dst& dst, Op op)
00588     {
00589         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00590         semantic_at_c<N-1>(dst) = op2 (semantic_at_c<N-1>(src1),
00591                                        semantic_at_c<N-1>(src2));
00592         return op2;
00593     }
00594 };
00595 
00596 // Termination condition of the compile-time recursion for element
00597 // operations on a channel base
00598 template<> struct element_recursion<0>
00599 {
00600     //static_equal
00601     template <typename P1,typename P2>
00602     static bool static_equal(const P1&, const P2&) { return true; }
00603     //static_copy
00604     template <typename P1,typename P2>
00605     static void static_copy(const P1&, const P2&) {}
00606     //static_fill
00607     template <typename P, typename T2>
00608     static void static_fill(const P&, T2) {}
00609     //static_generate
00610     template <typename Dst,typename Op>
00611     static void static_generate(const Dst&,Op) {}
00612     //static_for_each with one source
00613     template <typename P1,typename Op>
00614     static Op static_for_each(const P1&,Op op) { return op; }
00615     //static_for_each with two sources
00616     template <typename P1,typename P2,typename Op>
00617     static Op static_for_each(const P1&,const P2&,Op op) { return op; }
00618     //static_for_each with three sources
00619     template <typename P1,typename P2,typename P3,typename Op>
00620     static Op static_for_each(const P1&,const P2&,const P3&,Op op) { return op; }
00621     //static_transform with one source
00622     template <typename P1,typename Dst,typename Op>
00623     static Op static_transform(const P1&,const Dst&,Op op) { return op; }
00624     //static_transform with two sources
00625     template <typename P1,typename P2,typename Dst,typename Op>
00626     static Op static_transform(const P1&,const P2&,const Dst&,Op op) { return op; }
00627 };
00628 
00629 // std::min and std::max don't have the mutable overloads...
00630 template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y)
00631 { return x<y ? x : y; }
00632 template <typename Q> inline       Q& mutable_min(      Q& x,       Q& y)
00633 { return x<y ? x : y; }
00634 template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y)
00635 { return x<y ? y : x; }
00636 template <typename Q> inline       Q& mutable_max(      Q& x,       Q& y)
00637 { return x<y ? y : x; }
00638 
00639 // compile-time recursion for min/max element
00640 template <int N>
00641 struct min_max_recur
00642 {
00643     template <typename P>
00644     static typename element_const_reference_type<P>::type max_ (const P& p)
00645     {
00646         return mutable_max(min_max_recur<N-1>::max_(p), semantic_at_c<N-1>(p));
00647     }
00648     
00649     template <typename P>
00650     static typename element_reference_type<P>::type       max_ (P& p)
00651     {
00652         return mutable_max(min_max_recur<N-1>::max_(p), semantic_at_c<N-1>(p));
00653     }
00654     
00655     template <typename P>
00656     static typename element_const_reference_type<P>::type min_ (const P& p)
00657     {
00658         return mutable_min(min_max_recur<N-1>::min_(p), semantic_at_c<N-1>(p));
00659     }
00660     
00661     template <typename P>
00662     static typename element_reference_type<P>::type       min_ (P& p)
00663     {
00664         return mutable_min(min_max_recur<N-1>::min_(p), semantic_at_c<N-1>(p));
00665     }    
00666 };
00667 
00668 // termination condition of the compile-time recursion for min/max
00669 // element
00670 template <>
00671 struct min_max_recur<1>
00672 {
00673     template <typename P>
00674     static typename element_const_reference_type<P>::type max_(const P& p)
00675     { return semantic_at_c<0>(p); }
00676     template <typename P>
00677     static typename element_reference_type<P>::type       max_(P& p)
00678     { return semantic_at_c<0>(p); }
00679     template <typename P>
00680     static typename element_const_reference_type<P>::type min_(const P& p)
00681     { return semantic_at_c<0>(p); }
00682     template <typename P>
00683     static typename element_reference_type<P>::type       min_(P& p)
00684     { return semantic_at_c<0>(p); }
00685 };
00686 
00687 } /* namespace detail */
00688 
00689 
00706 template <typename P>
00707 PSYNTH_FORCEINLINE
00708 typename element_const_reference_type<P>::type static_max (const P& p)
00709 { return detail::min_max_recur<size<P>::value>::max_(p); }
00710 
00711 template <typename P>
00712 PSYNTH_FORCEINLINE
00713 typename element_reference_type<P>::type       static_max (P& p)
00714 { return detail::min_max_recur<size<P>::value>::max_(p); }
00715 
00716 template <typename P>
00717 PSYNTH_FORCEINLINE
00718 typename element_const_reference_type<P>::type static_min (const P& p)
00719 { return detail::min_max_recur<size<P>::value>::min_(p); }
00720 
00721 template <typename P>
00722 PSYNTH_FORCEINLINE
00723 typename element_reference_type<P>::type       static_min (P& p)
00724 { return detail::min_max_recur<size<P>::value>::min_(p); }
00725 
00745 template <typename P1,typename P2>
00746 PSYNTH_FORCEINLINE
00747 bool static_equal (const P1& p1, const P2& p2)
00748 { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
00749 
00769 template <typename Src,typename Dst>
00770 PSYNTH_FORCEINLINE
00771 void static_copy(const Src& src, Dst& dst)
00772 {  detail::element_recursion<size<Dst>::value>::static_copy(src,dst); }
00773 
00789 template <typename P,typename V>
00790 PSYNTH_FORCEINLINE
00791 void static_fill (P& p, const V& v)
00792 {  detail::element_recursion<size<P>::value>::static_fill(p,v); }
00817 template <typename P1,typename Op>
00818 PSYNTH_FORCEINLINE void static_generate(P1& dst,Op op)
00819 { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
00820 
00854 //static_transform with one source
00855 template <typename Src,typename Dst,typename Op>
00856 PSYNTH_FORCEINLINE
00857 Op static_transform (Src& src, Dst& dst,Op op)
00858 {
00859     return detail::element_recursion<size<Dst>::value>::static_transform (
00860         src, dst, op);
00861 }
00862 
00863 template <typename Src,typename Dst,typename Op>
00864 PSYNTH_FORCEINLINE
00865 Op static_transform (const Src& src, Dst& dst, Op op)
00866 {
00867     return detail::element_recursion<size<Dst>::value>::static_transform (
00868         src, dst, op);
00869 }
00870 
00871 //static_transform with two sources
00872 template <typename P2,typename P3,typename Dst,typename Op>
00873 PSYNTH_FORCEINLINE
00874 Op static_transform (P2& p2, P3& p3, Dst& dst, Op op)
00875 {
00876     return detail::element_recursion<size<Dst>::value>::static_transform (
00877         p2, p3, dst, op);
00878 }
00879 
00880 template <typename P2,typename P3,typename Dst,typename Op>
00881 PSYNTH_FORCEINLINE
00882 Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op)
00883 {
00884     return detail::element_recursion<size<Dst>::value>::static_transform (
00885         p2, p3, dst, op);
00886 }
00887 
00888 template <typename P2,typename P3,typename Dst,typename Op>
00889 PSYNTH_FORCEINLINE
00890 Op static_transform (const P2& p2, P3& p3, Dst& dst, Op op)
00891 {
00892     return detail::element_recursion<size<Dst>::value>::static_transform (
00893         p2, p3, dst, op);
00894 }
00895 
00896 template <typename P2,typename P3,typename Dst,typename Op>
00897 PSYNTH_FORCEINLINE
00898 Op static_transform (const P2& p2, const P3& p3, Dst& dst, Op op)
00899 {
00900     return detail::element_recursion<size<Dst>::value>::static_transform (
00901         p2, p3, dst, op);
00902 }
00903 
00933 //static_for_each with one source
00934 template <typename P1,typename Op>
00935 PSYNTH_FORCEINLINE
00936 Op static_for_each (P1& p1, Op op)
00937 { return detail::element_recursion<size<P1>::value>::static_for_each (p1,op); }
00938 
00939 template <typename P1,typename Op>
00940 PSYNTH_FORCEINLINE
00941 Op static_for_each (const P1& p1, Op op)
00942 { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
00943 
00944 //static_for_each with two sources
00945 template <typename P1,typename P2,typename Op>
00946 PSYNTH_FORCEINLINE
00947 Op static_for_each (P1& p1, P2& p2, Op op)
00948 {
00949     return detail::element_recursion<size<P1>::value>::static_for_each (
00950         p1, p2, op);
00951 }
00952 
00953 template <typename P1,typename P2,typename Op>
00954 PSYNTH_FORCEINLINE
00955 Op static_for_each(P1& p1,const P2& p2, Op op)
00956 { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00957 
00958 template <typename P1,typename P2,typename Op>
00959 PSYNTH_FORCEINLINE
00960 Op static_for_each(const P1& p1, P2& p2, Op op)
00961 { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00962 
00963 template <typename P1,typename P2,typename Op>
00964 PSYNTH_FORCEINLINE
00965 Op static_for_each(const P1& p1,const P2& p2, Op op)
00966 { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00967 
00968 //static_for_each with three sources
00969 template <typename P1,typename P2,typename P3,typename Op>
00970 PSYNTH_FORCEINLINE
00971 Op static_for_each(P1& p1,P2& p2,P3& p3,Op op)
00972 {
00973     return detail::element_recursion<size<P1>::value>::static_for_each(
00974         p1,p2,p3,op);
00975 }
00976 
00977 template <typename P1,typename P2,typename P3,typename Op>
00978 PSYNTH_FORCEINLINE
00979 Op static_for_each(P1& p1,P2& p2,const P3& p3,Op op)
00980 {
00981     return detail::element_recursion<size<P1>::value>::static_for_each(
00982         p1,p2,p3,op);
00983 }
00984 
00985 template <typename P1,typename P2,typename P3,typename Op>
00986 PSYNTH_FORCEINLINE
00987 Op static_for_each(P1& p1,const P2& p2,P3& p3,Op op)
00988 {
00989     return detail::element_recursion<size<P1>::value>::static_for_each(
00990         p1,p2,p3,op);
00991 }
00992 
00993 template <typename P1,typename P2,typename P3,typename Op>
00994 PSYNTH_FORCEINLINE
00995 Op static_for_each(P1& p1,const P2& p2,const P3& p3,Op op)
00996 {
00997     return detail::element_recursion<size<P1>::value>::static_for_each (
00998         p1,p2,p3,op);
00999 }
01000 
01001 template <typename P1,typename P2,typename P3,typename Op>
01002 PSYNTH_FORCEINLINE
01003 Op static_for_each(const P1& p1,P2& p2,P3& p3,Op op)
01004 {
01005     return detail::element_recursion<size<P1>::value>::static_for_each (
01006         p1,p2,p3,op);
01007 }
01008 
01009 template <typename P1,typename P2,typename P3,typename Op>
01010 PSYNTH_FORCEINLINE
01011 Op static_for_each(const P1& p1,P2& p2,const P3& p3,Op op)
01012 {
01013     return detail::element_recursion<size<P1>::value>::static_for_each (
01014         p1,p2,p3,op);
01015 }
01016 
01017 template <typename P1,typename P2,typename P3,typename Op>
01018 PSYNTH_FORCEINLINE
01019 Op static_for_each(const P1& p1,const P2& p2,P3& p3,Op op)
01020 {
01021     return detail::element_recursion<size<P1>::value>::static_for_each(
01022         p1,p2,p3,op);
01023 }
01024 
01025 template <typename P1,typename P2,typename P3,typename Op>
01026 PSYNTH_FORCEINLINE
01027 Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op)
01028 { return detail::element_recursion<size<P1>::value>::static_for_each (
01029         p1,p2,p3,op);
01030 }
01033 } /* namespace sound */
01034 } /* namespace psynth */
01035 
01036 #endif /* PSYNTH_SOUND_CHANNEL_BASE_ALGORITHM */