#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Function to print an array along with the process rank
void printArray(double *array, int size, int rank) {
printf("Process %d array: ", rank
); for (int i = 0; i < size; i++) {
}
}
// Function to calculate the local average of an array
double calculateLocalAverage(double *array, int size) {
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += array[i];
}
return sum / size;
}
int main(int argc, char *argv[]) {
// Initialize MPI and variables
MPI_Init(&argc, &argv);
int rank, size, N;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Read and validate command-line argument
if (argc
!= 2 || (N
= atoi(argv
[1])) <= 1) { if (rank
== 0) fprintf(stderr
, "Usage: %s N (N > 1)\n", argv
[0]); MPI_Finalize();
return 1;
}
// Seed random number generator differently for each process
// Allocate and initialize the array with random values
double *array
= (double *)malloc(N
* sizeof(double)); for (int i = 0; i < N; i++) {
array
[i
] = (double)(rand() % 100) / 10.0; }
// Initial array print by master process in process order
if (rank == 0) {
}
MPI_Barrier(MPI_COMM_WORLD); // Sync for orderly printing
printArray(array, N, rank);
MPI_Barrier(MPI_COMM_WORLD);
// Calculate global average
double local_sum = 0.0, global_sum = 0.0;
for (int i = 0; i < N; i++) {
local_sum += array[i];
}
MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
double global_average = global_sum / (N * size);
// Randomly select an "odd-ball" process (other than process 0)
int odd_ball = -1;
if (rank == 0) {
odd_ball
= (rand() % (size
- 1)) + 1; // Random process excluding 0 printf("Odd-ball process selected: %d\n", odd_ball
); }
MPI_Bcast(&odd_ball, 1, MPI_INT, 0, MPI_COMM_WORLD);
// Adjust array elements based on the global average
for (int i = 0; i < N; i++) {
if (rank == odd_ball) {
array[i] += global_average; // Odd-ball adds
} else {
array[i] -= global_average; // Others subtract
}
}
// Each process finds its maximum value
double local_max = array[0];
for (int i = 1; i < N; i++) {
if (array[i] > local_max) local_max = array[i];
}
// Gather all max values from processes
double *max_values
= (double *)malloc(size
* sizeof(double)); MPI_Allgather(&local_max, 1, MPI_DOUBLE, max_values, 1, MPI_DOUBLE, MPI_COMM_WORLD);
// Add neighbor’s max value, or subtract if the process is the odd-ball
double neighbor_max = (rank == size - 1) ? max_values[0] : max_values[rank + 1];
for (int i = 0; i < N; i++) {
if (rank == odd_ball) {
array[i] -= neighbor_max; // Odd-ball subtracts
} else {
array[i] += neighbor_max; // Others add
}
}
// Odd-Even Transposition Sort using MPI
int sorted = 0;
while (!sorted) {
sorted = 1;
for (int phase = 0; phase < size; phase++) {
int partner = (phase % 2 == rank % 2) ? rank + 1 : rank - 1;
if (partner >= 0 && partner < size) {
double *temp_array
= (double *)malloc(N
* sizeof(double)); MPI_Sendrecv(array, N, MPI_DOUBLE, partner, 0, temp_array, N, MPI_DOUBLE, partner, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
// Local sorting logic here between received and local array for transposition
}
}
}
// Print final sorted arrays
if (rank == 0) {
printf("Final Sorted Arrays:\n"); }
MPI_Barrier(MPI_COMM_WORLD); // Sync for orderly printing
printArray(array, N, rank);
MPI_Barrier(MPI_COMM_WORLD);
// Clean up
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPG1waS5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8dGltZS5oPgoKLy8gRnVuY3Rpb24gdG8gcHJpbnQgYW4gYXJyYXkgYWxvbmcgd2l0aCB0aGUgcHJvY2VzcyByYW5rCnZvaWQgcHJpbnRBcnJheShkb3VibGUgKmFycmF5LCBpbnQgc2l6ZSwgaW50IHJhbmspIHsKICAgIHByaW50ZigiUHJvY2VzcyAlZCBhcnJheTogIiwgcmFuayk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgIHByaW50ZigiJS4yZiAiLCBhcnJheVtpXSk7CiAgICB9CiAgICBwcmludGYoIlxuIik7Cn0KCi8vIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgbG9jYWwgYXZlcmFnZSBvZiBhbiBhcnJheQpkb3VibGUgY2FsY3VsYXRlTG9jYWxBdmVyYWdlKGRvdWJsZSAqYXJyYXksIGludCBzaXplKSB7CiAgICBkb3VibGUgc3VtID0gMC4wOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKICAgICAgICBzdW0gKz0gYXJyYXlbaV07CiAgICB9CiAgICByZXR1cm4gc3VtIC8gc2l6ZTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkgewogICAgLy8gSW5pdGlhbGl6ZSBNUEkgYW5kIHZhcmlhYmxlcwogICAgTVBJX0luaXQoJmFyZ2MsICZhcmd2KTsKCiAgICBpbnQgcmFuaywgc2l6ZSwgTjsKICAgIE1QSV9Db21tX3JhbmsoTVBJX0NPTU1fV09STEQsICZyYW5rKTsKICAgIE1QSV9Db21tX3NpemUoTVBJX0NPTU1fV09STEQsICZzaXplKTsKCiAgICAvLyBSZWFkIGFuZCB2YWxpZGF0ZSBjb21tYW5kLWxpbmUgYXJndW1lbnQKICAgIGlmIChhcmdjICE9IDIgfHwgKE4gPSBhdG9pKGFyZ3ZbMV0pKSA8PSAxKSB7CiAgICAgICAgaWYgKHJhbmsgPT0gMCkgZnByaW50ZihzdGRlcnIsICJVc2FnZTogJXMgTiAoTiA+IDEpXG4iLCBhcmd2WzBdKTsKICAgICAgICBNUElfRmluYWxpemUoKTsKICAgICAgICByZXR1cm4gMTsKICAgIH0KCiAgICAvLyBTZWVkIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIGRpZmZlcmVudGx5IGZvciBlYWNoIHByb2Nlc3MKICAgIHNyYW5kKHRpbWUoTlVMTCkgKyByYW5rKTsKCiAgICAvLyBBbGxvY2F0ZSBhbmQgaW5pdGlhbGl6ZSB0aGUgYXJyYXkgd2l0aCByYW5kb20gdmFsdWVzCiAgICBkb3VibGUgKmFycmF5ID0gKGRvdWJsZSAqKW1hbGxvYyhOICogc2l6ZW9mKGRvdWJsZSkpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICBhcnJheVtpXSA9IChkb3VibGUpKHJhbmQoKSAlIDEwMCkgLyAxMC4wOwogICAgfQoKICAgIC8vIEluaXRpYWwgYXJyYXkgcHJpbnQgYnkgbWFzdGVyIHByb2Nlc3MgaW4gcHJvY2VzcyBvcmRlcgogICAgaWYgKHJhbmsgPT0gMCkgewogICAgICAgIHByaW50ZigiSW5pdGlhbCBBcnJheXM6XG4iKTsKICAgIH0KICAgIE1QSV9CYXJyaWVyKE1QSV9DT01NX1dPUkxEKTsgIC8vIFN5bmMgZm9yIG9yZGVybHkgcHJpbnRpbmcKICAgIHByaW50QXJyYXkoYXJyYXksIE4sIHJhbmspOwogICAgTVBJX0JhcnJpZXIoTVBJX0NPTU1fV09STEQpOwoKICAgIC8vIENhbGN1bGF0ZSBnbG9iYWwgYXZlcmFnZQogICAgZG91YmxlIGxvY2FsX3N1bSA9IDAuMCwgZ2xvYmFsX3N1bSA9IDAuMDsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgbG9jYWxfc3VtICs9IGFycmF5W2ldOwogICAgfQogICAgTVBJX0FsbHJlZHVjZSgmbG9jYWxfc3VtLCAmZ2xvYmFsX3N1bSwgMSwgTVBJX0RPVUJMRSwgTVBJX1NVTSwgTVBJX0NPTU1fV09STEQpOwogICAgZG91YmxlIGdsb2JhbF9hdmVyYWdlID0gZ2xvYmFsX3N1bSAvIChOICogc2l6ZSk7CgogICAgLy8gUmFuZG9tbHkgc2VsZWN0IGFuICJvZGQtYmFsbCIgcHJvY2VzcyAob3RoZXIgdGhhbiBwcm9jZXNzIDApCiAgICBpbnQgb2RkX2JhbGwgPSAtMTsKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBvZGRfYmFsbCA9IChyYW5kKCkgJSAoc2l6ZSAtIDEpKSArIDE7ICAvLyBSYW5kb20gcHJvY2VzcyBleGNsdWRpbmcgMAogICAgICAgIHByaW50ZigiT2RkLWJhbGwgcHJvY2VzcyBzZWxlY3RlZDogJWRcbiIsIG9kZF9iYWxsKTsKICAgIH0KICAgIE1QSV9CY2FzdCgmb2RkX2JhbGwsIDEsIE1QSV9JTlQsIDAsIE1QSV9DT01NX1dPUkxEKTsKCiAgICAvLyBBZGp1c3QgYXJyYXkgZWxlbWVudHMgYmFzZWQgb24gdGhlIGdsb2JhbCBhdmVyYWdlCiAgICBmb3IgKGludCBpID0gMDsgaSA8IE47IGkrKykgewogICAgICAgIGlmIChyYW5rID09IG9kZF9iYWxsKSB7CiAgICAgICAgICAgIGFycmF5W2ldICs9IGdsb2JhbF9hdmVyYWdlOyAgLy8gT2RkLWJhbGwgYWRkcwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGFycmF5W2ldIC09IGdsb2JhbF9hdmVyYWdlOyAgLy8gT3RoZXJzIHN1YnRyYWN0CiAgICAgICAgfQogICAgfQoKICAgIC8vIEVhY2ggcHJvY2VzcyBmaW5kcyBpdHMgbWF4aW11bSB2YWx1ZQogICAgZG91YmxlIGxvY2FsX21heCA9IGFycmF5WzBdOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPCBOOyBpKyspIHsKICAgICAgICBpZiAoYXJyYXlbaV0gPiBsb2NhbF9tYXgpIGxvY2FsX21heCA9IGFycmF5W2ldOwogICAgfQoKICAgIC8vIEdhdGhlciBhbGwgbWF4IHZhbHVlcyBmcm9tIHByb2Nlc3NlcwogICAgZG91YmxlICptYXhfdmFsdWVzID0gKGRvdWJsZSAqKW1hbGxvYyhzaXplICogc2l6ZW9mKGRvdWJsZSkpOwogICAgTVBJX0FsbGdhdGhlcigmbG9jYWxfbWF4LCAxLCBNUElfRE9VQkxFLCBtYXhfdmFsdWVzLCAxLCBNUElfRE9VQkxFLCBNUElfQ09NTV9XT1JMRCk7CgogICAgLy8gQWRkIG5laWdoYm9y4oCZcyBtYXggdmFsdWUsIG9yIHN1YnRyYWN0IGlmIHRoZSBwcm9jZXNzIGlzIHRoZSBvZGQtYmFsbAogICAgZG91YmxlIG5laWdoYm9yX21heCA9IChyYW5rID09IHNpemUgLSAxKSA/IG1heF92YWx1ZXNbMF0gOiBtYXhfdmFsdWVzW3JhbmsgKyAxXTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgaWYgKHJhbmsgPT0gb2RkX2JhbGwpIHsKICAgICAgICAgICAgYXJyYXlbaV0gLT0gbmVpZ2hib3JfbWF4OyAgLy8gT2RkLWJhbGwgc3VidHJhY3RzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYXJyYXlbaV0gKz0gbmVpZ2hib3JfbWF4OyAgLy8gT3RoZXJzIGFkZAogICAgICAgIH0KICAgIH0KCiAgICAvLyBPZGQtRXZlbiBUcmFuc3Bvc2l0aW9uIFNvcnQgdXNpbmcgTVBJCiAgICBpbnQgc29ydGVkID0gMDsKICAgIHdoaWxlICghc29ydGVkKSB7CiAgICAgICAgc29ydGVkID0gMTsKICAgICAgICBmb3IgKGludCBwaGFzZSA9IDA7IHBoYXNlIDwgc2l6ZTsgcGhhc2UrKykgewogICAgICAgICAgICBpbnQgcGFydG5lciA9IChwaGFzZSAlIDIgPT0gcmFuayAlIDIpID8gcmFuayArIDEgOiByYW5rIC0gMTsKICAgICAgICAgICAgaWYgKHBhcnRuZXIgPj0gMCAmJiBwYXJ0bmVyIDwgc2l6ZSkgewogICAgICAgICAgICAgICAgZG91YmxlICp0ZW1wX2FycmF5ID0gKGRvdWJsZSAqKW1hbGxvYyhOICogc2l6ZW9mKGRvdWJsZSkpOwogICAgICAgICAgICAgICAgTVBJX1NlbmRyZWN2KGFycmF5LCBOLCBNUElfRE9VQkxFLCBwYXJ0bmVyLCAwLCB0ZW1wX2FycmF5LCBOLCBNUElfRE9VQkxFLCBwYXJ0bmVyLCAwLCBNUElfQ09NTV9XT1JMRCwgTVBJX1NUQVRVU19JR05PUkUpOwogICAgICAgICAgICAgICAgLy8gTG9jYWwgc29ydGluZyBsb2dpYyBoZXJlIGJldHdlZW4gcmVjZWl2ZWQgYW5kIGxvY2FsIGFycmF5IGZvciB0cmFuc3Bvc2l0aW9uCiAgICAgICAgICAgICAgICBmcmVlKHRlbXBfYXJyYXkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vIFByaW50IGZpbmFsIHNvcnRlZCBhcnJheXMKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBwcmludGYoIkZpbmFsIFNvcnRlZCBBcnJheXM6XG4iKTsKICAgIH0KICAgIE1QSV9CYXJyaWVyKE1QSV9DT01NX1dPUkxEKTsgIC8vIFN5bmMgZm9yIG9yZGVybHkgcHJpbnRpbmcKICAgIHByaW50QXJyYXkoYXJyYXksIE4sIHJhbmspOwogICAgTVBJX0JhcnJpZXIoTVBJX0NPTU1fV09STEQpOwoKICAgIC8vIENsZWFuIHVwCiAgICBmcmVlKGFycmF5KTsKICAgIGZyZWUobWF4X3ZhbHVlcyk7CiAgICBNUElfRmluYWxpemUoKTsKICAgIHJldHVybiAwOwp9Cgo=