#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define COUNT1 262144   // 2^18
#define COUNT2 262145   // 2^18 + 1
#define COUNT3 262154   // 2^18 + 10
#define REPEATS 10000

void benchmark_copy(const int *src, int *dst, size_t count, const char *label) {
    size_t size_bytes = count * sizeof(int);

    clock_t start = clock();
    for (int i = 0; i < REPEATS; ++i) {
        memcpy(dst, src, size_bytes);
    }
    clock_t end = clock();

    double total_sec = (double)(end - start) / CLOCKS_PER_SEC;
    printf("%s: Copied %zu bytes (%zu ints) %d times\n", label, size_bytes, count, REPEATS);
    printf("%s: Total time: %.6f sec\n", label, total_sec);

    // Prevent optimizing away some stuff
    printf("%d \n", dst[14]);
}

int main(void) {
    static int src1[COUNT1], dst1[COUNT1];
    static int src2[COUNT2], dst2[COUNT2];
    static int src3[COUNT3], dst3[COUNT3];

    for (size_t i = 0; i < COUNT1; ++i) src1[i] = (int)i;
    for (size_t i = 0; i < COUNT2; ++i) src2[i] = (int)i;
    for (size_t i = 0; i < COUNT3; ++i) src3[i] = (int)i;
    
    // Do all benchmarks twice just in case
    benchmark_copy(src1, dst1, COUNT1, "COUNT1 (2^18)");
    benchmark_copy(src1, dst1, COUNT1, "COUNT1 (2^18)");
    benchmark_copy(src2, dst2, COUNT2, "COUNT2 (2^18 + 1)");
    benchmark_copy(src2, dst2, COUNT2, "COUNT2 (2^18 + 1)");
    benchmark_copy(src3, dst3, COUNT3, "COUNT3 (2^18 + 10)");
    benchmark_copy(src3, dst3, COUNT3, "COUNT3 (2^18 + 10)");

    return 0;
}