#include <iostream>
#include <fstream>
#include <vector>
#include <mpi.h>

// #define _NO_CXX11_AT_QUICK_EXIT
// #include <cstdlib>

using namespace std;

// Function to read a large number from a file into a vector of digits
void read_number(const string &filename, vector<int> &digits) {
    ifstream file(filename);
    int num_digits;
    file >> num_digits;  // Read the number of digits

    digits.resize(num_digits);
    for (int i = 0; i < num_digits; ++i) {
        file >> digits[i];
    }
}

// Function to write the result to a file
void write_result(const string &filename, const vector<int> &result) {
    ofstream file(filename);
    file << result.size() << endl;  // Write the number of digits
    for (int digit : result) {
        file << digit << " ";
    }
    file << endl;
}

int main(int argc, char* argv[]) {
    MPI_Init(&argc, &argv);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    vector<int> num1_digits, num2_digits, result_digits;
    vector<int> local_num1, local_num2, local_result;

    if (rank == 0) {
        // Process 0 reads the numbers from files
        read_number("Numar1.txt", num1_digits);
        read_number("Numar2.txt", num2_digits);

        // Ensure both numbers have the same length by padding with zeros if necessary
        int max_size = max(num1_digits.size(), num2_digits.size());
        num1_digits.resize(max_size, 0);
        num2_digits.resize(max_size, 0);

        result_digits.resize(max_size + 1, 0);  // Result can be one digit larger
    }

    // Scatter the digits across processes
    MPI_Scatter(num1_digits.data(), num1_digits.size() / size, MPI_INT,
                local_num1.data(), num1_digits.size() / size, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Scatter(num2_digits.data(), num2_digits.size() / size, MPI_INT,
                local_num2.data(), num2_digits.size() / size, MPI_INT, 0, MPI_COMM_WORLD);

    // Perform local addition
    int carry = 0;
    for (int i = 0; i < local_num1.size(); ++i) {
        int sum = local_num1[i] + local_num2[i] + carry;
        local_result.push_back(sum % 10);  // Store the last digit
        carry = sum / 10;  // Carry for the next addition
    }

    // Gather results back to process 0
    MPI_Gather(local_result.data(), local_result.size(), MPI_INT,
               result_digits.data(), local_result.size(), MPI_INT, 0, MPI_COMM_WORLD);

    // Process 0 writes the result to the file
    if (rank == 0) {
        write_result("Numar3.txt", result_digits);
    }

    MPI_Finalize();
    return 0;
}
