// SPDX-License-Identifier: MPL-2.0
#include "kernel/tests/test_utils.h"
#include "kernel/tests/test_slabs.h"
#include "kernel/tests/test_radix.h"
#include "kernel/log.h"
__attribute__((section(".bss")))
static sh_tsc_TSC_VALUE tsc_value[10000];
static void sort(sh_tsc_TSC_VALUE *array,sh_uint64 n) {
  for (sh_iter64 i=1;i<n;i++) {
    sh_tsc_TSC_VALUE key=array[i];
    sh_uint64 j=i;
    while (j>0 && array[j-1]>key) {
      array[j]=array[j-1];
      j--;
    }
    array[j]=key;
  }
}
static sh_tsc_TSC_VALUE percentile(sh_tsc_TSC_VALUE *array,sh_uint64 n,sh_uint8 p) {
  sh_uint64 idx=(n*p)/100;
  if (idx>=n) idx=n-1;
  return array[idx];
}
SH_STATUS sh_test_compute_print_stats(char* benchname,sh_tsc_TSC_VALUE *tsc_value_array,sh_uint64 array_size) {
  if (tsc_value_array==SH_NULLPTR || array_size==0) return SH_STATUS_INVALID_PARAMETER;
  sort(tsc_value_array,array_size);
  sh_uint64 min=tsc_value_array[0];
  sh_uint64 max=tsc_value_array[array_size-1];
  sh_uint64 median=tsc_value_array[array_size/2];
  sh_uint64 sum=0;
  for(sh_iter64 i=0;i<array_size;i++) sum+=tsc_value_array[i];
  sh_uint64 avrg=sum/array_size;
  sh_log_test("");
  sh_log_ftest("Result for benchmark \"%s\" :\n",benchname);
  sh_log_ftest("Min: %8u | Med: %8u | Avg: %8u | Max: %8u | Total : %8u (TSC)\n",min,median,avrg,max,sum);
  sh_uint64 p90=percentile(tsc_value_array,array_size,90);
  sh_uint64 p99=percentile(tsc_value_array,array_size,99);
  const char* labels[]={"[P00-P90]","[P90-P99]","[P99-Max]"};
  sh_uint64 bounds[]={min,p90,p99,max};
  sh_uint64 counts[]={90,9,1};
  for (int i=0;i<3;i++) {
    char bar[21];
    sh_uint64 fill=(counts[i]*20)/100;
    sh_uint64 j=0;
    for (;j<fill;j++) bar[j]='#';
    for (;j<20;j++) bar[j]='-';
    bar[20]='\0';
    sh_log_ftest("%s %8u-%8u : [%s] %8u%%\n",labels[i],bounds[i],bounds[i+1],bar,counts[i]);
  }
  return SH_STATUS_SUCCESS;
}
void sh_test_load_iterations_count(sh_uint64 iterations_num) {
  sh_test_slabs_load_iterations_count(iterations_num);
  sh_test_radix_load_iterations_count(iterations_num);
  return;
}
sh_tsc_TSC_VALUE* sh_test_get_tsc_values_buffer_ptr() {
  return &tsc_value[0];
}
