summaryrefslogtreecommitdiff
path: root/gcd.cpp
blob: e1d363a57c9ebabb26a02eb7c96967d95590b39f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * SYNOPSIS:
 *
 * # g++ -o gcd-cpp gcd.cpp
 * # ./gcd-cpp 11 22 33 121
 * # 11
 *
 *
 * To use GNU Multiple Precision Arithmetic Library:
 *
 * # g++ -DGMP gcd.cpp -lgmpxx -lgmp -o gcd-cpp-gmp
 * # ./gcd-cpp-gmp 1234567890987654321 987654321234567
 * # 63
 *
 */

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <vector>
#if __cplusplus >= 201703L
#include <execution>
#include <numeric>
#endif

#ifdef GMP
#include <gmpxx.h>
typedef mpz_class Number;
#else
typedef unsigned long Number;
#endif

using std::vector;

template <class N> N gcd2(N a, N b) {
  while (b != 0) {
    N c = b;
    b = a % b;
    a = c;
  }
  return a;
}

#if __cplusplus >= 201703L
template <class N> class GCD {
public:
  N operator()(N a, N b) const { return gcd2(a, b); };
};

template <class N> N gcd(const vector<N> &ns) {
  GCD<N> GCD;
  return reduce(std::execution::par, begin(ns), end(ns), N(0), GCD);
}

#else

template <class N> N gcd(const vector<N> &ns) {
  N r = 0;
  for (typename vector<N>::const_iterator n = ns.begin(); n != ns.end(); ++n)
    r = gcd2(*n, r);
  return r;
}
#endif

int main(int argc, char *argv[]) {
  if (argc > 1) {
    vector<Number> ns(argc - 1);
    for (int n = 1; n < argc; ++n) {
      std::stringstream str;
      str << argv[n];
      str >> ns[n - 1];
    }
    std::cout << gcd(ns) << std::endl;
  }
  return EXIT_SUCCESS;
}