// Copyright 2018-2025 RnD Center "ELVEES", JSC

/*! \file
 *  \brief Тестирование функции recip16
 *  \author Фролов Андрей
 */

#include "tests.h"

int main() {
  int failed_count = 0;
  int size[TEST_COUNT] = {512, 1024, 2048, 8192, 16384};
  int print = 0;

  print_table_header();

#ifndef LOCAL_MEM
  void* src0 = memalign(64, size[TEST_COUNT - 1] * sizeof(int16_t));
  void* res_rf = memalign(64, size[TEST_COUNT - 1] * sizeof(int16_t));
  void* res_exp = memalign(64, size[TEST_COUNT - 1] * sizeof(int16_t));
  void* dsp_res_rf = memalign(64, size[TEST_COUNT - 1] * sizeof(int16_t));
  void* dsp_res_exp = memalign(64, size[TEST_COUNT - 1] * sizeof(int16_t));
#else
#ifdef BARE_METAL
  void* src0 = &__local_mem;
#else
  disable_l2_cache();
  void* src0 = &xyram_data;
#endif
  void* res_rf = src0 + size[TEST_COUNT - 1] * sizeof(int16_t);
  void* res_exp = res_rf + size[TEST_COUNT - 1] * sizeof(int16_t);
  void* dsp_res_rf = res_exp + size[TEST_COUNT - 1] * sizeof(int16_t);
  void* dsp_res_exp = dsp_res_rf + size[TEST_COUNT - 1] * sizeof(int16_t);
#endif

  create_vector_s16(src0, size[TEST_COUNT - 1], 0);
  for (int i = 0; i < TEST_COUNT; ++i) {
    int32_t input_bytes = size[i] * sizeof(int16_t) * 1;
    int32_t ti_tics = size[i] * 8 + 45;
    printf("| recip_short            | %14d |", size[i]);
    failed_count += test_recip16(src0, res_rf, res_exp, dsp_res_rf, dsp_res_exp, size[i], print, input_bytes, ti_tics);
  }

#ifndef LOCAL_MEM
  free(src0);
  free(res_rf);
  free(res_exp);
  free(dsp_res_rf);
  free(dsp_res_exp);
#else
#ifndef BARE_METAL
  enable_l2_cache(L2_CACHE_SIZE);
#endif
#endif

  return failed_count;
}

int test_recip16(int16_t* src0, int16_t* res_rf, int16_t* res_exp, int16_t* dsp_res_rf, int16_t* dsp_res_exp, int size,
                 int print, int32_t input_bytes, int32_t ti_tics) {
  uint32_t tic_count[2], instruction_count[2];
  uint32_t ref_tic_count[2], ref_instruction_count[2];

  int ret = 0;

  count_tics(ref_tic_count, ref_instruction_count);
  ref_recip16(src0, res_rf, res_exp, size);
  count_tics(&ref_tic_count[1], &ref_instruction_count[1]);

  count_tics(tic_count, instruction_count);
  recip16(src0, dsp_res_rf, dsp_res_exp, size);
  count_tics(&tic_count[1], &instruction_count[1]);

  if (print) {
    printf("src:");
    print_vector_s16(src0, size);

    printf("res_rf:");
    print_vector_s16(res_rf, size);
    printf("res_exp:");
    print_vector_s16(res_exp, size);

    printf("dsp_res_rf:");
    print_vector_s16(dsp_res_rf, size);
    printf("dsp_res_exp:");
    print_vector_s16(dsp_res_exp, size);
  }

  for (int i = 0; i < size; ++i) {
    double vect0 = res_rf[i] * pow(2, (double)res_exp[i]);
    double vect1 = dsp_res_rf[i] * pow(2, (double)dsp_res_exp[i]);
    if ((fabs((double)(vect0 - vect1) / vect0) > EPS)) {
      printf("%d %d %d %d\n", res_rf[i], res_exp[i], dsp_res_rf[i], dsp_res_exp[i]);
      ret += 1;
      if (ret > 10) break;
    }
  }

  print_performance(ref_tic_count, ref_instruction_count, tic_count, instruction_count, input_bytes, ti_tics);

  if (ret == 0)
    printf(" passed |\n");
  else
    printf(" failed |\n");

  return ret;
}
