// Copyright 2025 RnD Center "ELVEES", JSC

/*! \file
 *  \brief Тестирование обратного двумерного БПФ для типа float16
 */

#include "test.h"

int test_ifft_hfloat_2d(const int fft_min_size, const int fft_max_size) {
  int error_count = 0;
  int freq1 = 2;
  int freq2 = 1;
  const float peak = 1.0;
  int16_t *dst = memalign(fft_max_size * 2 * sizeof(int16_t), fft_max_size * 2 * sizeof(int16_t));
  int16_t *src = memalign(fft_max_size * 2 * sizeof(int16_t), fft_max_size * 2 * sizeof(int16_t));
  float *fetalon = memalign(fft_max_size * 2 * sizeof(float), fft_max_size * 2 * sizeof(float));

  char *test_info = malloc(sizeof(char) * 1000000);
  int print_bytes;

  FILE *res_2d;
  if (MEM_TYPE == SL_DDR)
    res_2d = fopen("test_HFLOAT_IFFT_2D_DDR.csv", "w");
  else
    res_2d = fopen("test_HFLOAT_IFFT_2D_XYRAM.csv", "w");

  fprintf(res_2d, "%s,%s,%s,%s\n", "SIZE", "TIC_CNTR", "INSTR_CNTR", "STATUS");

  print_bytes = sprintf(test_info, "2d hfloat IFFT ");
  if (MEM_TYPE == SL_DDR)
    print_bytes += sprintf(test_info + print_bytes, "DDR\n\n");
  else
    print_bytes += sprintf(test_info + print_bytes, "XYRAM\n\n");

  float *v_fl32 = malloc(2 * fft_max_size * sizeof(float));

  int length, height;

  int retval = SL_SUCCESS;
  for (int size = fft_min_size; size <= fft_max_size; size <<= 1) {
    length = 1 << (int)log2(size) / 2;
    height = size / length;
    print_bytes += sprintf(test_info + print_bytes, "\nheight = %d, length = %d\n", height, length);
    fprintf(res_2d, "%dx%d,", height, length);

    fft_t fft_obj;
    fft_obj.src = src;
    fft_obj.dst = dst;
    fft_obj.int_mem = (enum sl_data_memory)MEM_TYPE;
    fft_obj.dir = SL_IFFT;
    fft_obj.dim = SL_2D;

    memset(src, 0.0, 2 * fft_max_size * sizeof(short));
    asm("fhcv %1, %0" : "=r"(src[2 * (freq1 * length + freq2) + 1]) : "r"(peak));

    retval = fft_plan_2d(&fft_obj, height, length, SL_HFLOAT);
    if (retval) {
      print_error_message(retval);
      error_count = 1;
      break;
    }

    retval = fft_execute(&fft_obj);
    if (retval) {
      print_error_message(retval);
      error_count = 1;

      fft_free_sources(&fft_obj);
      break;
    }

    float16_to_float32(src, v_fl32, 2 * size);

    if (fft_obj.int_mem && fft_obj.big_size)
      create_spectrum_2d(fetalon, length, height, freq2, freq1, SL_HFLOAT);
    else
      create_spectrum_2d(fetalon, height, length, freq1, freq2, SL_HFLOAT);

    print_bytes += sprintf(test_info + print_bytes, "\nticks_fft = %d, instr_fft = %d", fft_obj.ticks, fft_obj.instrs);
    fprintf(res_2d, "%d,%d,", fft_obj.ticks, fft_obj.instrs);
    float norm = maximum_norm(v_fl32, fetalon, fft_obj.size);
    print_bytes += sprintf(test_info + print_bytes, ", norm = %f ", norm);
    if (norm < 1e-1) {
      print_bytes += sprintf(test_info + print_bytes, " : OK\n\n");
      fprintf(res_2d, "%s\n", "passed");
    } else {
      ++error_count;
      print_bytes += sprintf(test_info + print_bytes, " : WRONG\n\n");
      fprintf(res_2d, "%s\n", "failed");
    }

    fft_free_sources(&fft_obj);
  }

  printf("%s", test_info);

  free(v_fl32);
  free(src);
  free(dst);
  free(fetalon);
  free(test_info);
  fclose(res_2d);
  return error_count;
}
