Subversion Repositories Kolibri OS

Rev

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

  1. // -*- C++ -*-
  2.  
  3. // Copyright (C) 2007-2015 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.     {
  90.       if (_GLIBCXX_PARALLEL_CONDITION(
  91.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  92.             >= __gnu_parallel::_Settings::get().accumulate_minimal_n
  93.             && __gnu_parallel::__is_parallel(__parallelism_tag)))
  94.         {
  95.           _Tp __res = __init;
  96.           __gnu_parallel::__accumulate_selector<__RAIter>
  97.             __my_selector;
  98.           __gnu_parallel::
  99.             __for_each_template_random_access_ed(__begin, __end,
  100.                                                  __gnu_parallel::_Nothing(),
  101.                                                  __my_selector,
  102.                                                  __gnu_parallel::
  103.                                                  __accumulate_binop_reduct
  104.                                                <_BinaryOperation>(__binary_op),
  105.                                                  __res, __res, -1);
  106.           return __res;
  107.         }
  108.       else
  109.         return accumulate(__begin, __end, __init, __binary_op,
  110.                           __gnu_parallel::sequential_tag());
  111.     }
  112.  
  113.   // Public interface.
  114.   template<typename _IIter, typename _Tp>
  115.     inline _Tp
  116.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  117.                __gnu_parallel::_Parallelism __parallelism_tag)
  118.     {
  119.       typedef std::iterator_traits<_IIter> _IteratorTraits;
  120.       typedef typename _IteratorTraits::value_type _ValueType;
  121.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  122.  
  123.       return __accumulate_switch(__begin, __end, __init,
  124.                                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
  125.                                  _IteratorCategory(), __parallelism_tag);
  126.     }
  127.  
  128.   template<typename _IIter, typename _Tp>
  129.     inline _Tp
  130.     accumulate(_IIter __begin, _IIter __end, _Tp __init)
  131.     {
  132.       typedef std::iterator_traits<_IIter> _IteratorTraits;
  133.       typedef typename _IteratorTraits::value_type _ValueType;
  134.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  135.  
  136.       return __accumulate_switch(__begin, __end, __init,
  137.                                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
  138.                                  _IteratorCategory());
  139.     }
  140.  
  141.   template<typename _IIter, typename _Tp, typename _BinaryOperation>
  142.     inline _Tp
  143.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  144.                _BinaryOperation __binary_op,
  145.                __gnu_parallel::_Parallelism __parallelism_tag)
  146.     {
  147.       typedef iterator_traits<_IIter> _IteratorTraits;
  148.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  149.       return __accumulate_switch(__begin, __end, __init, __binary_op,
  150.                                  _IteratorCategory(), __parallelism_tag);
  151.     }
  152.  
  153.   template<typename _IIter, typename _Tp, typename _BinaryOperation>
  154.     inline _Tp
  155.     accumulate(_IIter __begin, _IIter __end, _Tp __init,
  156.                _BinaryOperation __binary_op)
  157.     {
  158.       typedef iterator_traits<_IIter> _IteratorTraits;
  159.       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  160.       return __accumulate_switch(__begin, __end, __init, __binary_op,
  161.                                  _IteratorCategory());
  162.     }
  163.  
  164.  
  165.   // Sequential fallback.
  166.   template<typename _IIter1, typename _IIter2, typename _Tp>
  167.     inline _Tp
  168.     inner_product(_IIter1 __first1, _IIter1 __last1,
  169.                   _IIter2 __first2, _Tp __init,
  170.                   __gnu_parallel::sequential_tag)
  171.     { return _GLIBCXX_STD_A::inner_product(
  172.                                __first1, __last1, __first2, __init); }
  173.  
  174.   template<typename _IIter1, typename _IIter2, typename _Tp,
  175.            typename _BinaryFunction1, typename _BinaryFunction2>
  176.     inline _Tp
  177.     inner_product(_IIter1 __first1, _IIter1 __last1,
  178.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  179.                   _BinaryFunction2 __binary_op2,
  180.                   __gnu_parallel::sequential_tag)
  181.     { return _GLIBCXX_STD_A::inner_product(__first1, __last1, __first2, __init,
  182.                                            __binary_op1, __binary_op2); }
  183.  
  184.   // Parallel algorithm for random access iterators.
  185.   template<typename _RAIter1, typename _RAIter2,
  186.            typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
  187.     _Tp
  188.     __inner_product_switch(_RAIter1 __first1,
  189.                            _RAIter1 __last1,
  190.                            _RAIter2 __first2, _Tp __init,
  191.                            _BinaryFunction1 __binary_op1,
  192.                            _BinaryFunction2 __binary_op2,
  193.                            random_access_iterator_tag,
  194.                            random_access_iterator_tag,
  195.                            __gnu_parallel::_Parallelism __parallelism_tag)
  196.     {
  197.       if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
  198.                                       >= __gnu_parallel::_Settings::get().
  199.                                       accumulate_minimal_n
  200.                                       && __gnu_parallel::
  201.                                       __is_parallel(__parallelism_tag)))
  202.         {
  203.           _Tp __res = __init;
  204.           __gnu_parallel::
  205.             __inner_product_selector<_RAIter1,
  206.             _RAIter2, _Tp> __my_selector(__first1, __first2);
  207.           __gnu_parallel::
  208.             __for_each_template_random_access_ed(
  209.                 __first1, __last1, __binary_op2, __my_selector, __binary_op1,
  210.                 __res, __res, -1);
  211.           return __res;
  212.         }
  213.       else
  214.         return inner_product(__first1, __last1, __first2, __init,
  215.                              __gnu_parallel::sequential_tag());
  216.     }
  217.  
  218.   // No parallelism for input iterators.
  219.   template<typename _IIter1, typename _IIter2, typename _Tp,
  220.            typename _BinaryFunction1, typename _BinaryFunction2,
  221.            typename _IteratorTag1, typename _IteratorTag2>
  222.     inline _Tp
  223.     __inner_product_switch(_IIter1 __first1, _IIter1 __last1,
  224.                            _IIter2 __first2, _Tp __init,
  225.                            _BinaryFunction1 __binary_op1,
  226.                            _BinaryFunction2 __binary_op2,
  227.                            _IteratorTag1, _IteratorTag2)
  228.     { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
  229.                            __binary_op2, __gnu_parallel::sequential_tag()); }
  230.  
  231.   template<typename _IIter1, typename _IIter2, typename _Tp,
  232.            typename _BinaryFunction1, typename _BinaryFunction2>
  233.     inline _Tp
  234.     inner_product(_IIter1 __first1, _IIter1 __last1,
  235.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  236.                   _BinaryFunction2 __binary_op2,
  237.                   __gnu_parallel::_Parallelism __parallelism_tag)
  238.     {
  239.       typedef iterator_traits<_IIter1> _TraitsType1;
  240.       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  241.  
  242.       typedef iterator_traits<_IIter2> _TraitsType2;
  243.       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  244.  
  245.       return __inner_product_switch(__first1, __last1, __first2, __init,
  246.                                     __binary_op1, __binary_op2,
  247.                                     _IteratorCategory1(), _IteratorCategory2(),
  248.                                     __parallelism_tag);
  249.     }
  250.  
  251.   template<typename _IIter1, typename _IIter2, typename _Tp,
  252.            typename _BinaryFunction1, typename _BinaryFunction2>
  253.     inline _Tp
  254.     inner_product(_IIter1 __first1, _IIter1 __last1,
  255.                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  256.                   _BinaryFunction2 __binary_op2)
  257.     {
  258.       typedef iterator_traits<_IIter1> _TraitsType1;
  259.       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  260.  
  261.       typedef iterator_traits<_IIter2> _TraitsType2;
  262.       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  263.  
  264.       return __inner_product_switch(__first1, __last1, __first2, __init,
  265.                                     __binary_op1, __binary_op2,
  266.                                     _IteratorCategory1(),
  267.                                     _IteratorCategory2());
  268.     }
  269.  
  270.   template<typename _IIter1, typename _IIter2, typename _Tp>
  271.     inline _Tp
  272.     inner_product(_IIter1 __first1, _IIter1 __last1,
  273.                   _IIter2 __first2, _Tp __init,
  274.                   __gnu_parallel::_Parallelism __parallelism_tag)
  275.     {
  276.       typedef iterator_traits<_IIter1> _TraitsType1;
  277.       typedef typename _TraitsType1::value_type _ValueType1;
  278.       typedef iterator_traits<_IIter2> _TraitsType2;
  279.       typedef typename _TraitsType2::value_type _ValueType2;
  280.  
  281.       typedef typename
  282.         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  283.         _MultipliesResultType;
  284.       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  285.                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  286.                            __gnu_parallel::
  287.                            _Multiplies<_ValueType1, _ValueType2>(),
  288.                            __parallelism_tag);
  289.     }
  290.  
  291.   template<typename _IIter1, typename _IIter2, typename _Tp>
  292.     inline _Tp
  293.     inner_product(_IIter1 __first1, _IIter1 __last1,
  294.                   _IIter2 __first2, _Tp __init)
  295.     {
  296.       typedef iterator_traits<_IIter1> _TraitsType1;
  297.       typedef typename _TraitsType1::value_type _ValueType1;
  298.       typedef iterator_traits<_IIter2> _TraitsType2;
  299.       typedef typename _TraitsType2::value_type _ValueType2;
  300.  
  301.       typedef typename
  302.         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  303.         _MultipliesResultType;
  304.       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  305.                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  306.                            __gnu_parallel::
  307.                            _Multiplies<_ValueType1, _ValueType2>());
  308.     }
  309.  
  310.   // Sequential fallback.
  311.   template<typename _IIter, typename _OutputIterator>
  312.     inline _OutputIterator
  313.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  314.                 __gnu_parallel::sequential_tag)
  315.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result); }
  316.  
  317.   // Sequential fallback.
  318.   template<typename _IIter, typename _OutputIterator,
  319.            typename _BinaryOperation>
  320.     inline _OutputIterator
  321.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  322.                 _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
  323.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  324.  
  325.   // Sequential fallback for input iterator case.
  326.   template<typename _IIter, typename _OutputIterator,
  327.            typename _BinaryOperation, typename _IteratorTag1,
  328.            typename _IteratorTag2>
  329.     inline _OutputIterator
  330.     __partial_sum_switch(_IIter __begin, _IIter __end,
  331.                          _OutputIterator __result, _BinaryOperation __bin_op,
  332.                          _IteratorTag1, _IteratorTag2)
  333.     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  334.  
  335.   // Parallel algorithm for random access iterators.
  336.   template<typename _IIter, typename _OutputIterator,
  337.            typename _BinaryOperation>
  338.     _OutputIterator
  339.     __partial_sum_switch(_IIter __begin, _IIter __end,
  340.                          _OutputIterator __result, _BinaryOperation __bin_op,
  341.                          random_access_iterator_tag,
  342.                          random_access_iterator_tag)
  343.     {
  344.       if (_GLIBCXX_PARALLEL_CONDITION(
  345.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  346.             >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
  347.         return __gnu_parallel::__parallel_partial_sum(__begin, __end,
  348.                                                       __result, __bin_op);
  349.       else
  350.         return partial_sum(__begin, __end, __result, __bin_op,
  351.                            __gnu_parallel::sequential_tag());
  352.     }
  353.  
  354.   // Public interface.
  355.   template<typename _IIter, typename _OutputIterator>
  356.     inline _OutputIterator
  357.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
  358.     {
  359.       typedef typename iterator_traits<_IIter>::value_type _ValueType;
  360.       return __gnu_parallel::partial_sum(__begin, __end,
  361.                                          __result, std::plus<_ValueType>());
  362.     }
  363.  
  364.   // Public interface
  365.   template<typename _IIter, typename _OutputIterator,
  366.            typename _BinaryOperation>
  367.     inline _OutputIterator
  368.     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  369.                 _BinaryOperation __binary_op)
  370.     {
  371.       typedef iterator_traits<_IIter> _ITraitsType;
  372.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  373.  
  374.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  375.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  376.  
  377.       return __partial_sum_switch(__begin, __end, __result, __binary_op,
  378.                                   _IIteratorCategory(), _OIterCategory());
  379.     }
  380.  
  381.   // Sequential fallback.
  382.   template<typename _IIter, typename _OutputIterator>
  383.     inline _OutputIterator
  384.     adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
  385.                         __gnu_parallel::sequential_tag)
  386.     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end, __result); }
  387.  
  388.   // Sequential fallback.
  389.   template<typename _IIter, typename _OutputIterator,
  390.            typename _BinaryOperation>
  391.     inline _OutputIterator
  392.     adjacent_difference(_IIter __begin, _IIter __end,
  393.                         _OutputIterator __result, _BinaryOperation __bin_op,
  394.                         __gnu_parallel::sequential_tag)
  395.     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end,
  396.                                                  __result, __bin_op); }
  397.  
  398.   // Sequential fallback for input iterator case.
  399.   template<typename _IIter, typename _OutputIterator,
  400.            typename _BinaryOperation, typename _IteratorTag1,
  401.            typename _IteratorTag2>
  402.     inline _OutputIterator
  403.     __adjacent_difference_switch(_IIter __begin, _IIter __end,
  404.                                  _OutputIterator __result,
  405.                                  _BinaryOperation __bin_op, _IteratorTag1,
  406.                                  _IteratorTag2)
  407.     { return adjacent_difference(__begin, __end, __result, __bin_op,
  408.                                  __gnu_parallel::sequential_tag()); }
  409.  
  410.   // Parallel algorithm for random access iterators.
  411.   template<typename _IIter, typename _OutputIterator,
  412.            typename _BinaryOperation>
  413.     _OutputIterator
  414.     __adjacent_difference_switch(_IIter __begin, _IIter __end,
  415.                                  _OutputIterator __result,
  416.                                  _BinaryOperation __bin_op,
  417.                                  random_access_iterator_tag,
  418.                                  random_access_iterator_tag,
  419.                                  __gnu_parallel::_Parallelism
  420.                                  __parallelism_tag)
  421.     {
  422.       if (_GLIBCXX_PARALLEL_CONDITION(
  423.             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  424.             >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
  425.             && __gnu_parallel::__is_parallel(__parallelism_tag)))
  426.         {
  427.           bool __dummy = true;
  428.           typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
  429.             random_access_iterator_tag> _ItTrip;
  430.           *__result = *__begin;
  431.           _ItTrip __begin_pair(__begin + 1, __result + 1),
  432.             __end_pair(__end, __result + (__end - __begin));
  433.           __gnu_parallel::__adjacent_difference_selector<_ItTrip>
  434.                                                             __functionality;
  435.           __gnu_parallel::
  436.             __for_each_template_random_access_ed(
  437.                 __begin_pair, __end_pair, __bin_op, __functionality,
  438.                 __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
  439.           return __functionality._M_finish_iterator;
  440.         }
  441.       else
  442.         return adjacent_difference(__begin, __end, __result, __bin_op,
  443.                                    __gnu_parallel::sequential_tag());
  444.     }
  445.  
  446.   // Public interface.
  447.   template<typename _IIter, typename _OutputIterator>
  448.     inline _OutputIterator
  449.     adjacent_difference(_IIter __begin, _IIter __end,
  450.                         _OutputIterator __result,
  451.                         __gnu_parallel::_Parallelism __parallelism_tag)
  452.     {
  453.       typedef iterator_traits<_IIter> _TraitsType;
  454.       typedef typename _TraitsType::value_type _ValueType;
  455.       return adjacent_difference(__begin, __end, __result,
  456.                                  std::minus<_ValueType>(),
  457.                                  __parallelism_tag);
  458.     }
  459.  
  460.   template<typename _IIter, typename _OutputIterator>
  461.     inline _OutputIterator
  462.     adjacent_difference(_IIter __begin, _IIter __end,
  463.                         _OutputIterator __result)
  464.     {
  465.       typedef iterator_traits<_IIter> _TraitsType;
  466.       typedef typename _TraitsType::value_type _ValueType;
  467.       return adjacent_difference(__begin, __end, __result,
  468.                                  std::minus<_ValueType>());
  469.     }
  470.  
  471.   template<typename _IIter, typename _OutputIterator,
  472.            typename _BinaryOperation>
  473.     inline _OutputIterator
  474.     adjacent_difference(_IIter __begin, _IIter __end,
  475.                         _OutputIterator __result, _BinaryOperation __binary_op,
  476.                         __gnu_parallel::_Parallelism __parallelism_tag)
  477.     {
  478.       typedef iterator_traits<_IIter> _ITraitsType;
  479.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  480.  
  481.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  482.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  483.  
  484.       return __adjacent_difference_switch(__begin, __end, __result,
  485.                                           __binary_op,
  486.                                           _IIteratorCategory(),
  487.                                           _OIterCategory(),
  488.                                           __parallelism_tag);
  489.     }
  490.  
  491.   template<typename _IIter, typename _OutputIterator,
  492.            typename _BinaryOperation>
  493.     inline _OutputIterator
  494.     adjacent_difference(_IIter __begin, _IIter __end,
  495.                         _OutputIterator __result, _BinaryOperation __binary_op)
  496.     {
  497.       typedef iterator_traits<_IIter> _ITraitsType;
  498.       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  499.  
  500.       typedef iterator_traits<_OutputIterator> _OTraitsType;
  501.       typedef typename _OTraitsType::iterator_category _OIterCategory;
  502.  
  503.       return __adjacent_difference_switch(__begin, __end, __result,
  504.                                           __binary_op,
  505.                                           _IIteratorCategory(),
  506.                                           _OIterCategory());
  507.     }
  508. } // end namespace
  509. } // end namespace
  510.  
  511. #endif /* _GLIBCXX_NUMERIC_H */
  512.