genclibs/time_it.h
2024-10-14 15:26:57 +02:00

76 lines
3.2 KiB
C

#ifndef TIME_IT_H
#define TIME_IT_H
#include <stddef.h>
#include <time.h>
#define ARRAY_OF double
#include "array.h"
/*
* time_it - executes the provided code and returns a
* following argument (a1, a2, ..., an)
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
*
* @code: the code to time; It can be a simple function call or
* a full block code
* @...: the optional argument number that
*
* @return: the elapsed execution time in seconds
* Note: fun can be either a macro, a function or a cast
* in parenthesis (e.g. for_each((char), 67, 10))
*/
#define time_it(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(, code, __VA_ARGS__)
/*
* for_each - apply a function-like object (fun) to each
* following argument (a1, a2, ..., an)
* resulting in (fun(a1)), (fun(a2)), ..., (fun(an))
*
* @fun: the function-like object to apply
* @...: the list of agurments on which to apply
*
* Note: fun can be either a macro, a function or a cast
* in parenthesis (e.g. for_each((char), 67, 10))
*/
#define time_it_repeat(code, ...) TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(REPEAT, code, __VA_ARGS__)
#define TIME_IT_NOT_EXPOSED__GENERIC_IMPLEMENTATION(type, code, ...) __extension__({ \
struct time_it_params { TIME_IT_NOT_EXPOSED__IF_REPEAT(type, size_t repeat;) size_t number;} time_it_params = (struct time_it_params){ TIME_IT_NOT_EXPOSED__IF_REPEAT(type, .repeat = 1, _) .number = 1}; \
__VA_OPT__(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG(__VA_ARGS__);) \
__VA_OPT__(TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(time_it_params TIME_IT_NOT_EXPOSED__FIRST_ARG, __VA_ARGS__);) \
TIME_IT_NOT_EXPOSED__INIT_RES(type, time_it_params.repeat);\
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, for(size_t i = 0; i < time_it_params.repeat; i++){) \
double time_it_time = 0; \
for(size_t j = 0; j < time_it_params.number; j++){ \
struct timespec time_it_start, time_it_stop; \
clock_gettime(CLOCK_MONOTONIC, &time_it_start); \
code; \
clock_gettime(CLOCK_MONOTONIC, &time_it_stop); \
time_it_time += ((time_it_stop.tv_sec - time_it_start.tv_sec) + (time_it_stop.tv_nsec - time_it_start.tv_nsec) / 1000000000.0); \
}\
TIME_IT_NOT_EXPOSED__WRITE_RES(type, time_it_time); \
TIME_IT_NOT_EXPOSED__IF_REPEAT(type, }) \
res;\
})
#define TIME_IT_NOT_EXPOSED__MAYBE_SECOND_ARG(macro, a1, ...) __VA_OPT__(macro(__VA_ARGS__))
#define TIME_IT_NOT_EXPOSED__FIRST_ARG(a1, ...) a1
#define TIME_IT_NOT_EXPOSED__INIT_RES_REPEAT(repeat) double_arr_t *res = double_arr_init(repeat)
#define TIME_IT_NOT_EXPOSED__INIT_RES_(_) double res = 0
#define TIME_IT_NOT_EXPOSED__INIT_RES(type, repeat) TIME_IT_NOT_EXPOSED__INIT_RES_ ## type (repeat)
#define TIME_IT_NOT_EXPOSED__WRITE_RES_REPEAT(value) double_arr_push(res, value)
#define TIME_IT_NOT_EXPOSED__WRITE_RES_(value) res = value
#define TIME_IT_NOT_EXPOSED__WRITE_RES(type, value) TIME_IT_NOT_EXPOSED__WRITE_RES_ ## type(value)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_REPEAT(code, ...) code __VA_OPT__(,)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT_(...)
#define TIME_IT_NOT_EXPOSED__IF_REPEAT(type, ...) TIME_IT_NOT_EXPOSED__IF_REPEAT_ ## type (__VA_ARGS__)
#endif //TIME_IT_H