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

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

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

typedef float float32_t;
typedef double float64_t;

extern uint32_t xyram_data;

#define count_tics(tic_addr, instr_addr)        \
  asm volatile(                                 \
      "tcr     tic_cntr, r18  trl    %0, r6\n \
        tcr     instr_cntr, r19 trl    %1, r7\n \
        stl     r18, (r6)    stl     r19, (r7)" \
      :                                         \
      : "r"(tic_addr), "r"(instr_addr))

/*!
 *  \fn void print_table_header()
 *  \brief Печать заголовка таблицы
 */
void print_table_header();

/*!
 *  \fn void print_performance(uint32_t* ref_tic_count, uint32_t* ref_instruction_count, uint32_t* tic_count, uint32_t*
 * instruction_count, int32_t input_bytes, int32_t ti_tics)
 *  \brief Печать информации о работе функции
 */
void print_performance(uint32_t* ref_tic_count, uint32_t* ref_instruction_count, uint32_t* tic_count,
                       uint32_t* instruction_count, int32_t input_bytes, int32_t ti_tics);

/*!
 *  \fn void print_vector_s32(int32_t* vect, int size)
 *  \brief Печать вектора типа int32
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 */
void print_vector_s32(int32_t* vect, int size);
/*!
 *  \fn void print_vector_s16(int16_t* vect, int size)
 *  \brief Печать вектора типа int16
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 */
void print_vector_s16(int16_t* vect, int size);
/*!
 *  \fn void print_vector_float(float* vect, int size)
 *  \brief Печать вектора типа float
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 */
void print_vector_float(float* vect, int size);
/*!
 *  \fn void print_vector_double(double* vect, int size)
 *  \brief Печать вектора типа double
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 */
void print_vector_double(double* vect, int size);

/*!
 *  \fn void create_vector_s16(int16_t* vect, int size, int sign)
 *  \brief Заполнение массива случайными числами типа int16
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 *  \param[in] sign знак случайных чисел (-1 - отрицательные, 1 - положительные, 0 - любой знак)
 */
void create_vector_s16(int16_t* vect, int size, int sign);
/*!
 *  \fn void create_vector_s32(int32_t* vect, int size, int sign)
 *  \brief Заполнение массива случайными числами типа int32
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 *  \param[in] sign знак случайных чисел (-1 - отрицательные, 1 - положительные, 0 - любой знак)
 */
void create_vector_s32(int32_t* vect, int size, int sign);
/*!
 *  \fn void create_vector_float(float* vect, int size, int sign)
 *  \brief Заполнение массива случайными числами типа float
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 *  \param[in] sign знак случайных чисел (-1 - отрицательные, 1 - положительные, 0 - любой знак)
 */
void create_vector_float(float* vect, int size, int sign);
/*!
 *  \fn void create_vector_double(double* vect, int size, int sign)
 *  \brief Заполнение массива случайными числами типа double
 *  \param[in] vect указатель на вектор
 *  \param[in] size размер входных данных
 *  \param[in] sign знак случайных чисел (-1 - отрицательные, 1 - положительные, 0 - любой знак)
 */
void create_vector_double(double* vect, int size, int sign);

/*!
 *  \fn uint8_t compare_s16(int16_t* vect0, int16_t* vect1, int size)
 *  \brief Сравнение векторов типа int16
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_s16(int16_t* vect0, int16_t* vect1, int size);
/*!
 *  \fn uint8_t compare_s32(int32_t* vect0, int32_t* vect1, int size)
 *  \brief Сравнение векторов типа int32
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_s32(int32_t* vect0, int32_t* vect1, int size);
/*!
 *  \fn uint8_t compare_s64(int64_t* vect0, int64_t* vect1, int size)
 *  \brief Сравнение векторов типа int64
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_s64(int64_t* vect0, int64_t* vect1, int size);
/*!
 *  \fn uint8_t compare_float(float* vect0, float* vect1, int size)
 *  \brief Сравнение векторов типа float
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_float(float* vect0, float* vect1, int size);
/*!
 *  \fn uint8_t compare_double(double* vect0, double* vect1, int size)
 *  \brief Сравнение векторов типа double
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_double(double* vect0, double* vect1, int size);

/*!
 *  \fn void print_matrix_s16(int16_t* mat, int rows, int columns)
 *  \brief Печать матрицы типа int16
 *  \param[in] mat указатель на матрицу
 *  \param[in] rows количество строк
 *  \param[in] columns количество столбцов
 */
void print_matrix_s16(int16_t* mat, int rows, int columns);
/*!
 *  \fn print_matrix_float(float* mat, int rows, int columns)
 *  \brief Печать матрицы типа float
 *  \param[in] mat указатель на матрицу
 *  \param[in] rows количество строк
 *  \param[in] columns количество столбцов
 */
void print_matrix_float(float* mat, int rows, int columns);
/*!
 *  \fn void print_matrix_s32(int32_t* mat, int rows, int columns)
 *  \brief Печать матрицы типа int32
 *  \param[in] mat указатель на матрицу
 *  \param[in] rows количество строк
 *  \param[in] columns количество столбцов
 */
void print_matrix_s32(int32_t* mat, int rows, int columns);
/*!
 *  \fn void print_matrix_double(double* mat, int rows, int columns)
 *  \brief Печать матрицы типа double
 *  \param[in] mat указатель на матрицу
 *  \param[in] rows количество строк
 *  \param[in] columns количество столбцов
 */
void print_matrix_double(double* mat, int rows, int columns);

/*!
 *  \fn uint8_t compare_float_eps(float* vect0, float* vect1, int size, float eps)
 *  \brief Сравнение векторов типа float c погрешностью
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \param[in] eps относительная погрешность
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_float_eps(float* vect0, float* vect1, int size, float eps);
/*!
 *  \fn uint8_t compare_double_eps(double* vect0, double* vect1, int size, float eps)
 *  \brief Сравнение векторов типа double c погрешностью
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \param[in] eps относительная погрешность
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_double_eps(double* vect0, double* vect1, int size, float eps);
/*!
 *  \fn uint8_t compare_16i16f_eps(int32_t* vect0, int32_t* vect1, int size, float eps)
 *  \brief Сравнение векторов типа 16i16f (фиксированная точка) c погрешностью
 *  \param[in] vect0 указатель на первый вектор
 *  \param[in] vect1 указатель на второй вектор
 *  \param[in] size размер входных данных
 *  \param[in] eps относительная погрешность
 *  \return
 *      - \b 0 вектора равны
        - \b 1 вектора не равны
 */
uint8_t compare_16i16f_eps(int32_t* vect0, int32_t* vect1, int size, float eps);
/*!
 *  \fn float pow_(int a, int b)
 *  \brief Возведение в степень
 *  \param[in] a число возводимое в степень
 *  \param[in] b степень
 *  \return
 *      - \b float результат возведения в степень
 */
float pow_(int a, int b);

/*!
 *  \fn int ceil_(float num)
 *  \brief Округление числа вверх
 *  \param[in] num округляемое число
 *  \return
 *      - \b int результат
 */
int ceil_(float num);
