Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*-
  2.  
  3. // Copyright (C) 2007-2013 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the terms
  7. // of the GNU General Public License as published by the Free Software
  8. // Foundation; either version 3, or (at your option) any later
  9. // version.
  10.  
  11. // This library is distributed in the hope that it will be useful, but
  12. // WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. // General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. /**
  26.  * @file parallel/numeric
  27. *
  28.  * @brief Parallel STL function calls corresponding to stl_numeric.h.
  29.  * The functions defined here mainly do case switches and
  30.  * call the actual parallelized versions in other files.
  31.  * Inlining policy: Functions that basically only contain one function call,
  32.  * are declared inline.
  33.  *  This file is a GNU parallel extension to the Standard C++ Library.
  34.  */
  35.  
  36. // Written by Johannes Singler and Felix Putze.
  37.  
  38. #ifndef _GLIBCXX_PARALLEL_NUMERIC_H
  39. #define _GLIBCXX_PARALLEL_NUMERIC_H 1
  40.  
  41. #include <numeric>
  42. #include <bits/stl_function.h>
  43. #include <parallel/numericfwd.h>
  44. #include <parallel/iterator.h>
  45. #include <parallel/for_each.h>
  46. #include <parallel/for_each_selectors.h>
  47. #include <parallel/partial_sum.h>
  48.  
  49. namespace std _GLIBCXX_VISIBILITY(default)
  50. {
  51. namespace __parallel
  52. {
  53.   // Sequential fallback.
  54.   template<typename _IIter, typename _Tp>
  55.     inline _Tp
  56.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  57.                __gnu_parallel::sequential_tag)
  58.     { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init); }
  59.  
  60.   template<typename _IIter, typename _Tp, typename _BinaryOperation>
  61.     inline _Tp
  62.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  63.                _BinaryOperation __binary_op, __gnu_parallel::sequential_tag)
  64.     { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init, __binary_op); }
  65.  
  66.   // Sequential fallback for input iterator case.
  67.   template<typename _IIter, typename _Tp, typename _IteratorTag>
  68.     inline _Tp
  69.     __accumulate_switch(_IIter __begin, _IIter __end,
  70.                       _Tp __init, _IteratorTag)
  71.     { return accumulate(__begin, __end, __init,
  72.                         __gnu_parallel::sequential_tag()); }
  73.  
  74.   template<typename _IIter, typename _Tp, typename _BinaryOperation,
  75.            typename _IteratorTag>
  76.     inline _Tp
  77.     __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init,
  78.                       _BinaryOperation __binary_op, _IteratorTag)
  79.     { return accumulate(__begin, __end, __init, __binary_op,
  80.                         __gnu_parallel::sequential_tag()); }
  81.  
  82.   // Parallel algorithm for random access iterators.
  83.   template<typename __RAIter, typename _Tp, typename _BinaryOperation>
  84.     _Tp
  85.     __accumulate_switch(__RAIter __begin, __RAIter __end,
  86.                       _Tp __init, _BinaryOperation __binary_op,
  87.                       random_access_iterator_tag,
  88.                       __gnu_parallel::_Parallelism __parallelism_tag  
  89.                       = __gnu_parallel::parallel_unbalanced)
  90.     {
  91.       if (_GLIBCXX_PARALLEL_CONDITION(
  92.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  93.             >= __gnu_parallel::_Settings::get().accumulate_minimal_n
  94.             && __gnu_parallel::__is_parallel(__parallelism_tag)))
  95.         {
  96.           _Tp __res = __init;
  97.           __gnu_parallel::__accumulate_selector<__RAIter>
  98.             __my_selector;
  99.           __gnu_parallel::
  100.             __for_each_template_random_access_ed(__begin, __end,
  101.                                                  __gnu_parallel::_Nothing(),
  102.                                                  __my_selector,
  103.                                                  __gnu_parallel::
  104.                                                  __accumulate_binop_reduct
  105.                                                <_BinaryOperation>(__binary_op),
  106.                                                  __res, __res, -1);
  107.           return __res;
  108.         }
  109.       else
  110.         return accumulate(__begin, __end, __init, __binary_op,
  111.                           __gnu_parallel::sequential_tag());
  112.     }
  113.  
  114.   // Public interface.
  115.   template<typename _IIter, typename _Tp>
  116.     inline _Tp
  117.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  118.                __gnu_parallel::_Parallelism __parallelism_tag)
  119.     {
  120.       typedef std::iterator_traits<_IIter> _IteratorTraits;
  121.       typedef typename _IteratorTraits::value_type _ValueType;
  122.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  123.  
  124.       return __accumulate_switch(__begin, __end, __init,
  125.                                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
  126.                                  _IteratorCategory(), __parallelism_tag);
  127.     }
  128.  
  129.   template<typename _IIter, typename _Tp>
  130.     inline _Tp
  131.     accumulate(_IIter __begin, _IIter __end, _Tp __init)
  132.     {
  133.       typedef std::iterator_traits<_IIter> _IteratorTraits;
  134.       typedef typename _IteratorTraits::value_type _ValueType;
  135.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  136.  
  137.       return __accumulate_switch(__begin, __end, __init,
  138.                                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
  139.                                  _IteratorCategory());
  140.     }
  141.  
  142.   template<typename _IIter, typename _Tp, typename _BinaryOperation>
  143.     inline _Tp
  144.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  145.                _BinaryOperation __binary_op,
  146.                __gnu_parallel::_Parallelism __parallelism_tag)
  147.     {
  148.       typedef iterator_traits<_IIter> _IteratorTraits;
  149.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  150.       return __accumulate_switch(__begin, __end, __init, __binary_op,
  151.                                  _IteratorCategory(), __parallelism_tag);
  152.     }
  153.  
  154.   template<typename _IIter, typename _Tp, typename _BinaryOperation>
  155.     inline _Tp
  156.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  157.                _BinaryOperation __binary_op)
  158.     {
  159.       typedef iterator_traits<_IIter> _IteratorTraits;
  160.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  161.       return __accumulate_switch(__begin, __end, __init, __binary_op,
  162.                                  _IteratorCategory());
  163.     }
  164.  
  165.  
  166.   // Sequential fallback.
  167.   template<typename _IIter1, typename _IIter2, typename _Tp>
  168.     inline _Tp
  169.     inner_product(_IIter1 __first1, _IIter1 __last1,
  170.                   _IIter2 __first2, _Tp __init,
  171.                   __gnu_parallel::sequential_tag)
  172.     { return _GLIBCXX_STD_A::inner_product(
  173.                                __first1, __last1, __first2, __init); }
  174.  
  175.   template<typename _IIter1, typename _IIter2, typename _Tp,
  176.            typename _BinaryFunction1, typename _BinaryFunction2>
  177.     inline _Tp
  178.     inner_product(_IIter1 __first1, _IIter1 __last1,
  179.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  180.                   _BinaryFunction2 __binary_op2,
  181.                   __gnu_parallel::sequential_tag)
  182.     { return _GLIBCXX_STD_A::inner_product(__first1, __last1, __first2, __init,
  183.                                            __binary_op1, __binary_op2); }
  184.  
  185.   // Parallel algorithm for random access iterators.
  186.   template<typename _RAIter1, typename _RAIter2,
  187.            typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
  188.     _Tp
  189.     __inner_product_switch(_RAIter1 __first1,
  190.                            _RAIter1 __last1,
  191.                            _RAIter2 __first2, _Tp __init,
  192.                            _BinaryFunction1 __binary_op1,
  193.                            _BinaryFunction2 __binary_op2,
  194.                            random_access_iterator_tag,
  195.                            random_access_iterator_tag,
  196.                            __gnu_parallel::_Parallelism __parallelism_tag
  197.                            = __gnu_parallel::parallel_unbalanced)
  198.     {
  199.       if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
  200.                                       >= __gnu_parallel::_Settings::get().
  201.                                       accumulate_minimal_n
  202.                                       && __gnu_parallel::
  203.                                       __is_parallel(__parallelism_tag)))
  204.         {
  205.           _Tp __res = __init;
  206.           __gnu_parallel::
  207.             __inner_product_selector<_RAIter1,
  208.             _RAIter2, _Tp> __my_selector(__first1, __first2);
  209.           __gnu_parallel::
  210.             __for_each_template_random_access_ed(
  211.                 __first1, __last1, __binary_op2, __my_selector, __binary_op1,
  212.                 __res, __res, -1);
  213.           return __res;
  214.         }
  215.       else
  216.         return inner_product(__first1, __last1, __first2, __init,
  217.                              __gnu_parallel::sequential_tag());
  218.     }
  219.  
  220.   // No parallelism for input iterators.
  221.   template<typename _IIter1, typename _IIter2, typename _Tp,
  222.            typename _BinaryFunction1, typename _BinaryFunction2,
  223.            typename _IteratorTag1, typename _IteratorTag2>
  224.     inline _Tp
  225.     __inner_product_switch(_IIter1 __first1, _IIter1 __last1,
  226.                            _IIter2 __first2, _Tp __init,
  227.                            _BinaryFunction1 __binary_op1,
  228.                            _BinaryFunction2 __binary_op2,
  229.                            _IteratorTag1, _IteratorTag2)
  230.     { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
  231.                            __binary_op2, __gnu_parallel::sequential_tag()); }
  232.  
  233.   template<typename _IIter1, typename _IIter2, typename _Tp,
  234.            typename _BinaryFunction1, typename _BinaryFunction2>
  235.     inline _Tp
  236.     inner_product(_IIter1 __first1, _IIter1 __last1,
  237.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  238.                   _BinaryFunction2 __binary_op2,
  239.                   __gnu_parallel::_Parallelism __parallelism_tag)
  240.     {
  241.       typedef iterator_traits<_IIter1> _TraitsType1;
  242.       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  243.  
  244.       typedef iterator_traits<_IIter2> _TraitsType2;
  245.       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  246.  
  247.       return __inner_product_switch(__first1, __last1, __first2, __init,
  248.                                     __binary_op1, __binary_op2,
  249.                                     _IteratorCategory1(), _IteratorCategory2(),
  250.                                     __parallelism_tag);
  251.     }
  252.  
  253.   template<typename _IIter1, typename _IIter2, typename _Tp,
  254.            typename _BinaryFunction1, typename _BinaryFunction2>
  255.     inline _Tp
  256.     inner_product(_IIter1 __first1, _IIter1 __last1,
  257.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  258.                   _BinaryFunction2 __binary_op2)
  259.     {
  260.       typedef iterator_traits<_IIter1> _TraitsType1;
  261.       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  262.  
  263.       typedef iterator_traits<_IIter2> _TraitsType2;
  264.       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  265.  
  266.       return __inner_product_switch(__first1, __last1, __first2, __init,
  267.                                     __binary_op1, __binary_op2,
  268.                                     _IteratorCategory1(),
  269.                                     _IteratorCategory2());
  270.     }
  271.  
  272.   template<typename _IIter1, typename _IIter2, typename _Tp>
  273.     inline _Tp
  274.     inner_product(_IIter1 __first1, _IIter1 __last1,
  275.                   _IIter2 __first2, _Tp __init,
  276.                   __gnu_parallel::_Parallelism __parallelism_tag)
  277.     {
  278.       typedef iterator_traits<_IIter1> _TraitsType1;
  279.       typedef typename _TraitsType1::value_type _ValueType1;
  280.       typedef iterator_traits<_IIter2> _TraitsType2;
  281.       typedef typename _TraitsType2::value_type _ValueType2;
  282.  
  283.       typedef typename
  284.         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  285.         _MultipliesResultType;
  286.       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  287.                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  288.                            __gnu_parallel::
  289.                            _Multiplies<_ValueType1, _ValueType2>(),
  290.                            __parallelism_tag);
  291.     }
  292.  
  293.   template<typename _IIter1, typename _IIter2, typename _Tp>
  294.     inline _Tp
  295.     inner_product(_IIter1 __first1, _IIter1 __last1,
  296.                   _IIter2 __first2, _Tp __init)
  297.     {
  298.       typedef iterator_traits<_IIter1> _TraitsType1;
  299.       typedef typename _TraitsType1::value_type _ValueType1;
  300.       typedef iterator_traits<_IIter2> _TraitsType2;
  301.       typedef typename _TraitsType2::value_type _ValueType2;
  302.  
  303.       typedef typename
  304.         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  305.         _MultipliesResultType;
  306.       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  307.                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  308.                            __gnu_parallel::
  309.                            _Multiplies<_ValueType1, _ValueType2>());
  310.     }
  311.  
  312.   // Sequential fallback.
  313.   template<typename _IIter, typename _OutputIterator>
  314.     inline _OutputIterator
  315.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  316.                 __gnu_parallel::sequential_tag)
  317.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result); }
  318.  
  319.   // Sequential fallback.
  320.   template<typename _IIter, typename _OutputIterator,
  321.            typename _BinaryOperation>
  322.     inline _OutputIterator
  323.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  324.                 _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
  325.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  326.  
  327.   // Sequential fallback for input iterator case.
  328.   template<typename _IIter, typename _OutputIterator,
  329.            typename _BinaryOperation, typename _IteratorTag1,
  330.            typename _IteratorTag2>
  331.     inline _OutputIterator
  332.     __partial_sum_switch(_IIter __begin, _IIter __end,
  333.                          _OutputIterator __result, _BinaryOperation __bin_op,
  334.                          _IteratorTag1, _IteratorTag2)
  335.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  336.  
  337.   // Parallel algorithm for random access iterators.
  338.   template<typename _IIter, typename _OutputIterator,
  339.            typename _BinaryOperation>
  340.     _OutputIterator
  341.     __partial_sum_switch(_IIter __begin, _IIter __end,
  342.                          _OutputIterator __result, _BinaryOperation __bin_op,
  343.                          random_access_iterator_tag,
  344.                          random_access_iterator_tag)
  345.     {
  346.       if (_GLIBCXX_PARALLEL_CONDITION(
  347.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  348.             >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
  349.         return __gnu_parallel::__parallel_partial_sum(__begin, __end,
  350.                                                       __result, __bin_op);
  351.       else
  352.         return partial_sum(__begin, __end, __result, __bin_op,
  353.                            __gnu_parallel::sequential_tag());
  354.     }
  355.  
  356.   // Public interface.
  357.   template<typename _IIter, typename _OutputIterator>
  358.     inline _OutputIterator
  359.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
  360.     {
  361.       typedef typename iterator_traits<_IIter>::value_type _ValueType;
  362.       return __gnu_parallel::partial_sum(__begin, __end,
  363.                                          __result, std::plus<_ValueType>());
  364.     }
  365.  
  366.   // Public interface
  367.   template<typename _IIter, typename _OutputIterator,
  368.            typename _BinaryOperation>
  369.     inline _OutputIterator
  370.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  371.                 _BinaryOperation __binary_op)
  372.     {
  373.       typedef iterator_traits<_IIter> _ITraitsType;
  374.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  375.  
  376.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  377.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  378.  
  379.       return __partial_sum_switch(__begin, __end, __result, __binary_op,
  380.                                   _IIteratorCategory(), _OIterCategory());
  381.     }
  382.  
  383.   // Sequential fallback.
  384.   template<typename _IIter, typename _OutputIterator>
  385.     inline _OutputIterator
  386.     adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
  387.                         __gnu_parallel::sequential_tag)
  388.     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end, __result); }
  389.  
  390.   // Sequential fallback.
  391.   template<typename _IIter, typename _OutputIterator,
  392.            typename _BinaryOperation>
  393.     inline _OutputIterator
  394.     adjacent_difference(_IIter __begin, _IIter __end,
  395.                         _OutputIterator __result, _BinaryOperation __bin_op,
  396.                         __gnu_parallel::sequential_tag)
  397.     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end,
  398.                                                  __result, __bin_op); }
  399.  
  400.   // Sequential fallback for input iterator case.
  401.   template<typename _IIter, typename _OutputIterator,
  402.            typename _BinaryOperation, typename _IteratorTag1,
  403.            typename _IteratorTag2>
  404.     inline _OutputIterator
  405.     __adjacent_difference_switch(_IIter __begin, _IIter __end,
  406.                                  _OutputIterator __result,
  407.                                  _BinaryOperation __bin_op, _IteratorTag1,
  408.                                  _IteratorTag2)
  409.     { return adjacent_difference(__begin, __end, __result, __bin_op,
  410.                                  __gnu_parallel::sequential_tag()); }
  411.  
  412.   // Parallel algorithm for random access iterators.
  413.   template<typename _IIter, typename _OutputIterator,
  414.            typename _BinaryOperation>
  415.     _OutputIterator
  416.     __adjacent_difference_switch(_IIter __begin, _IIter __end,
  417.                                  _OutputIterator __result,
  418.                                  _BinaryOperation __bin_op,
  419.                                  random_access_iterator_tag,
  420.                                  random_access_iterator_tag,
  421.                                  __gnu_parallel::_Parallelism
  422.                                  __parallelism_tag
  423.                                  = __gnu_parallel::parallel_balanced)
  424.     {
  425.       if (_GLIBCXX_PARALLEL_CONDITION(
  426.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  427.             >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
  428.             && __gnu_parallel::__is_parallel(__parallelism_tag)))
  429.         {
  430.           bool __dummy = true;
  431.           typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
  432.             random_access_iterator_tag> _ItTrip;
  433.           *__result = *__begin;
  434.           _ItTrip __begin_pair(__begin + 1, __result + 1),
  435.             __end_pair(__end, __result + (__end - __begin));
  436.           __gnu_parallel::__adjacent_difference_selector<_ItTrip>
  437.                                                             __functionality;
  438.           __gnu_parallel::
  439.             __for_each_template_random_access_ed(
  440.                 __begin_pair, __end_pair, __bin_op, __functionality,
  441.                 __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
  442.           return __functionality._M_finish_iterator;
  443.         }
  444.       else
  445.         return adjacent_difference(__begin, __end, __result, __bin_op,
  446.                                    __gnu_parallel::sequential_tag());
  447.     }
  448.  
  449.   // Public interface.
  450.   template<typename _IIter, typename _OutputIterator>
  451.     inline _OutputIterator
  452.     adjacent_difference(_IIter __begin, _IIter __end,
  453.                         _OutputIterator __result,
  454.                         __gnu_parallel::_Parallelism __parallelism_tag)
  455.     {
  456.       typedef iterator_traits<_IIter> _TraitsType;
  457.       typedef typename _TraitsType::value_type _ValueType;
  458.       return adjacent_difference(__begin, __end, __result,
  459.                                  std::minus<_ValueType>(),
  460.                                  __parallelism_tag);
  461.     }
  462.  
  463.   template<typename _IIter, typename _OutputIterator>
  464.     inline _OutputIterator
  465.     adjacent_difference(_IIter __begin, _IIter __end,
  466.                         _OutputIterator __result)
  467.     {
  468.       typedef iterator_traits<_IIter> _TraitsType;
  469.       typedef typename _TraitsType::value_type _ValueType;
  470.       return adjacent_difference(__begin, __end, __result,
  471.                                  std::minus<_ValueType>());
  472.     }
  473.  
  474.   template<typename _IIter, typename _OutputIterator,
  475.            typename _BinaryOperation>
  476.     inline _OutputIterator
  477.     adjacent_difference(_IIter __begin, _IIter __end,
  478.                         _OutputIterator __result, _BinaryOperation __binary_op,
  479.                         __gnu_parallel::_Parallelism __parallelism_tag)
  480.     {
  481.       typedef iterator_traits<_IIter> _ITraitsType;
  482.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  483.  
  484.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  485.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  486.  
  487.       return __adjacent_difference_switch(__begin, __end, __result,
  488.                                           __binary_op,
  489.                                           _IIteratorCategory(),
  490.                                           _OIterCategory(),
  491.                                           __parallelism_tag);
  492.     }
  493.  
  494.   template<typename _IIter, typename _OutputIterator,
  495.            typename _BinaryOperation>
  496.     inline _OutputIterator
  497.     adjacent_difference(_IIter __begin, _IIter __end,
  498.                         _OutputIterator __result, _BinaryOperation __binary_op)
  499.     {
  500.       typedef iterator_traits<_IIter> _ITraitsType;
  501.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  502.  
  503.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  504.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  505.  
  506.       return __adjacent_difference_switch(__begin, __end, __result,
  507.                                           __binary_op,
  508.                                           _IIteratorCategory(),
  509.                                           _OIterCategory());
  510.     }
  511. } // end namespace
  512. } // end namespace
  513.  
  514. #endif /* _GLIBCXX_NUMERIC_H */
  515.