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

/*! \file
 *  \brief Заголовочный файл c функциями тестирования библиотеки
 *  \author Фролов Андрей
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <iomanip>
#include <iostream>

#include "helper_for_cpp_tests.hpp"

extern "C" {
#include <elcore50-dsplib/asm_func.h>
#include <elcore50-dsplib/elcore50.h>
#include <elcore50-dsplib/reference.h>
}

extern int __local_mem;
extern uint32_t xyram_data;

#define LOCAL_MEM
// Количество тестов для каждой из функций. Максимальное количество равно пяти
#define TEST_COUNT 5

#define DISABLE_NEG_TEST_DATA
#define DISABLE_POS_TEST_DATA

/// Тестирование функции c двумя входами и одним выходом одного размера
/// @return количество ошибок
template <class T, class ref_func_ptr, class opt_func_ptr>
int test_cplx_func_2src_1dst(ref_func_ptr ref_func,  ///< [in]  указатель на референсную функцию
                             opt_func_ptr opt_func,  ///< [in]  указатель на оптимизированную функцию
                             T* src0,                ///< [in]  указатель на входной массив
                             T* src1,                ///< [in]  указатель на входной массив
                             T* dst_ref,             ///< [in]  указатель на выходной массив для референсной функции
                             T* dst_opt,           ///< [in]  указатель на выходной массив для оптимизированной функции
                             int size,             ///< [in]  количество комплексных элементов входных массивов
                             int32_t input_bytes,  ///< [in]  количество обрабатываемых байтов
                             std::string message   ///< [in]  название функции для лога
);

/// Тестирование функции c константным входом
/// @return количество ошибок
template <class T, class ref_func_ptr, class opt_func_ptr>
int test_cplx_func_rconst(ref_func_ptr ref_func,  ///< [in]  указатель на референсную функцию
                          opt_func_ptr opt_func,  ///< [in]  указатель на оптимизированную функцию
                          T value,                ///< [in]  константа
                          T* dst_ref,  ///< [in]  указатель на входной/выходной массив для референсной функции
                          T* dst_opt,  ///< [in]  указатель на входной/выходной массив для оптимизированной функции
                          int size,    ///< [in]  количество комплексных элементов входных массивов
                          int32_t input_bytes,  ///< [in]  количество обрабатываемых байт
                          std::string message   ///< [in]  название функции для лога
);

/// Тестирование функции acc_cplx32
/// @return количество ошибок
int test_vec_acc_cplx32(int32_t* src0,       ///< [in]  входные данные массива
                        int32_t* dst_opt,    ///< [out] выходные данные ассемблерной функции
                        int32_t* dst_ref,    ///< [out] выходные данные референсной функции
                        int size,            ///< [in]  количество комплексных элементов входного массива
                        int print,           ///< [in]  флаг для печати данных
                        int32_t input_bytes  ///< [in]  размер входных массивов в байтах
);

/// Тестирование функции sum_cplx32
/// @return количество ошибок
int test_vec_sum_cplx32(int32_t* dst_opt,    ///< [out] выходные данные ассемблерной функции
                        int32_t* dst_ref,    ///< [out] выходные данные референсной функции
                        int size,            ///< [in]  количество комплексных элементов входных массивов
                        int print,           ///< [in]  флаг для печати данных
                        int32_t input_bytes  ///< [in]  размер входных массивов в байтах
);

/// Тестирование функции abs_cplx32
/// @return количество ошибок
int test_abs_cplx32(int32_t* src0,       ///< [in]  входные данные массива
                    int32_t* dst_opt,    ///< [out] выходные данные ассемблерной функции
                    int32_t* dst_ref,    ///< [out] выходные данные референсной функции
                    int size,            ///< [in]  количество комплексных элементов входного массива
                    int print,           ///< [in]  флаг для печати данных
                    int32_t input_bytes  ///< [in]  размер входных массивов в байтах
);

/// Тестирование функции conv_cplx
/// @return количество ошибок
template <class T, class ref_func_ptr, class opt_func_ptr>
int test_conv_cplx(ref_func_ptr ref_func,  ///< [in]  указатель на референсную функцию
                   opt_func_ptr opt_func,  ///< [in]  указатель на оптимизированную функцию
                   T* src0,                ///< [in]  входные данные массива
                   T* src1,                ///< [in]  входные данные окна свертки
                   T* dst_opt,             ///< [out] выходные данные ассемблерной функции
                   T* dst_ref,             ///< [out] выходные данные референсной функции
                   int size,               ///< [in]  количество комплексных элементов входного массивов
                   int size_ker,           ///< [in]  количество комплексных элементов окна свертки
                   int print,              ///< [in]  флаг для печати данных
                   int32_t input_bytes     ///< [in]  размер входных массивов в байтах
);
