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

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

#ifndef _ASM_FUNC_H
#define _ASM_FUNC_H

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

/// Сумма элементов типа int16
extern void adds16(int16_t *src0,  ///< [in] входные данные
                   int16_t *src1,  ///< [in] входные данные
                   int16_t *dst,   ///< [out] выходные данные
                   int32_t size    ///< [in] размер входных данных
);
/// Сумма элементов типа int32
extern void adds32(int32_t *src0,  ///< [in] входные данные
                   int32_t *src1,  ///< [in] входные данные
                   int32_t *dst,   ///< [out] выходные данные
                   int32_t size    ///< [in] размер входных данных
);
/// Сумма элементов типа float
extern void add_fl(float *src0,  ///< [in] входные данные
                   float *src1,  ///< [in] входные данные
                   float *dst,   ///< [out] выходные данные
                   int32_t size  ///< [in] размер входных данных
);
/// Сумма элементов типа double
extern void add_db(double *src0,  ///< [in] входные данные
                   double *src1,  ///< [in] входные данные
                   double *dst,   ///< [out] выходные данные
                   int32_t size   ///< [in] размер входных данных
);
/// Скалярное произведение векторов типа int16
/// @return Значение скалярного произведения
extern int32_t dotprod(int16_t *src0,  ///< [in] входные данные
                       int16_t *src1,  ///< [in] входные данные
                       int32_t size    ///< [in] размер входных данных
);
/// Скалярное произведение векторов типа int32
/// @return Значение скалярного произведения
extern int64_t dotprod32(int32_t *src0,  ///< [in] входные данные
                         int32_t *src1,  ///< [in] входные данные
                         int32_t size    ///< [in] размер входных данных
);
/// Скалярное произведение векторов типа float
/// @return Значение скалярного произведения
extern float dotprod_fl(float *src0,  ///< [in] входные данные
                        float *src1,  ///< [in] входные данные
                        int32_t size  ///< [in] размер входных данных
);
/// Скалярное произведение векторов типа double
/// @return Значение скалярного произведения
extern double dotprod_db(double *src0,  ///< [in] входные данные
                         double *src1,  ///< [in] входные данные
                         int32_t size   ///< [in] размер входных данных
);
/// Корень из суммы элементов вектора типа int16
/// @return Корень из суммы элементов вектора
extern int64_t vecsumsq(int16_t *src0,  ///< [in] входные данные
                        int32_t size    ///< [in] размер входных данных
);
/// Корень из суммы элементов вектора типа int32
/// @return Корень из суммы элементов вектора
extern int64_t vecsumsq32(int32_t *src0,  ///< [in] входные данные
                          int32_t size    ///< [in] размер входных данных
);
/// Корень из суммы элементов вектора типа float
/// @return Корень из суммы элементов вектора
extern float vecsumsq_fl(float *src0,  ///< [in] входные данные
                         int32_t size  ///< [in] размер входных данных
);
/// Корень из суммы элементов вектора типа double
/// @return Корень из суммы элементов вектора
extern double vecsumsq_db(double *src0,  ///< [in] входные данные
                          int32_t size   ///< [in] размер входных данных
);
/// Отрицание элементов вектора типа int32
extern void neg32(int32_t *src0,  ///< [in] входные данные
                  int32_t *dst,   ///< [out] выходные данные
                  int32_t size    ///< [in] размер входных данных
);
/// Отрицание элементов вектора типа int16
extern void neg16(int16_t *src0,  ///< [in] входные данные
                  int16_t *dst,   ///< [out] выходные данные
                  int32_t size    ///< [in] размер входных данных
);
/// Отрицание элементов вектора типа float
extern void neg_fl(float *src0,  ///< [in] входные данные
                   float *dst,   ///< [out] выходные данные
                   int32_t size  ///< [in] размер входных данных
);
/// Отрицание элементов вектора типа double
extern void neg_db(double *src0,  ///< [in] входные данные
                   double *dst,   ///< [out] выходные данные
                   int32_t size   ///< [in] размер входных данных
);
/// Сложение элементов вектора с взвешенными элементами другого вектора для типа int16
extern void w_vec(int16_t *src0,  ///< [in] входные данные
                  int16_t *src1,  ///< [in] входные данные
                  int16_t w,      ///< [in] весовой коэффициент
                  int16_t *dst,   ///< [out] выходные данные
                  int32_t size    ///< [in] размер входных данных
);
/// Сложение элементов вектора с взвешенными элементами другого вектора для типа int32
extern void w_vec32(int32_t *src0,  ///< [in] входные данные
                    int32_t *src1,  ///< [in] входные данные
                    int32_t w,      ///< [in] весовой коэффициент
                    int32_t *dst,   ///< [out] выходные данные
                    int32_t size    ///< [in] размер входных данных
);
/// Сложение элементов вектора с взвешенными элементами другого вектора для типа float
extern void w_vec_fl(float *src0,  ///< [in] входные данные
                     float *src1,  ///< [in] входные данные
                     float w,      ///< [in] весовой коэффициент
                     float *dst,   ///< [out] выходные данные
                     int32_t size  ///< [in] размер входных данных
);
/// Сложение элементов вектора с взвешенными элементами другого вектора для типа double
extern void w_vec_db(double *src0,  ///< [in] входные данные
                     double *src1,  ///< [in] входные данные
                     double w,      ///< [in] весовой коэффициент
                     double *dst,   ///< [out] выходные данные
                     int32_t size   ///< [in] размер входных данных
);
/// Подсчет суммы квадратов элементов второго вектора, вычисление скалярного произведения векторов типа int16
/// @return Сумма квадратов элементов второго вектора
extern int32_t dotp_sqr(int32_t G,      ///< [in] коэффициент, который суммируется с результатом суммы квадратов
                        int16_t *src0,  ///< [in] входные данные
                        int16_t *src1,  ///< [in] входные данные
                        int32_t *r,     ///< [in] скалярное произведение векторов
                        int32_t size    ///< [in] размер входных данных
);
/// Подсчет суммы квадратов элементов второго вектора, вычисление скалярного произведения векторов типа int32
/// @return Сумма квадратов элементов второго вектора
extern int64_t dotp_sqr32(int64_t G,      ///< [in] коэффициент, который суммируется с результатом суммы квадратов
                          int32_t *src0,  ///< [in] входные данные
                          int32_t *src1,  ///< [in] входные данные
                          int64_t *r,     ///< [in] скалярное произведение векторов
                          int32_t size    ///< [in] размер входных данных
);
/// Подсчет суммы квадратов элементов второго вектора, вычисление скалярного произведения векторов типа float
/// @return Сумма квадратов элементов второго вектора
extern float dotp_sqr_fl(float G,      ///< [in] коэффициент, который суммируется с результатом суммы квадратов
                         float *src0,  ///< [in] входные данные
                         float *src1,  ///< [in] входные данные
                         float *r,     ///< [in] скалярное произведение векторов
                         int32_t size  ///< [in] размер входных данных
);
/// Подсчет суммы квадратов элементов второго вектора, вычисление скалярного произведения векторов типа double
/// @return Сумма квадратов элементов второго вектора
extern double dotp_sqr_db(double G,      ///< [in] коэффициент, который суммируется с результатом суммы квадратов
                          double *src0,  ///< [in] входные данные
                          double *src1,  ///< [in] входные данные
                          double *r,     ///< [in] скалярное произведение векторов
                          int32_t size   ///< [in] размер входных данных
);
/// Поиск значения максимального элемента в векторе типа int16
/// @return Значение максимума
extern int16_t maxval(int16_t *src0,  ///< [in] входные данные
                      int32_t size    ///< [in] размер входных данных
);
/// Поиск значения максимального элемента в векторе типа int32
/// @return Значение максимума
extern int32_t maxval32(int32_t *src0,  ///< [in] входные данные
                        int32_t size    ///< [in] размер входных данных
);
/// Поиск значения максимального элемента в векторе типа float
/// @return Значение максимума
extern float maxval_fl(float *src0,  ///< [in] входные данные
                       int32_t size  ///< [in] размер входных данных
);
/// Поиск значения максимального элемента в векторе типа double
/// @return Значение максимума
extern double maxval_db(double *src0,  ///< [in] входные данные
                        int32_t size   ///< [in] размер входных данных
);

/// Поиск значения минимального элемента в векторе типа int16
/// @return Значение максимума
extern int16_t minval(int16_t *src0,  ///< [in] входные данные
                      int32_t size    ///< [in] размер входных данных
);
/// Поиск значения минимального элемента в векторе типа int32
/// @return Значение максимума
extern int32_t minval32(int32_t *src0,  ///< [in] входные данные
                        int32_t size    ///< [in] размер входных данных
);
/// Поиск значения минимального элемента в векторе типа float
/// @return Значение максимума
extern float minval_fl(float *src0,  ///< [in] входные данные
                       int32_t size  ///< [in] размер входных данных
);
/// Поиск значения минимального элемента в векторе типа double
/// @return Значение максимума
extern double minval_db(double *src0,  ///< [in] входные данные
                        int32_t size   ///< [in] размер входных данных
);
/// Транспонирование матрицы типы int16
extern void mat_trans_scalar(int16_t *src0,    ///< [in] входные данные
                             int32_t rows,     ///< [in] количество строк матрицы
                             int32_t columns,  ///< [in] количество столбцов матрицы
                             int16_t *dst      ///< [out] выходные данные
);
/// Транспонирование матрицы типы float
extern void mat_trans_scalar_fl(float *src0,      ///< [in] входные данные
                                int32_t rows,     ///< [in] количество строк матрицы
                                int32_t columns,  ///< [in] количество столбцов матрицы
                                float *dst        ///< [out] выходные данные
);
/// Транспонирование матрицы типы int32
extern void mat_trans_scalar_s32(int32_t *src0,    ///< [in] входные данные
                                 int32_t rows,     ///< [in] количество строк матрицы
                                 int32_t columns,  ///< [in] количество столбцов матрицы
                                 int32_t *dst      ///< [out] выходные данные
);
/// Транспонирование матрицы типы double
extern void mat_trans_scalar_db(double *src0,     ///< [in] входные данные
                                int32_t rows,     ///< [in] количество строк матрицы
                                int32_t columns,  ///< [in] количество столбцов матрицы
                                double *dst       ///< [out] выходные данные
);
/// Умножение матриц типа int16
extern void mat_mul(int16_t *src0,     ///< [in] входные данные
                    int32_t rows0,     ///< [in] количество строк первой матрицы
                    int32_t columns0,  ///< [in] количество столбцов первой матрицы
                    int16_t *src1,     ///< [in] входные данные
                    int32_t columns1,  ///< [in] количество столбцов второй матрицы
                    int16_t *dst,      ///< [out] выходные данные
                    int32_t shift      ///< [in] сдвиг результата
);
/// Умножение матриц типа int32
extern void mat_mul32(int32_t *src0,     ///< [in] входные данные
                      int32_t rows0,     ///< [in] количество строк первой матрицы
                      int32_t columns0,  ///< [in] количество столбцов первой матрицы
                      int32_t *src1,     ///< [in] входные данные
                      int32_t columns1,  ///< [in] количество столбцов второй матрицы
                      int32_t *dst,      ///< [out] выходные данные
                      int32_t shift      ///< [in] сдвиг результата
);
/// Умножение матриц типа float
extern void mat_mul_fl(float *src0,       ///< [in] входные данные
                       int32_t rows0,     ///< [in] количество строк первой матрицы
                       int32_t columns0,  ///< [in] количество столбцов первой матрицы
                       float *src1,       ///< [in] входные данные
                       int32_t columns1,  ///< [in] количество столбцов второй матрицы
                       float *dst         ///< [out] выходные данные
);
/// Умножение матриц типа double
extern void mat_mul_db(double *src0,      ///< [in] входные данные
                       int32_t rows0,     ///< [in] количество строк первой матрицы
                       int32_t columns0,  ///< [in] количество столбцов первой матрицы
                       double *src1,      ///< [in] входные данные
                       int32_t columns1,  ///< [in] количество столбцов второй матрицы
                       double *dst        ///< [out] выходные данные
);
/// Комплексное умножение матриц типа int16 (cint16)
extern void mat_mul_cplx(int16_t *src0,     ///< [in] входные данные
                         int32_t rows0,     ///< [in] количество строк первой матрицы
                         int32_t columns0,  ///< [in] количество столбцов первой матрицы
                         int16_t *src1,     ///< [in] входные данные
                         int32_t columns1,  ///< [in] количество столбцов второй матрицы
                         int16_t *dst,      ///< [out] выходные данные референсной функции
                         int32_t shift      ///< [in] сдвиг результата
);
/// Комплексное умножение матриц типа int32 (cint32)
extern void mat_mul_cplx32(int32_t *src0,     ///< [in] входные данные
                           int32_t rows0,     ///< [in] количество строк первой матрицы
                           int32_t columns0,  ///< [in] количество столбцов первой матрицы
                           int32_t *src1,     ///< [in] входные данные
                           int32_t columns1,  ///< [in] количество столбцов второй матрицы
                           int32_t *dst,      ///< [out] выходные данные референсной функции
                           int32_t shift      ///< [in] сдвиг результата
);
/// Комплексное умножение матриц типа float (cfloat)
extern void mat_mul_cplx_fl(float *src0,       ///< [in] входные данные
                            int32_t rows0,     ///< [in] количество строк первой матрицы
                            int32_t columns0,  ///< [in] количество столбцов первой матрицы
                            float *src1,       ///< [in] входные данные
                            int32_t columns1,  ///< [in] количество столбцов второй матрицы
                            float *dst         ///< [out] выходные данные референсной функции
);
/// Комплексное умножение матриц типа double (cdouble)
extern void mat_mul_cplx_db(double *src0,      ///< [in] входные данные
                            int32_t rows0,     ///< [in] количество строк первой матрицы
                            int32_t columns0,  ///< [in] количество столбцов первой матрицы
                            double *src1,      ///< [in] входные данные
                            int32_t columns1,  ///< [in] количество столбцов второй матрицы
                            double *dst        ///< [out] выходные данные референсной функции
);
/// Обратная величина для чисел с фиксированной точкой типа int16
extern void recip16(int16_t *x,      ///< [in] входные данные
                    int16_t *rfrac,  ///< [out] выходные данные, нормализованное значение
                    int16_t *rexp,   ///< [out] выходные данные, значение степени экспоненты
                    int32_t size     ///< [in] размер входных массивов
);

/// Умножение чисел с фиксированной точкой (i=16,f=16)
extern void mul16i16f(int32_t *src0,  ///< [in]  входные данные первого массива
                      int32_t *src1,  ///< [in]  входные данные второго массива
                      int32_t *dst,   ///< [out] выходные данные массива
                      int32_t size    ///< [in]  количество элементов входных массивов
);
/// Сложение комплексных чисел
extern void add_cplx32(int32_t *src0,  ///< [in] входные данные
                       int32_t *src1,  ///< [in] входные данные
                       int32_t size,   ///< [in] размер входных массивов
                       int32_t *dst    ///< [out] выходные данные
);
/// Комплексное векторное сложение с накоплением
extern void acc_cplx32(int32_t *dst,   ///< [in/out] входные/выходные данные
                       int32_t *src0,  ///< [in] входные данные
                       int32_t size    ///< [in] размер входных массивов
);
/// Комплексное векторное вычитание
extern void sub_cplx32(int32_t *src0,  ///< [in] входные данные
                       int32_t *src1,  ///< [in] входные данные
                       int32_t size,   ///< [in] размер входных массивов
                       int32_t *dst    ///< [out] выходные данные
);
/// Комплексное векторное умножение
extern void mul_cplx32(int32_t *src0,  ///< [in] входные данные
                       int32_t *src1,  ///< [in] входные данные
                       int32_t size,   ///< [in] размер входных массивов
                       int32_t *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел, порядок следования Re, Im для типа int16_t
extern void mul_cplx16_re_im(int16_t *src0,  ///< [in]  входные данные для первого массива
                             int16_t *src1,  ///< [in]  входные данные для второго массива
                             int32_t size,   ///< [in]  количество комплексных элементов входных массивов
                             int16_t *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел, порядок следования Re, Im для типа int32_t
extern void mul_cplx32_re_im(int32_t *src0,  ///< [in]  входные данные для первого массива
                             int32_t *src1,  ///< [in]  входные данные для второго массива
                             int32_t size,   ///< [in]  количество комплексных элементов входных массивов
                             int32_t *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел, порядок следования Re, Im для типа float
extern void mul_cplx_fl_re_im(float *src0,   ///< [in]  входные данные для первого массива
                              float *src1,   ///< [in]  входные данные для второго массива
                              int32_t size,  ///< [in]  количество комплексных элементов входных массивов
                              float *dst     ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел, порядок следования Re, Im для типа double
extern void mul_cplx_db_re_im(double *src0,  ///< [in]  входные данные для первого массива
                              double *src1,  ///< [in]  входные данные для второго массива
                              int32_t size,  ///< [in]  количество комплексных элементов входных массивов
                              double *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел c комплексным сопряжением второго вектора,
/// порядок следования Re, Im для типа int16_t
extern void mul_conj_cplx16_re_im(int16_t *src0,  ///< [in]  входные данные для первого массива
                                  int16_t *src1,  ///< [in]  входные данные для второго массива
                                  int32_t size,   ///< [in]  количество комплексных элементов входных массивов
                                  int16_t *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел c комплексным сопряжением второго вектора,
/// порядок следования Re, Im для типа int32_t
extern void mul_conj_cplx32_re_im(int32_t *src0,  ///< [in]  входные данные для первого массива
                                  int32_t *src1,  ///< [in]  входные данные для второго массива
                                  int32_t size,   ///< [in]  количество комплексных элементов входных массивов
                                  int32_t *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел c комплексным сопряжением второго вектора,
/// порядок следования Re, Im для типа float
extern void mul_conj_cplx_fl_re_im(float *src0,   ///< [in]  входные данные для первого массива
                                   float *src1,   ///< [in]  входные данные для второго массива
                                   int32_t size,  ///< [in]  количество комплексных элементов входных массивов
                                   float *dst     ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел c комплексным сопряжением второго вектора/
/// порядок следования Re, Im для типа double
extern void mul_conj_cplx_db_re_im(double *src0,  ///< [in]  входные данные для первого массива
                                   double *src1,  ///< [in]  входные данные для второго массива
                                   int32_t size,  ///< [in]  количество комплексных элементов входных массивов
                                   double *dst    ///< [out] выходные данные
);
/// Поэлементное умножение двух векторов комплексных чисел c комплексным сопряжением второго вектора
extern void mul_conj_cplx32(int32_t *src0,  ///< [in] входные данные
                            int32_t *src1,  ///< [in] входные данные
                            int32_t size,   ///< [in] размер входных массивов
                            int32_t *dst    ///< [out] выходные данные
);
/// Добавление числа к каждому элементу вектора
extern void add_rconst_cplx32(int32_t *dst,  ///< [in/out] входные данные
                              int32_t size,  ///< [in] размер входных массивов
                              int32_t value  ///< [in] коэффициент
);
/// Умножение вектора на реальное число
extern void mul_rconst_cplx32(int32_t *dst,  ///< [in/out] входные данные
                              int32_t size,  ///< [in] размер входных массивов
                              int32_t value  ///< [in] коэффициент
);
/// Масштабирование вектора на степень двойки
extern void scale_cplx32(int32_t *dst,  ///< [in/out] входные данные
                         int32_t size,  ///< [in] размер входных массивов
                         int32_t value  ///< [in] коэффициент
);
/// Деление вектора на реальное число
extern void div_rconst_cplx32(int32_t *dst,  ///< [in/out] входные данные
                              int32_t size,  ///< [in] размер входных массивов
                              int32_t value  ///< [in] коэффициент
);
/// Сумма всех элементов вектора
extern void sum_cplx32(int32_t *dst,  ///< [in/out] входные данные
                       int32_t size,  ///< [in] размер входных массивов
                       int32_t *res   ///< [in] указатель на результат
);
/// Расчет модуля
extern void abs_cplx32(int32_t *src,  ///< [in] входные данные
                       int32_t size,  ///< [in] размер входных массивов
                       int32_t *res   ///< [in] указатель на результат
);
/// Вычисление свертки для одномерного массива, тип обработки границ valid, размер результата input_size - ker_size + 1
extern void conv_cplx32(int32_t *src0,     ///< [in]  входные данные
                        int32_t *src1,     ///< [in]  входные данные ядра
                        int32_t size,      ///< [in]  размер входного массива
                        int32_t size_ker,  ///< [in]  размер ядра свертки
                        int32_t *dst       ///< [out] указатель на результат
);
/// Вычисление свертки для одномерного массива, тип обработки границ valid, размер результата input_size - ker_size
/// + 1. Порядок следования Re, Im. Тип данных int32
extern void conv_cplx32_re_im(int32_t *src0,     ///< [in]  входные данные
                              int32_t *src1,     ///< [in]  входные данные ядра
                              int32_t size,      ///< [in]  размер входного массива
                              int32_t size_ker,  ///< [in]  размер ядра свертки
                              int32_t *dst       ///< [out] указатель на результат
);
/// Вычисление свертки для одномерного массива, тип обработки границ valid, размер результата input_size - ker_size
/// + 1. Порядок следования Re, Im. Тип данных float
extern void conv_cplx_fl_re_im(float *src0,       ///< [in]  входные данные
                               float *src1,       ///< [in]  входные данные ядра
                               int32_t size,      ///< [in]  размер входного массива
                               int32_t size_ker,  ///< [in]  размер ядра свертки
                               float *dst         ///< [out] указатель на результат
);
/// Поэлементное перемножение двух массивов типа int16
extern void muls16(const int16_t *src0,  ///< [in]  входные данные первого массива
                   const int16_t *src1,  ///< [in]  входные данные второго массива
                   int16_t *dst,         ///< [out] выходные данные массива
                   const int32_t size    ///< [in]  количество элементов выходного массива
);
/// Поэлементное перемножение двух массивов типа int32
extern void muls32(const int32_t *src0,  ///< [in]  входные данные первого массива
                   const int32_t *src1,  ///< [in]  входные данные второго массива
                   int32_t *dst,         ///< [out] выходные данные массива
                   const int32_t size    ///< [in]  количество элементов выходного массива
);
/// Поэлементное перемножение двух массивов типа float
extern void mul_fl(const float *src0,  ///< [in]  входные данные первого массива
                   const float *src1,  ///< [in]  входные данные второго массива
                   float *dst,         ///< [out] выходные данные массива
                   const int32_t size  ///< [in]  количество элементов выходного массива
);
/// Поэлементное перемножение двух массивов типа double
extern void mul_db(const double *src0,  ///< [in]  входные данные первого массива
                   const double *src1,  ///< [in]  входные данные второго массива
                   double *dst,         ///< [out] выходные данные массива
                   const int32_t size   ///< [in]  количество элементов выходного массива
);

#endif
