summaryrefslogtreecommitdiff
path: root/gcd.cpp
blob: 15fc4e99c3572eb8443ebd7656582a66740eb81f (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
77
78
79
80
81
82
/*
 * 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 int Number;
#endif

using namespace std;

typedef vector<Number> Numbers;

Number gcd(Number a, Number b) {
  Number c;
  while (b != 0) {
    c = b;
    b = a % b;
    a = c;
  }
  return a;
}

#if __cplusplus >= 201703L
class GCD {
public:
  Number operator()(Number a, Number b) const { return gcd(a, b); };
} GCD;

Number gcd(const Numbers &ns) {
  return reduce(execution::par, begin(ns), end(ns), Number(0), GCD);
}

#else

Number gcd(const Numbers &ns) {
  Number r = 0;
  for (Numbers::const_iterator n = ns.begin(); n != ns.end(); ++n)
    r = gcd(*n, r);
  return r;
}
#endif

int main(int argc, char *argv[]) {
  if (argc > 1) {
    Numbers ns(argc - 1);
    for (int n = 1; n < argc; ++n) {
      stringstream str;
      str << argv[n];
      str >> ns[n - 1];
      /* NOTE:
       * For GMP we can just assign: ns[n-1] = argv[n],
       * and sstream is not needed.
       */
    }
    cout << gcd(ns) << endl;
  }
  return EXIT_SUCCESS;
}