//! To compile on GCC: g++ -std=gnu++0x -lrt main.cpp -o main

#include <vector>
#include <iomanip>
#include <iostream>
#include <cstring>

#include "inversions.hpp"
#include "chronometer.hpp"

int main(int argc, char** argv) {

    int step = 10;
    int max = 2000;

    enum {
        quadratic,
        nlogn
    } algo = quadratic;

    // Parse argv, minimal error checking.
    for (int i = 1; i < argc; i++) {
        if (strcmp("--nlogn", argv[i]) == 0) {
            algo = nlogn;
        } else if (strcmp("--max", argv[i]) == 0) {
            if (i + 1 < argc)
                max = atoi(argv[++i]);
        } else if (strcmp("--step", argv[i]) == 0) {
            if (i + 1 < argc)
                step = atoi(argv[++i]);
        }
    }

    benchmark::Chronometer chrono;
    std::vector<int> list;

    // Print header informations.
    std::cout << "# algo:" << (algo == quadratic ? "quad": "nlogn") << " "
              << "step:" << step << " "
              << "max:" << max << std::endl;
    std::cout << std::setw(6) << "# size"
              << std::setw(4) << "sec"
              << std::setw(10) << "ns"
              << std::endl;

    for (int i = 0, j = step; j <= max; i = j, j += step) {
        list.reserve(j);
        for (int k = i; k < j; k++) {
            list.push_back(max - k);    // Fill in decreasing order.
        }

        chrono.reset(); // Reset chronometer.
        chrono.start(); // Start chronometer.

        switch (algo) {
        case quadratic:
            inversions::quadratic(list);
            break;
        case nlogn:
            inversions::nlogn(list);
            break;
        }

        chrono.stop();  // Stop chronometer.

        // Print results for this instance.
        std::cout << std::setw(6) << j
                  << std::setw(4) << chrono.sec()
                  << std::setw(10) << chrono.nsec()
                  << std::endl;
    }

    return 0;
}