#include #include #include #include #include using namespace std; const double a = 0; const double b = 1; double f(double x) { return 4 / (1 + x*x); } // numerical integration according to the Simpson rule // for f over the interval [a,b] using n subintervals double simpson(double (*f)(double), double a, double b, int n) { assert(n > 0 && a <= b); double value = f(a)/2 + f(b)/2; double xleft; double x = a; for (int i = 1; i < n; ++i) { xleft = x; x = a + i * (b - a) / n; value += f(x) + 2 * f((xleft + x)/2); } value += 2 * f((x + b)/2); value *= (b - a) / n / 3; return value; } char* cmdname; void usage() { cerr << "Usage: " << cmdname << " [# intervals] " << endl; MPI_Abort(MPI_COMM_WORLD, 1); } int main(int argc, char** argv) { MPI_Init(&argc, &argv); int nofprocesses; MPI_Comm_size(MPI_COMM_WORLD, &nofprocesses); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); // process command line arguments int n; // number of intervals if (rank == 0) { cmdname = argv[0]; if (argc > 2) usage(); if (argc == 1) { n = nofprocesses; } else { istringstream arg(argv[1]); if (!(arg >> n) || n <= 0) usage(); } } // broadcast number of intervals MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); double value = 0; // summed up value of our intervals; if (rank < n) { int nofintervals = n / nofprocesses; int remainder = n % nofprocesses; int first_interval = rank * nofintervals; if (rank < remainder) { ++nofintervals; if (rank > 0) first_interval += rank; } else { first_interval += remainder; } int next_interval = first_interval + nofintervals; double xleft = a + first_interval * (b - a) / n; double x = a + next_interval * (b - a) / n; value = simpson(f, xleft, x, nofintervals); } double sum; MPI_Reduce(&value, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Finalize(); if (rank == 0) { cout << setprecision(14) << sum << endl; } }