C++ STL 시리즈

5 / 5

C++ 17을 기준으로 cppreference를 참고하여 작성했습니다.

다양한 수학 함수와 타입들을 제공하는 라이브러리다. 이 라이브러리에는 <cmath>, <numbers>, <linalg>, <simd> 등 여러 개의 헤더로 나뉘어 있다. 그 중에서도 <numeric>은 수치 연산과 관련된 함수들을 제공한다.

iota

template< class ForwardIt, class T >
void iota( ForwardIt first, ForwardIt last, T value );

itoa가 아니다!

배열이나 컨테이너에 1씩 증가하는 값을 연속적으로 채울 때 쓰는 함수다.

함수 이름은 (그리스 문자 ⍳)에서 따온 듯하다.

예시

#include <iostream>
#include <vector>
#include <numeric>

int main() {
  std::vector<int> list(10);
  std::iota(list.begin(), list.end(), 10);
  for (auto it = list.begin(); it != list.end(); ++it)
  {
    std::cout << *it << ' ';
  }


  // 출력 결과
  // 10 11 12 13 14 15 16 17 18 19
}

accumulate

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );

배열이나 컨테이너를 순회하며 값에 대해 연산한다.

예시

#include <iostream>
#include <vector>
#include <numeric>

int main() {
  std::vector<int> list{1,2,3,4,5,6,7,8,9,10};
  std::cout << std::accumulate(list.begin(), list.end(), 0) << std::endl;
  std::cout << std::accumulate(list.begin(), list.end(), 1, [](const auto& a, const auto& b){return a*b;});

  // 출력 결과
  // 55
  // 3628800
}

reduce

template< class InputIt >
typename std::iterator_traits<InputIt>::value_type
    reduce( InputIt first, InputIt last );

template< class ExecutionPolicy, class ForwardIt >
typename std::iterator_traits<ForwardIt>::value_type
    reduce( ExecutionPolicy&& policy,
            ForwardIt first, ForwardIt last );

template< class ExecutionPolicy, class ForwardIt, class T >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init );

template< class InputIt, class T, class BinaryOp >
T reduce( InputIt first, InputIt last, T init, BinaryOp op );

template< class ExecutionPolicy,
          class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init, BinaryOp op );

accumulate와 매우 유사하지만, 시그니처에서 보이듯이 실행 정책을 결정할 수 있다. accumulate와 똑같이 무조건 순서를 지켜 실행하도록 하거나, 병렬적으로 실행하도록 결정할 수 있다.

예시

아래 코드는 accumulate와 동일한 작업을 병렬적으로 실행시킨 코드다.

#include <iostream>
#include <vector>
#include <numeric>
#include <execution>

int main()
{
    std::vector<int> list{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::cout << std::accumulate(
        list.begin(),
        list.end(),
        100,
        [](const auto& a, const auto& b) { return a - b; }) << std::endl;

    std::cout << std::reduce(
        std::execution::par, // 병렬적으로 실행
        list.begin(),
        list.end(),
        100,
        [](const auto& a, const auto& b) { return a - b; });

  // 출력 결과
  // 45
  // 81
}

inner_product

두 배열 또는 컨테이너에 대해 내적을 수행한다.

template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init );

template< class InputIt1, class InputIt2, class T,
          class BinaryOp1, class BinaryOp2 >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,
                 BinaryOp1 op1, BinaryOp2 op2 );
#include <iostream>
#include <vector>
#include <numeric>

int main()
{
    std::vector<int> v1{1, 3, 5}, v2{2, 4, 6};
    std::cout << std::inner_product(
        v1.begin(),
        v1.end(),
        v2.begin(),
        0);

    // 출력 결과
    // 44
}

adjacent_difference

template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2 >
ForwardIt2 adjacent_difference( ExecutionPolicy&& policy,
                                ForwardIt1 first, ForwardIt1 last,
                                ForwardIt2 d_first );

template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class BinaryOp >
ForwardIt2 adjacent_difference( ExecutionPolicy&& policy,
                                ForwardIt1 first, ForwardIt1 last,
                                ForwardIt2 d_first, BinaryOp op );

주어진 배열 또는 컨테이너의 원소들에 두 인접한 원소의 차를 대입한다.

예시

#include <iostream>
#include <vector>
#include <numeric>
int main()
{
    std::vector<int> list{ 4, 12, 54, 38, 75, 23, 55, 35, 91 };
    for (auto it = list.begin(); it != list.end(); ++it) { std::cout << *it << ' ';}
    std::cout << std::endl;
    std::adjacent_difference(
        list.begin(),
        list.end(),
        list.begin());
    for (auto it = list.begin(); it != list.end(); ++it) { std::cout << *it << ' ';}
    std::cout << std::endl;

    // 출력 결과
    // 4 12 54 38 75 23 55 35 91
    // 4 8 42 -16 37 -52 32 -20 56
}

partial_sum

template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first );

template< class InputIt, class OutputIt, class BinaryOp >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first, BinaryOp op );

주어진 배열 또는 컨테이너의 원소들에 시작 지점부터 해당 원소까지의 구간합을 대입한다.

#include <iostream>
#include <vector>
#include <numeric>
int main()
{
    std::vector<int> list{ 4, 12, 54, 38, 75, 23, 55, 35, 91 };
    for (auto it = list.begin(); it != list.end(); ++it) { std::cout << *it << ' ';}
    std::cout << std::endl;
    std::partial_sum(
        list.begin(),
        list.end(),
        list.begin());
    for (auto it = list.begin(); it != list.end(); ++it) { std::cout << *it << ' ';}
    std::cout << std::endl;

    // 출력 결과
    // 4 12 54 38 75 23 55 35 91 
    // 4 16 70 108 183 206 261 296 387 
}

gcd, lcm

template< class M, class N >
constexpr std::common_type_t<M, N> gcd( M m, N n );

template< class M, class N >
constexpr std::common_type_t<M, N> lcm( M m, N n );

최대공약수, 최소공배수를 구한다.

예시는 없어도 될 듯…