• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    function template
    <numeric>

    std::adjacent_difference

    namespace std {
      template <class InputIterator, class OutputIterator>
      OutputIterator
        adjacent_difference(InputIterator first,
                            InputIterator last,
                            OutputIterator result);     // (1) C++03
      template <class InputIterator, class OutputIterator>
      constexpr OutputIterator
        adjacent_difference(InputIterator first,
                            InputIterator last,
                            OutputIterator result);     // (1) C++20
    
      template <class InputIterator, class OutputIterator, class BinaryOperation>
      OutputIterator
        adjacent_difference(InputIterator first,
                            InputIterator last,
                            OutputIterator result,
                            BinaryOperation binary_op); // (2) C++03
      template <class InputIterator, class OutputIterator, class BinaryOperation>
      constexpr OutputIterator
        adjacent_difference(InputIterator first,
                            InputIterator last,
                            OutputIterator result,
                            BinaryOperation binary_op); // (2) C++20
    
      template <class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2>
      ForwardIterator2
        adjacent_difference(ExecutionPolicy&& exec,
                            ForwardIterator1 first,
                            ForwardIterator1 last,
                            ForwardIterator2 result);   // (3) C++17
    
      template <class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
                class BinaryOperation>
      ForwardIterator2
        adjacent_difference(ExecutionPolicy&& exec,
                            ForwardIterator1 first,
                            ForwardIterator1 last,
                            ForwardIterator2 result,
                            BinaryOperation binary_op); // (4) C++17
    }
    

    概要

    隣接する要素間の差を計算する。

    この関数に与えられたイテレータ範囲[first, last)rとして、その範囲の隣接する要素同士の差を、{r[0], r[1] - r[0], r[2] - r[1], r[3] - r[2], r[4] - r[3]}のように演算して求められた新たな範囲を返す。

    • (1), (3) : 各隣接要素aboperator-(b, a)で減算した結果を、result出力イテレータに書き込む
    • (2), (4) : 各隣接要素abbinary_op(b, a)で減算した結果を、result出力イテレータに書き込む

    要件

    • (2) :
      • C++03まで : 関数オブジェクトbinary_opの呼び出しは、副作用を起こしてはならない
      • C++11から : 関数オブジェクトbinary_opの呼び出しが、イテレータ範囲[first, last]およびイテレータ範囲[result, result + (last - first)]の要素変更、イテレータの無効化をしてはならない
    • (3), (4) :

    テンプレートパラメータ制約

    • (1) :
      • C++11から : InputIteratorが指す値の型が、ムーブ代入可能であり、*firstで初期化でき、result出力イテレータに書き込めること
      • C++11からC++17まで : InputIteratorが指す値の型のオブジェクトabにおいて、式b - aの結果がresult出力イテレータに書き込めること
      • C++20から : InputIteratorが指す値の型のオブジェクトabにおいて、式b - std::move(a)の結果がresult出力イテレータに書き込めること
    • (2)
      • C++11から : InputIteratorが指す値の型が、ムーブ代入可能であり、*firstで初期化でき、result出力イテレータに書き込めること
      • C++11からC++17まで : InputIteratorが指す値の型のオブジェクトabにおいて、式binary_op(b, a)の結果がresult出力イテレータに書き込めること
      • C++20から : InputIteratorが指す値の型のオブジェクトabにおいて、式binary_op(b, std::move(a))の結果がresult出力イテレータに書き込めること
    • (3) :
      • ForwardIterator1が指す値の型が、ムーブ代入可能であり、*firstで初期化でき、ForwardIterator2が指す値の型に対して代入できること
      • ForwardIterator1が指す値の型のオブジェクトabにおいて、式b - aの結果が、ForwardIterator2が指す値の型に対して代入できること
    • (4) :
      • ForwardIterator1が指す値の型が、ムーブ代入可能であり、*firstで初期化でき、ForwardIterator2が指す値の型に対して代入できること
      • ForwardIterator1が指す値の型のオブジェクトabにおいて、式binary_op(b, a)の結果が、ForwardIterator2が指す値の型に対して代入できること

    効果

    • (1), (2) : 非空のイテレータ範囲[first, last)について、
      1. *result = *firstで結果の初期値を書き込む。acc = *firstとしてひとつ前の位置の値を保持する
      2. イテレータ範囲[first + 1, last)の各イテレータをi、そのイテレータが指す値をvalとして定義する 3.
        • C++17 : (1)であればval - acc、(2)であればbinary_op(val, acc)で隣接値を求めて、その結果を*resultに代入する
        • C++20 : (1)であればval - std::move(acc)、(2)であればbinary_op(val, std::moved(acc))で隣接値を求めて、その結果を*resultに代入する
      3. valaccにムーブ代入し、ひとつ前の位置の値を更新する
    • (3), (4) : 非空のイテレータ範囲[first, last)について、
      1. *result = *firstで結果の初期値を代入する
      2. インデックス範囲[1, last - first - 1]のそれぞれの値dとして定義する
      3. (3)であればval = *(first + d) - *(first + d - 1)、(4)であればval = binary_op(*(first + d), *(first + d - 1))として、隣接値を求める
      4. *(result + d) = valで各隣接値を出力する

    戻り値

    result + (last - first)
    

    計算量

    ちょうど(last - first) - 1回の2項演算を適用する

    備考

    • (1), (2) : resultfirstと同値になるだろう

    #include <iostream>
    #include <numeric>
    #include <vector>
    
    template <class Range>
    void print(const Range& r)
    {
      for(const auto& x : r)
        std::cout << x << " --> ";
      std::cout << "end" << std::endl;
    }
    
    int main()
    {
      std::vector<double> v = {0.0, 0.2, 0.4, 0.6, 0.8};
      std::vector<double> diffs(v.size());
    
      // (1) : operator-()を使用して、隣接要素の差を計算する
      std::adjacent_difference(v.cbegin(), v.cend(), diffs.begin());
      print(diffs);
    
      // (2) : 最後の引数として与えた任意の2項演算関数によって、
      //       隣接要素の差を計算する
      std::adjacent_difference(v.cbegin(), v.cend(), diffs.begin(),
        [](double a, double b) {
          return a*a - b*b; // 2点間の距離の計算
        });
      print(diffs);
    }
    

    出力

    0 --> 0.2 --> 0.2 --> 0.2 --> 0.2 --> end
    0 --> 0.04 --> 0.12 --> 0.2 --> 0.28 --> end
    

    実装例

    #include <iterator>
    #include <functional>
    
    // (2)
    template <class InputIterator, class OutputIterator, class BinaryOperation>
    OutputIterator adjacent_difference(InputIterator first,
                                       InputIterator last,
                                       OutputIterator result,
                                       BinaryOperation binary_op)
    {
      if (first == last)
        return result;
    
      using value_type = typename std::iterator_traits<InputIterator>::value_type;
    
      value_type acc = *first;
      *result = acc;
      ++result;
      ++first;
    
      while (first != last) {
        value_type val = *first;
        *result = binary_op(val, std::move(acc));
        acc = std::move(val);
    
        ++result;
        ++first;
      }
      return result;
    }
    
    // (1)
    template <class InputIterator, class OutputIterator>
    OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result)
    {
      using value_type = typename std::iterator_traits<InputIterator>::value_type;
      return adjacent_difference(first, last, result, std::minus<value_type>());
    }
    

    参照