//
//  Created by Ivano Bilenchi on 22/05/18.
//  Copyright © 2018-2020 SisInf Lab. All rights reserved.
//

#ifndef TMEBenchmark_h
#define TMEBenchmark_h

#include <stdlib.h>
#include <mach/mach_time.h>

/**
 * Converts nanosecond intervals retrieved via mach_absolute_time to milliseconds.
 *
 * @param start Start timestamp.
 * @param end End timestamp.
 * @return Elapsed milliseconds.
 */
static double mach_time_to_millis(uint64_t start, uint64_t end) {
    mach_timebase_info_data_t info;
    if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0;
    double mult = (double)info.numer / (double)info.denom;
    return (double)(end-start) * mult / (double)NSEC_PER_MSEC;
}

/**
 * Benchmarks the given code block.
 *
 * @param prompt Prompt string.
 * @param end End string.
 * @param code Code block to benchmark.
 */
#define BENCHMARK(prompt, end, code) do {                                                           \
    printf("%s: ", (prompt));                                                                       \
    uint64_t start = mach_absolute_time();                                                          \
    code;                                                                                           \
    uint64_t stop = mach_absolute_time();                                                           \
    printf("%.2f ms", mach_time_to_millis(start, stop));                                            \
    if ((bool)(end)) printf("%s", end);                                                             \
} while (0)

#endif /* TMEBenchmark_h */
