From bd18d63a6d646962b1db6d85cba52eacb6dedfc7 Mon Sep 17 00:00:00 2001 From: xxxxm <2389287465@qq.com> Date: Sat, 7 Mar 2026 20:35:34 +0800 Subject: [PATCH] batch 3: add Middlewares --- Middlewares/ST/ARM/DSP/Inc/arm_math.h | 8970 +++++++++++++++++ .../ST/ARM/DSP/Lib/arm_ARMv8MMLlfsp_math.lib | Bin 0 -> 2669240 bytes .../ST/ARM/DSP/Lib/arm_cortexM3l_math.lib | Bin 0 -> 2695680 bytes .../ST/ARM/DSP/Lib/arm_cortexM4l_math.lib | Bin 0 -> 2755496 bytes .../ST/ARM/DSP/Lib/arm_cortexM4lf_math.lib | Bin 0 -> 2729868 bytes .../ST/ARM/DSP/Lib/iar_ARMv8MMLlfsp_math.a | Bin 0 -> 3770082 bytes .../ST/ARM/DSP/Lib/iar_cortexM3l_math.a | Bin 0 -> 3804952 bytes .../ST/ARM/DSP/Lib/iar_cortexM4l_math.a | Bin 0 -> 3948312 bytes .../ST/ARM/DSP/Lib/iar_cortexM4lf_math.a | Bin 0 -> 3914736 bytes .../ST/ARM/DSP/Lib/libarm_ARMv8MMLlfsp_math.a | Bin 0 -> 6120924 bytes .../ST/ARM/DSP/Lib/libarm_cortexM3l_math.a | Bin 0 -> 6184576 bytes .../ST/ARM/DSP/Lib/libarm_cortexM4l_math.a | Bin 0 -> 6514372 bytes .../ST/ARM/DSP/Lib/libarm_cortexM4lf_math.a | Bin 0 -> 6421864 bytes Middlewares/Third_Party/ARM/DSP/LICENSE.txt | 201 + .../FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h | 846 ++ .../FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c | 2482 +++++ .../FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h | 734 ++ .../Source/CMSIS_RTOS_V2/freertos_mpool.h | 63 + .../Source/CMSIS_RTOS_V2/freertos_os2.h | 310 + .../Third_Party/FreeRTOS/Source/History.txt | 2752 +++++ .../Third_Party/FreeRTOS/Source/LICENSE | 18 + .../Third_Party/FreeRTOS/Source/croutine.c | 353 + .../FreeRTOS/Source/event_groups.c | 753 ++ .../FreeRTOS/Source/include/FreeRTOS.h | 1295 +++ .../Source/include/FreeRTOSConfig_template.h | 162 + .../FreeRTOS/Source/include/StackMacros.h | 133 + .../FreeRTOS/Source/include/atomic.h | 414 + .../FreeRTOS/Source/include/croutine.h | 720 ++ .../Source/include/deprecated_definitions.h | 279 + .../FreeRTOS/Source/include/event_groups.h | 757 ++ .../FreeRTOS/Source/include/list.h | 412 + .../FreeRTOS/Source/include/message_buffer.h | 803 ++ .../FreeRTOS/Source/include/mpu_prototypes.h | 160 + .../FreeRTOS/Source/include/mpu_wrappers.h | 189 + .../FreeRTOS/Source/include/portable.h | 199 + .../FreeRTOS/Source/include/projdefs.h | 124 + .../FreeRTOS/Source/include/queue.h | 1655 +++ .../FreeRTOS/Source/include/semphr.h | 1140 +++ .../FreeRTOS/Source/include/stack_macros.h | 129 + .../FreeRTOS/Source/include/stream_buffer.h | 859 ++ .../FreeRTOS/Source/include/task.h | 2543 +++++ .../FreeRTOS/Source/include/timers.h | 1309 +++ .../Third_Party/FreeRTOS/Source/list.c | 198 + .../Source/portable/GCC/ARM_CM4F/port.c | 775 ++ .../Source/portable/GCC/ARM_CM4F/portmacro.h | 243 + .../FreeRTOS/Source/portable/MemMang/heap_1.c | 146 + .../FreeRTOS/Source/portable/MemMang/heap_2.c | 272 + .../FreeRTOS/Source/portable/MemMang/heap_3.c | 97 + .../FreeRTOS/Source/portable/MemMang/heap_4.c | 492 + .../FreeRTOS/Source/portable/MemMang/heap_5.c | 547 + .../Source/portable/RVDS/ARM_CM4F/port.c | 775 ++ .../Source/portable/RVDS/ARM_CM4F/portmacro.h | 243 + .../Third_Party/FreeRTOS/Source/queue.c | 2945 ++++++ .../Third_Party/FreeRTOS/Source/readme.txt | 17 + .../Third_Party/FreeRTOS/Source/st_readme.txt | 427 + .../FreeRTOS/Source/stream_buffer.c | 1263 +++ .../Third_Party/FreeRTOS/Source/tasks.c | 5310 ++++++++++ .../Third_Party/FreeRTOS/Source/timers.c | 1127 +++ 58 files changed, 45641 insertions(+) create mode 100644 Middlewares/ST/ARM/DSP/Inc/arm_math.h create mode 100644 Middlewares/ST/ARM/DSP/Lib/arm_ARMv8MMLlfsp_math.lib create mode 100644 Middlewares/ST/ARM/DSP/Lib/arm_cortexM3l_math.lib create mode 100644 Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib create mode 100644 Middlewares/ST/ARM/DSP/Lib/arm_cortexM4lf_math.lib create mode 100644 Middlewares/ST/ARM/DSP/Lib/iar_ARMv8MMLlfsp_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/iar_cortexM3l_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/iar_cortexM4l_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/iar_cortexM4lf_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/libarm_ARMv8MMLlfsp_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/libarm_cortexM3l_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/libarm_cortexM4l_math.a create mode 100644 Middlewares/ST/ARM/DSP/Lib/libarm_cortexM4lf_math.a create mode 100644 Middlewares/Third_Party/ARM/DSP/LICENSE.txt create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/freertos_mpool.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/freertos_os2.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/History.txt create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/LICENSE create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/croutine.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/event_groups.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/atomic.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/list.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/message_buffer.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/portable.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/queue.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/stack_macros.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/task.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/include/timers.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/list.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_1.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_2.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_3.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_5.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/queue.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/readme.txt create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/st_readme.txt create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/tasks.c create mode 100644 Middlewares/Third_Party/FreeRTOS/Source/timers.c diff --git a/Middlewares/ST/ARM/DSP/Inc/arm_math.h b/Middlewares/ST/ARM/DSP/Inc/arm_math.h new file mode 100644 index 0000000..48bee62 --- /dev/null +++ b/Middlewares/ST/ARM/DSP/Inc/arm_math.h @@ -0,0 +1,8970 @@ +/****************************************************************************** + * @file arm_math.h + * @brief Public header file for CMSIS DSP Library + * @version V1.7.0 + * @date 18. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2010-2019 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M and Cortex-A processor + * based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filtering functions + * - Matrix functions + * - Transform functions + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * - Support Vector Machine functions (SVM) + * - Bayes classifier functions + * - Distance functions + * + * The library has generally separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * + * Here is the list of pre-built libraries : + * - arm_cortexM7lfdp_math.lib (Cortex-M7, Little endian, Double Precision Floating Point Unit) + * - arm_cortexM7bfdp_math.lib (Cortex-M7, Big endian, Double Precision Floating Point Unit) + * - arm_cortexM7lfsp_math.lib (Cortex-M7, Little endian, Single Precision Floating Point Unit) + * - arm_cortexM7bfsp_math.lib (Cortex-M7, Big endian and Single Precision Floating Point Unit on) + * - arm_cortexM7l_math.lib (Cortex-M7, Little endian) + * - arm_cortexM7b_math.lib (Cortex-M7, Big endian) + * - arm_cortexM4lf_math.lib (Cortex-M4, Little endian, Floating Point Unit) + * - arm_cortexM4bf_math.lib (Cortex-M4, Big endian, Floating Point Unit) + * - arm_cortexM4l_math.lib (Cortex-M4, Little endian) + * - arm_cortexM4b_math.lib (Cortex-M4, Big endian) + * - arm_cortexM3l_math.lib (Cortex-M3, Little endian) + * - arm_cortexM3b_math.lib (Cortex-M3, Big endian) + * - arm_cortexM0l_math.lib (Cortex-M0 / Cortex-M0+, Little endian) + * - arm_cortexM0b_math.lib (Cortex-M0 / Cortex-M0+, Big endian) + * - arm_ARMv8MBLl_math.lib (Armv8-M Baseline, Little endian) + * - arm_ARMv8MMLl_math.lib (Armv8-M Mainline, Little endian) + * - arm_ARMv8MMLlfsp_math.lib (Armv8-M Mainline, Little endian, Single Precision Floating Point Unit) + * - arm_ARMv8MMLld_math.lib (Armv8-M Mainline, Little endian, DSP instructions) + * - arm_ARMv8MMLldfsp_math.lib (Armv8-M Mainline, Little endian, DSP instructions, Single Precision Floating Point Unit) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M cores with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library is now tested on Fast Models building with cmake. + * Core M0, M7, A5 are tested. + * + * + * + * Building the Library + * ------------ + * + * The library installer contains a project file to rebuild libraries on MDK toolchain in the CMSIS\\DSP\\Projects\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional preprocessor macros detailed above. + * + * There is also a work in progress cmake build. The README file is giving more details. + * + * Preprocessor Macros + * ------------ + * + * Each library project have different preprocessor macros. + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_LOOPUNROLL: + * + * Define macro ARM_MATH_LOOPUNROLL to enable manual loop unrolling in DSP functions + * + * - ARM_MATH_NEON: + * + * Define macro ARM_MATH_NEON to enable Neon versions of the DSP functions. + * It is not enabled by default when Neon is available because performances are + * dependent on the compiler and target architecture. + * + * - ARM_MATH_NEON_EXPERIMENTAL: + * + * Define macro ARM_MATH_NEON_EXPERIMENTAL to enable experimental Neon versions of + * of some DSP functions. Experimental Neon versions currently do not have better + * performances than the scalar versions. + * + * - ARM_MATH_HELIUM: + * + * It implies the flags ARM_MATH_MVEF and ARM_MATH_MVEI and ARM_MATH_FLOAT16. + * + * - ARM_MATH_MVEF: + * + * Select Helium versions of the f32 algorithms. + * It implies ARM_MATH_FLOAT16 and ARM_MATH_MVEI. + * + * - ARM_MATH_MVEI: + * + * Select Helium versions of the int and fixed point algorithms. + * + * - ARM_MATH_FLOAT16: + * + * Float16 implementations of some algorithms (Requires MVE extension). + * + *
+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |---------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP\\DSP_Lib_TestSuite | DSP_Lib test suite | + * |\b CMSIS\\DSP\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP\\Include | DSP_Lib include files | + * |\b CMSIS\\DSP\\Lib | DSP_Lib binaries | + * |\b CMSIS\\DSP\\Projects | Projects to rebuild DSP_Lib binaries | + * |\b CMSIS\\DSP\\Source | DSP_Lib source files | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to \ref arm_mat_init_f32(), \ref arm_mat_init_q31() and \ref arm_mat_init_q15() + * for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ + +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ + +/** + * @defgroup groupSVM SVM Functions + * This set of functions is implementing SVM classification on 2 classes. + * The training must be done from scikit-learn. The parameters can be easily + * generated from the scikit-learn object. Some examples are given in + * DSP/Testing/PatternGeneration/SVM.py + * + * If more than 2 classes are needed, the functions in this folder + * will have to be used, as building blocks, to do multi-class classification. + * + * No multi-class classification is provided in this SVM folder. + * + */ + + +/** + * @defgroup groupBayes Bayesian estimators + * + * Implement the naive gaussian Bayes estimator. + * The training must be done from scikit-learn. + * + * The parameters can be easily + * generated from the scikit-learn object. Some examples are given in + * DSP/Testing/PatternGeneration/Bayes.py + */ + +/** + * @defgroup groupDistance Distance functions + * + * Distance functions for use with clustering algorithms. + * There are distance functions for float vectors and boolean vectors. + * + */ + + +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wunused-parameter" + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#elif defined ( _MSC_VER ) + +#else + #error Unknown compiler +#endif + + +/* Included for instrinsics definitions */ +#if defined (_MSC_VER ) +#include +#define __STATIC_FORCEINLINE static __forceinline +#define __STATIC_INLINE static __inline +#define __ALIGNED(x) __declspec(align(x)) + +#elif defined (__GNUC_PYTHON__) +#include +#define __ALIGNED(x) __attribute__((aligned(x))) +#define __STATIC_FORCEINLINE static __attribute__((inline)) +#define __STATIC_INLINE static __attribute__((inline)) +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wattributes" + +#else +#include "cmsis_compiler.h" +#endif + + + +#include +#include +#include +#include + + +#define F64_MAX ((float64_t)DBL_MAX) +#define F32_MAX ((float32_t)FLT_MAX) + +#if defined(ARM_MATH_FLOAT16) +#define F16_MAX ((float16_t)FLT_MAX) +#endif + +#define F64_MIN (-DBL_MAX) +#define F32_MIN (-FLT_MAX) + +#if defined(ARM_MATH_FLOAT16) +#define F16_MIN (-(float16_t)FLT_MAX) +#endif + +#define F64_ABSMAX ((float64_t)DBL_MAX) +#define F32_ABSMAX ((float32_t)FLT_MAX) + +#if defined(ARM_MATH_FLOAT16) +#define F16_ABSMAX ((float16_t)FLT_MAX) +#endif + +#define F64_ABSMIN ((float64_t)0.0) +#define F32_ABSMIN ((float32_t)0.0) + +#if defined(ARM_MATH_FLOAT16) +#define F16_ABSMIN ((float16_t)0.0) +#endif + +#define Q31_MAX ((q31_t)(0x7FFFFFFFL)) +#define Q15_MAX ((q15_t)(0x7FFF)) +#define Q7_MAX ((q7_t)(0x7F)) +#define Q31_MIN ((q31_t)(0x80000000L)) +#define Q15_MIN ((q15_t)(0x8000)) +#define Q7_MIN ((q7_t)(0x80)) + +#define Q31_ABSMAX ((q31_t)(0x7FFFFFFFL)) +#define Q15_ABSMAX ((q15_t)(0x7FFF)) +#define Q7_ABSMAX ((q7_t)(0x7F)) +#define Q31_ABSMIN ((q31_t)0) +#define Q15_ABSMIN ((q15_t)0) +#define Q7_ABSMIN ((q7_t)0) + +/* evaluate ARM DSP feature */ +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + #define ARM_MATH_DSP 1 +#endif + +#if defined(ARM_MATH_NEON) +#include +#endif + +#if defined (ARM_MATH_HELIUM) + #define ARM_MATH_MVEF + #define ARM_MATH_FLOAT16 +#endif + +#if defined (ARM_MATH_MVEF) + #define ARM_MATH_MVEI + #define ARM_MATH_FLOAT16 +#endif + +#if defined (ARM_MATH_HELIUM) || defined(ARM_MATH_MVEF) || defined(ARM_MATH_MVEI) +#include +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 ((q31_t)(0x100)) +#define DELTA_Q15 ((q15_t)0x5) +#define INDEX_MASK 0x0000003F +#ifndef PI + #define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macros for complex numbers + */ + + /* Dimension C vector space */ + #define CMPLX_DIM 2 + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Input matrix is singular and cannot be inverted */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief vector types + */ +#if defined(ARM_MATH_NEON) || defined (ARM_MATH_MVEI) + /** + * @brief 64-bit fractional 128-bit vector data type in 1.63 format + */ + typedef int64x2_t q63x2_t; + + /** + * @brief 32-bit fractional 128-bit vector data type in 1.31 format. + */ + typedef int32x4_t q31x4_t; + + /** + * @brief 16-bit fractional 128-bit vector data type with 16-bit alignement in 1.15 format. + */ + typedef __ALIGNED(2) int16x8_t q15x8_t; + + /** + * @brief 8-bit fractional 128-bit vector data type with 8-bit alignement in 1.7 format. + */ + typedef __ALIGNED(1) int8x16_t q7x16_t; + + /** + * @brief 32-bit fractional 128-bit vector pair data type in 1.31 format. + */ + typedef int32x4x2_t q31x4x2_t; + + /** + * @brief 32-bit fractional 128-bit vector quadruplet data type in 1.31 format. + */ + typedef int32x4x4_t q31x4x4_t; + + /** + * @brief 16-bit fractional 128-bit vector pair data type in 1.15 format. + */ + typedef int16x8x2_t q15x8x2_t; + + /** + * @brief 16-bit fractional 128-bit vector quadruplet data type in 1.15 format. + */ + typedef int16x8x4_t q15x8x4_t; + + /** + * @brief 8-bit fractional 128-bit vector pair data type in 1.7 format. + */ + typedef int8x16x2_t q7x16x2_t; + + /** + * @brief 8-bit fractional 128-bit vector quadruplet data type in 1.7 format. + */ + typedef int8x16x4_t q7x16x4_t; + + /** + * @brief 32-bit fractional data type in 9.23 format. + */ + typedef int32_t q23_t; + + /** + * @brief 32-bit fractional 128-bit vector data type in 9.23 format. + */ + typedef int32x4_t q23x4_t; + + /** + * @brief 64-bit status 128-bit vector data type. + */ + typedef int64x2_t status64x2_t; + + /** + * @brief 32-bit status 128-bit vector data type. + */ + typedef int32x4_t status32x4_t; + + /** + * @brief 16-bit status 128-bit vector data type. + */ + typedef int16x8_t status16x8_t; + + /** + * @brief 8-bit status 128-bit vector data type. + */ + typedef int8x16_t status8x16_t; + + +#endif + +#if defined(ARM_MATH_NEON) || defined(ARM_MATH_MVEF) /* floating point vector*/ + /** + * @brief 32-bit floating-point 128-bit vector type + */ + typedef float32x4_t f32x4_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit floating-point 128-bit vector data type + */ + typedef __ALIGNED(2) float16x8_t f16x8_t; +#endif + + /** + * @brief 32-bit floating-point 128-bit vector pair data type + */ + typedef float32x4x2_t f32x4x2_t; + + /** + * @brief 32-bit floating-point 128-bit vector quadruplet data type + */ + typedef float32x4x4_t f32x4x4_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit floating-point 128-bit vector pair data type + */ + typedef float16x8x2_t f16x8x2_t; + + /** + * @brief 16-bit floating-point 128-bit vector quadruplet data type + */ + typedef float16x8x4_t f16x8x4_t; +#endif + + /** + * @brief 32-bit ubiquitous 128-bit vector data type + */ + typedef union _any32x4_t + { + float32x4_t f; + int32x4_t i; + } any32x4_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit ubiquitous 128-bit vector data type + */ + typedef union _any16x8_t + { + float16x8_t f; + int16x8_t i; + } any16x8_t; +#endif + +#endif + +#if defined(ARM_MATH_NEON) + /** + * @brief 32-bit fractional 64-bit vector data type in 1.31 format. + */ + typedef int32x2_t q31x2_t; + + /** + * @brief 16-bit fractional 64-bit vector data type in 1.15 format. + */ + typedef __ALIGNED(2) int16x4_t q15x4_t; + + /** + * @brief 8-bit fractional 64-bit vector data type in 1.7 format. + */ + typedef __ALIGNED(1) int8x8_t q7x8_t; + + /** + * @brief 32-bit float 64-bit vector data type. + */ + typedef float32x2_t f32x2_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit float 64-bit vector data type. + */ + typedef __ALIGNED(2) float16x4_t f16x4_t; +#endif + + /** + * @brief 32-bit floating-point 128-bit vector triplet data type + */ + typedef float32x4x3_t f32x4x3_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit floating-point 128-bit vector triplet data type + */ + typedef float16x8x3_t f16x8x3_t; +#endif + + /** + * @brief 32-bit fractional 128-bit vector triplet data type in 1.31 format + */ + typedef int32x4x3_t q31x4x3_t; + + /** + * @brief 16-bit fractional 128-bit vector triplet data type in 1.15 format + */ + typedef int16x8x3_t q15x8x3_t; + + /** + * @brief 8-bit fractional 128-bit vector triplet data type in 1.7 format + */ + typedef int8x16x3_t q7x16x3_t; + + /** + * @brief 32-bit floating-point 64-bit vector pair data type + */ + typedef float32x2x2_t f32x2x2_t; + + /** + * @brief 32-bit floating-point 64-bit vector triplet data type + */ + typedef float32x2x3_t f32x2x3_t; + + /** + * @brief 32-bit floating-point 64-bit vector quadruplet data type + */ + typedef float32x2x4_t f32x2x4_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit floating-point 64-bit vector pair data type + */ + typedef float16x4x2_t f16x4x2_t; + + /** + * @brief 16-bit floating-point 64-bit vector triplet data type + */ + typedef float16x4x3_t f16x4x3_t; + + /** + * @brief 16-bit floating-point 64-bit vector quadruplet data type + */ + typedef float16x4x4_t f16x4x4_t; +#endif + + /** + * @brief 32-bit fractional 64-bit vector pair data type in 1.31 format + */ + typedef int32x2x2_t q31x2x2_t; + + /** + * @brief 32-bit fractional 64-bit vector triplet data type in 1.31 format + */ + typedef int32x2x3_t q31x2x3_t; + + /** + * @brief 32-bit fractional 64-bit vector quadruplet data type in 1.31 format + */ + typedef int32x4x3_t q31x2x4_t; + + /** + * @brief 16-bit fractional 64-bit vector pair data type in 1.15 format + */ + typedef int16x4x2_t q15x4x2_t; + + /** + * @brief 16-bit fractional 64-bit vector triplet data type in 1.15 format + */ + typedef int16x4x2_t q15x4x3_t; + + /** + * @brief 16-bit fractional 64-bit vector quadruplet data type in 1.15 format + */ + typedef int16x4x3_t q15x4x4_t; + + /** + * @brief 8-bit fractional 64-bit vector pair data type in 1.7 format + */ + typedef int8x8x2_t q7x8x2_t; + + /** + * @brief 8-bit fractional 64-bit vector triplet data type in 1.7 format + */ + typedef int8x8x3_t q7x8x3_t; + + /** + * @brief 8-bit fractional 64-bit vector quadruplet data type in 1.7 format + */ + typedef int8x8x4_t q7x8x4_t; + + /** + * @brief 32-bit ubiquitous 64-bit vector data type + */ + typedef union _any32x2_t + { + float32x2_t f; + int32x2_t i; + } any32x2_t; + +#if defined(ARM_MATH_FLOAT16) + /** + * @brief 16-bit ubiquitous 64-bit vector data type + */ + typedef union _any16x4_t + { + float16x4_t f; + int16x4_t i; + } any16x4_t; +#endif + + /** + * @brief 32-bit status 64-bit vector data type. + */ + typedef int32x4_t status32x2_t; + + /** + * @brief 16-bit status 64-bit vector data type. + */ + typedef int16x8_t status16x4_t; + + /** + * @brief 8-bit status 64-bit vector data type. + */ + typedef int8x16_t status8x8_t; + +#endif + + + +/** + @brief definition to read/write two 16 bit values. + @deprecated + */ +#if defined ( __CC_ARM ) + #define __SIMD32_TYPE int32_t __packed +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define __SIMD32_TYPE int32_t +#elif defined ( __GNUC__ ) + #define __SIMD32_TYPE int32_t +#elif defined ( __ICCARM__ ) + #define __SIMD32_TYPE int32_t __packed +#elif defined ( __TI_ARM__ ) + #define __SIMD32_TYPE int32_t +#elif defined ( __CSMC__ ) + #define __SIMD32_TYPE int32_t +#elif defined ( __TASKING__ ) + #define __SIMD32_TYPE __un(aligned) int32_t +#elif defined(_MSC_VER ) + #define __SIMD32_TYPE int32_t +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ( (__SIMD32_TYPE * ) (addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE * ) (addr)) +#define __SIMD64(addr) (*( int64_t **) & (addr)) + +#define STEP(x) (x) <= 0 ? 0 : 1 +#define SQ(x) ((x) * (x)) + +/* SIMD replacement */ + + +/** + @brief Read 2 Q15 from Q15 pointer. + @param[in] pQ15 points to input value + @return Q31 value + */ +__STATIC_FORCEINLINE q31_t read_q15x2 ( + q15_t * pQ15) +{ + q31_t val; + +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (&val, pQ15, 4); +#else + val = (pQ15[1] << 16) | (pQ15[0] & 0x0FFFF) ; +#endif + + return (val); +} + +/** + @brief Read 2 Q15 from Q15 pointer and increment pointer afterwards. + @param[in] pQ15 points to input value + @return Q31 value + */ +__STATIC_FORCEINLINE q31_t read_q15x2_ia ( + q15_t ** pQ15) +{ + q31_t val; + +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (&val, *pQ15, 4); +#else + val = ((*pQ15)[1] << 16) | ((*pQ15)[0] & 0x0FFFF); +#endif + + *pQ15 += 2; + return (val); +} + +/** + @brief Read 2 Q15 from Q15 pointer and decrement pointer afterwards. + @param[in] pQ15 points to input value + @return Q31 value + */ +__STATIC_FORCEINLINE q31_t read_q15x2_da ( + q15_t ** pQ15) +{ + q31_t val; + +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (&val, *pQ15, 4); +#else + val = ((*pQ15)[1] << 16) | ((*pQ15)[0] & 0x0FFFF); +#endif + + *pQ15 -= 2; + return (val); +} + +/** + @brief Write 2 Q15 to Q15 pointer and increment pointer afterwards. + @param[in] pQ15 points to input value + @param[in] value Q31 value + @return none + */ +__STATIC_FORCEINLINE void write_q15x2_ia ( + q15_t ** pQ15, + q31_t value) +{ + q31_t val = value; +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (*pQ15, &val, 4); +#else + (*pQ15)[0] = (val & 0x0FFFF); + (*pQ15)[1] = (val >> 16) & 0x0FFFF; +#endif + + *pQ15 += 2; +} + +/** + @brief Write 2 Q15 to Q15 pointer. + @param[in] pQ15 points to input value + @param[in] value Q31 value + @return none + */ +__STATIC_FORCEINLINE void write_q15x2 ( + q15_t * pQ15, + q31_t value) +{ + q31_t val = value; + +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (pQ15, &val, 4); +#else + pQ15[0] = val & 0x0FFFF; + pQ15[1] = val >> 16; +#endif +} + + +/** + @brief Read 4 Q7 from Q7 pointer and increment pointer afterwards. + @param[in] pQ7 points to input value + @return Q31 value + */ +__STATIC_FORCEINLINE q31_t read_q7x4_ia ( + q7_t ** pQ7) +{ + q31_t val; + + +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (&val, *pQ7, 4); +#else + val =(((*pQ7)[3] & 0x0FF) << 24) | (((*pQ7)[2] & 0x0FF) << 16) | (((*pQ7)[1] & 0x0FF) << 8) | ((*pQ7)[0] & 0x0FF); +#endif + + *pQ7 += 4; + + return (val); +} + +/** + @brief Read 4 Q7 from Q7 pointer and decrement pointer afterwards. + @param[in] pQ7 points to input value + @return Q31 value + */ +__STATIC_FORCEINLINE q31_t read_q7x4_da ( + q7_t ** pQ7) +{ + q31_t val; +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (&val, *pQ7, 4); +#else + val = ((((*pQ7)[3]) & 0x0FF) << 24) | ((((*pQ7)[2]) & 0x0FF) << 16) | ((((*pQ7)[1]) & 0x0FF) << 8) | ((*pQ7)[0] & 0x0FF); +#endif + *pQ7 -= 4; + + return (val); +} + +/** + @brief Write 4 Q7 to Q7 pointer and increment pointer afterwards. + @param[in] pQ7 points to input value + @param[in] value Q31 value + @return none + */ +__STATIC_FORCEINLINE void write_q7x4_ia ( + q7_t ** pQ7, + q31_t value) +{ + q31_t val = value; +#ifdef __ARM_FEATURE_UNALIGNED + memcpy (*pQ7, &val, 4); +#else + (*pQ7)[0] = val & 0x0FF; + (*pQ7)[1] = (val >> 8) & 0x0FF; + (*pQ7)[2] = (val >> 16) & 0x0FF; + (*pQ7)[3] = (val >> 24) & 0x0FF; + +#endif + *pQ7 += 4; +} + +/* + +Normally those kind of definitions are in a compiler file +in Core or Core_A. + +But for MSVC compiler it is a bit special. The goal is very specific +to CMSIS-DSP and only to allow the use of this library from other +systems like Python or Matlab. + +MSVC is not going to be used to cross-compile to ARM. So, having a MSVC +compiler file in Core or Core_A would not make sense. + +*/ +#if defined ( _MSC_VER ) || defined(__GNUC_PYTHON__) + __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#ifndef ARM_MATH_DSP + /** + * @brief definition to pack two 16 bit values. + */ + #define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) + #define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) +#endif + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + #define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + #define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + __STATIC_FORCEINLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + __STATIC_FORCEINLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + __STATIC_FORCEINLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + __STATIC_FORCEINLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + __STATIC_FORCEINLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y) ) ); + } + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + __STATIC_FORCEINLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + const q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if (in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0U; i < 2U; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1U); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + __STATIC_FORCEINLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + const q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if (in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0U; i < 2U; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + +/** + * @brief Integer exponentiation + * @param[in] x value + * @param[in] nb integer exponent >= 1 + * @return x^nb + * + */ +__STATIC_INLINE float32_t arm_exponent_f32(float32_t x, int32_t nb) +{ + float32_t r = x; + nb --; + while(nb > 0) + { + r = r * x; + nb--; + } + return(r); +} + +/** + * @brief 64-bit to 32-bit unsigned normalization + * @param[in] in is input unsigned long long value + * @param[out] normalized is the 32-bit normalized value + * @param[out] norm is norm scale + */ +__STATIC_INLINE void arm_norm_64_to_32u(uint64_t in, int32_t * normalized, int32_t *norm) +{ + int32_t n1; + int32_t hi = (int32_t) (in >> 32); + int32_t lo = (int32_t) ((in << 32) >> 32); + + n1 = __CLZ(hi) - 32; + if (!n1) + { + /* + * input fits in 32-bit + */ + n1 = __CLZ(lo); + if (!n1) + { + /* + * MSB set, need to scale down by 1 + */ + *norm = -1; + *normalized = (((uint32_t) lo) >> 1); + } else + { + if (n1 == 32) + { + /* + * input is zero + */ + *norm = 0; + *normalized = 0; + } else + { + /* + * 32-bit normalization + */ + *norm = n1 - 1; + *normalized = lo << *norm; + } + } + } else + { + /* + * input fits in 64-bit + */ + n1 = 1 - n1; + *norm = -n1; + /* + * 64 bit normalization + */ + *normalized = (((uint32_t) lo) >> n1) | (hi << (32 - n1)); + } +} + +__STATIC_INLINE q31_t arm_div_q63_to_q31(q63_t num, q31_t den) +{ + q31_t result; + uint64_t absNum; + int32_t normalized; + int32_t norm; + + /* + * if sum fits in 32bits + * avoid costly 64-bit division + */ + absNum = num > 0 ? num : -num; + arm_norm_64_to_32u(absNum, &normalized, &norm); + if (norm > 0) + /* + * 32-bit division + */ + result = (q31_t) num / den; + else + /* + * 64-bit division + */ + result = (q31_t) (num / den); + + return result; +} + + +/* + * @brief C custom defined intrinsic functions + */ +#if !defined (ARM_MATH_DSP) + + /* + * @brief C custom defined QADD8 + */ + __STATIC_FORCEINLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 + */ + __STATIC_FORCEINLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 + */ + __STATIC_FORCEINLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 + */ + __STATIC_FORCEINLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 + */ + __STATIC_FORCEINLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 + */ + __STATIC_FORCEINLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX + */ + __STATIC_FORCEINLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX + */ + __STATIC_FORCEINLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX + */ + __STATIC_FORCEINLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX + */ + __STATIC_FORCEINLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX + */ + __STATIC_FORCEINLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX + */ + __STATIC_FORCEINLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD + */ + __STATIC_FORCEINLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB + */ + __STATIC_FORCEINLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD + */ + __STATIC_FORCEINLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX + */ + __STATIC_FORCEINLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX + */ + __STATIC_FORCEINLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD + */ + __STATIC_FORCEINLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX + */ + __STATIC_FORCEINLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD + */ + __STATIC_FORCEINLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD + */ + __STATIC_FORCEINLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 + */ + __STATIC_FORCEINLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + + /* + * @brief C custom defined SMMLA + */ + __STATIC_FORCEINLINE int32_t __SMMLA( + int32_t x, + int32_t y, + int32_t sum) + { + return (sum + (int32_t) (((int64_t) x * y) >> 32)); + } + +#endif /* !defined (ARM_MATH_DSP) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + const q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + const q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + const q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + const float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + const q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + const q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the fast Q15 FIR filter (fast version). + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns either + * ARM_MATH_SUCCESS if initialization was successful or + * ARM_MATH_ARGUMENT_ERROR if numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + const q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the fast Q31 FIR filter (fast version). + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + const q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + const float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + const q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + const q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + const float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) + /** + * @brief Instance structure for the modified Biquad coefs required by vectorized code. + */ + typedef struct + { + float32_t coeffs[8][4]; /**< Points to the array of modified coefficients. The array is of length 32. There is one per stage */ + } arm_biquad_mod_coef_f32; +#endif + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + const q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + const q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pCoeffsMod points to the modified filter coefficients (only MVE version). + * @param[in] pState points to the state buffer. + */ +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) + void arm_biquad_cascade_df1_mve_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + const float32_t * pCoeffs, + arm_biquad_mod_coef_f32 * pCoeffsMod, + float32_t * pState); +#endif + + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + const float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Compute the logical bitwise AND of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_and_u16( + const uint16_t * pSrcA, + const uint16_t * pSrcB, + uint16_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise AND of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_and_u32( + const uint32_t * pSrcA, + const uint32_t * pSrcB, + uint32_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise AND of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_and_u8( + const uint8_t * pSrcA, + const uint8_t * pSrcB, + uint8_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise OR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_or_u16( + const uint16_t * pSrcA, + const uint16_t * pSrcB, + uint16_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise OR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_or_u32( + const uint32_t * pSrcA, + const uint32_t * pSrcB, + uint32_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise OR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_or_u8( + const uint8_t * pSrcA, + const uint8_t * pSrcB, + uint8_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise NOT of a fixed-point vector. + * @param[in] pSrc points to input vector + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_not_u16( + const uint16_t * pSrc, + uint16_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise NOT of a fixed-point vector. + * @param[in] pSrc points to input vector + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_not_u32( + const uint32_t * pSrc, + uint32_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise NOT of a fixed-point vector. + * @param[in] pSrc points to input vector + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_not_u8( + const uint8_t * pSrc, + uint8_t * pDst, + uint32_t blockSize); + +/** + * @brief Compute the logical bitwise XOR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_xor_u16( + const uint16_t * pSrcA, + const uint16_t * pSrcB, + uint16_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise XOR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_xor_u32( + const uint32_t * pSrcA, + const uint32_t * pSrcB, + uint32_t * pDst, + uint32_t blockSize); + + /** + * @brief Compute the logical bitwise XOR of two fixed-point vectors. + * @param[in] pSrcA points to input vector A + * @param[in] pSrcB points to input vector B + * @param[out] pDst points to output vector + * @param[in] blockSize number of samples in each vector + * @return none + */ + void arm_xor_u8( + const uint8_t * pSrcA, + const uint8_t * pSrcB, + uint8_t * pDst, + uint32_t blockSize); + + /** + * @brief Struct for specifying sorting algorithm + */ + typedef enum + { + ARM_SORT_BITONIC = 0, + /**< Bitonic sort */ + ARM_SORT_BUBBLE = 1, + /**< Bubble sort */ + ARM_SORT_HEAP = 2, + /**< Heap sort */ + ARM_SORT_INSERTION = 3, + /**< Insertion sort */ + ARM_SORT_QUICK = 4, + /**< Quick sort */ + ARM_SORT_SELECTION = 5 + /**< Selection sort */ + } arm_sort_alg; + + /** + * @brief Struct for specifying sorting algorithm + */ + typedef enum + { + ARM_SORT_DESCENDING = 0, + /**< Descending order (9 to 0) */ + ARM_SORT_ASCENDING = 1 + /**< Ascending order (0 to 9) */ + } arm_sort_dir; + + /** + * @brief Instance structure for the sorting algorithms. + */ + typedef struct + { + arm_sort_alg alg; /**< Sorting algorithm selected */ + arm_sort_dir dir; /**< Sorting order (direction) */ + } arm_sort_instance_f32; + + /** + * @param[in] S points to an instance of the sorting structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_sort_f32( + const arm_sort_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @param[in,out] S points to an instance of the sorting structure. + * @param[in] alg Selected algorithm. + * @param[in] dir Sorting order. + */ + void arm_sort_init_f32( + arm_sort_instance_f32 * S, + arm_sort_alg alg, + arm_sort_dir dir); + + /** + * @brief Instance structure for the sorting algorithms. + */ + typedef struct + { + arm_sort_dir dir; /**< Sorting order (direction) */ + float32_t * buffer; /**< Working buffer */ + } arm_merge_sort_instance_f32; + + /** + * @param[in] S points to an instance of the sorting structure. + * @param[in,out] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_merge_sort_f32( + const arm_merge_sort_instance_f32 * S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); + + /** + * @param[in,out] S points to an instance of the sorting structure. + * @param[in] dir Sorting order. + * @param[in] buffer Working buffer. + */ + void arm_merge_sort_init_f32( + arm_merge_sort_instance_f32 * S, + arm_sort_dir dir, + float32_t * buffer); + + /** + * @brief Struct for specifying cubic spline type + */ + typedef enum + { + ARM_SPLINE_NATURAL = 0, /**< Natural spline */ + ARM_SPLINE_PARABOLIC_RUNOUT = 1 /**< Parabolic runout spline */ + } arm_spline_type; + + /** + * @brief Instance structure for the floating-point cubic spline interpolation. + */ + typedef struct + { + arm_spline_type type; /**< Type (boundary conditions) */ + const float32_t * x; /**< x values */ + const float32_t * y; /**< y values */ + uint32_t n_x; /**< Number of known data points */ + float32_t * coeffs; /**< Coefficients buffer (b,c, and d) */ + } arm_spline_instance_f32; + + /** + * @brief Processing function for the floating-point cubic spline interpolation. + * @param[in] S points to an instance of the floating-point spline structure. + * @param[in] xq points to the x values ot the interpolated data points. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples of output data. + */ + void arm_spline_f32( + arm_spline_instance_f32 * S, + const float32_t * xq, + float32_t * pDst, + uint32_t blockSize); + + /** + * @brief Initialization function for the floating-point cubic spline interpolation. + * @param[in,out] S points to an instance of the floating-point spline structure. + * @param[in] type type of cubic spline interpolation (boundary conditions) + * @param[in] x points to the x values of the known data points. + * @param[in] y points to the y values of the known data points. + * @param[in] n number of known data points. + * @param[in] coeffs coefficients array for b, c, and d + * @param[in] tempBuffer buffer array for internal computations + */ + void arm_spline_init_f32( + arm_spline_instance_f32 * S, + arm_spline_type type, + const float32_t * x, + const float32_t * y, + uint32_t n, + float32_t * coeffs, + float32_t * tempBuffer); + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#if !defined (ARM_MATH_DSP) + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + const q7_t * pSrcA, + const q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const q15_t *pTwiddle; /**< points to the twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const q31_t *pTwiddle; /**< points to the twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ +#if defined(ARM_MATH_MVEI) + const uint32_t *rearranged_twiddle_tab_stride1_arr; /**< Per stage reordered twiddle pointer (offset 1) */ \ + const uint32_t *rearranged_twiddle_tab_stride2_arr; /**< Per stage reordered twiddle pointer (offset 2) */ \ + const uint32_t *rearranged_twiddle_tab_stride3_arr; /**< Per stage reordered twiddle pointer (offset 3) */ \ + const q15_t *rearranged_twiddle_stride1; /**< reordered twiddle offset 1 storage */ \ + const q15_t *rearranged_twiddle_stride2; /**< reordered twiddle offset 2 storage */ \ + const q15_t *rearranged_twiddle_stride3; +#endif + } arm_cfft_instance_q15; + +arm_status arm_cfft_init_q15( + arm_cfft_instance_q15 * S, + uint16_t fftLen); + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ +#if defined(ARM_MATH_MVEI) + const uint32_t *rearranged_twiddle_tab_stride1_arr; /**< Per stage reordered twiddle pointer (offset 1) */ \ + const uint32_t *rearranged_twiddle_tab_stride2_arr; /**< Per stage reordered twiddle pointer (offset 2) */ \ + const uint32_t *rearranged_twiddle_tab_stride3_arr; /**< Per stage reordered twiddle pointer (offset 3) */ \ + const q31_t *rearranged_twiddle_stride1; /**< reordered twiddle offset 1 storage */ \ + const q31_t *rearranged_twiddle_stride2; /**< reordered twiddle offset 2 storage */ \ + const q31_t *rearranged_twiddle_stride3; +#endif + } arm_cfft_instance_q31; + +arm_status arm_cfft_init_q31( + arm_cfft_instance_q31 * S, + uint16_t fftLen); + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) + const uint32_t *rearranged_twiddle_tab_stride1_arr; /**< Per stage reordered twiddle pointer (offset 1) */ \ + const uint32_t *rearranged_twiddle_tab_stride2_arr; /**< Per stage reordered twiddle pointer (offset 2) */ \ + const uint32_t *rearranged_twiddle_tab_stride3_arr; /**< Per stage reordered twiddle pointer (offset 3) */ \ + const float32_t *rearranged_twiddle_stride1; /**< reordered twiddle offset 1 storage */ \ + const float32_t *rearranged_twiddle_stride2; /**< reordered twiddle offset 2 storage */ \ + const float32_t *rearranged_twiddle_stride3; +#endif + } arm_cfft_instance_f32; + + + arm_status arm_cfft_init_f32( + arm_cfft_instance_f32 * S, + uint16_t fftLen); + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + + /** + * @brief Instance structure for the Double Precision Floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float64_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f64; + + void arm_cfft_f64( + const arm_cfft_instance_f64 * S, + float64_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + const q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + const q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ +#if defined(ARM_MATH_MVEI) + arm_cfft_instance_q15 cfftInst; +#else + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ +#endif + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + const q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + const q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ +#if defined(ARM_MATH_MVEI) + arm_cfft_instance_q31 cfftInst; +#else + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ +#endif + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + const float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + const float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the Double Precision Floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f64 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + const float64_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f64 ; + +arm_status arm_rfft_fast_init_f64 ( + arm_rfft_fast_instance_f64 * S, + uint16_t fftLen); + + +void arm_rfft_fast_f64( + arm_rfft_fast_instance_f64 * S, + float64_t * p, float64_t * pOut, + uint8_t ifftFlag); + + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + const float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + + + void arm_rfft_fast_f32( + const arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + const float32_t *pTwiddle; /**< points to the twiddle factor table. */ + const float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + const q31_t *pTwiddle; /**< points to the twiddle factor table. */ + const q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + const q15_t *pTwiddle; /**< points to the twiddle factor table. */ + const q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + const q7_t * pSrcA, + const q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + const q7_t * pSrcA, + const q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + const float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + const q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + const q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + const q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + const q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + const q7_t * pSrcA, + const q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + const q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + const q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + const q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + const float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + const q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + const q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + const q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + const q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + const q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + const float32_t * pSrcA, + uint32_t srcALen, + const float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + const float32_t * pSrcA, + uint32_t srcALen, + const float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + const q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + const q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + +/** + @brief Instance structure for floating-point FIR decimator. + */ +typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + const float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + +/** + @brief Processing function for floating-point FIR decimator. + @param[in] S points to an instance of the floating-point FIR decimator structure + @param[in] pSrc points to the block of input data + @param[out] pDst points to the block of output data + @param[in] blockSize number of samples to process + */ +void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + +/** + @brief Initialization function for the floating-point FIR decimator. + @param[in,out] S points to an instance of the floating-point FIR decimator structure + @param[in] numTaps number of coefficients in the filter + @param[in] M decimation factor + @param[in] pCoeffs points to the filter coefficients + @param[in] pState points to the state buffer + @param[in] blockSize number of input samples to process per call + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_LENGTH_ERROR : blockSize is not a multiple of M + */ +arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + const float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + const q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + const arm_fir_decimate_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + const q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + const q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + const q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + const float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + const q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + const q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + const float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + const q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + const q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + const float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + const float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + const float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + const float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + +#if defined(ARM_MATH_NEON) +void arm_biquad_cascade_df2T_compute_coefs_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs); +#endif + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + const float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + const float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + const float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + const q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + const q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + const float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + const q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + const q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + const float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + const float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + const q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + const q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + const float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + const q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + const q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + const q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + const q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + const float32_t * pSrcA, + uint32_t srcALen, + const float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + +/** + @brief Correlation of Q15 sequences + @param[in] pSrcA points to the first input sequence + @param[in] srcALen length of the first input sequence + @param[in] pSrcB points to the second input sequence + @param[in] srcBLen length of the second input sequence + @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. +*/ +void arm_correlate_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + +/** + @brief Correlation of Q15 sequences. + @param[in] pSrcA points to the first input sequence + @param[in] srcALen length of the first input sequence + @param[in] pSrcB points to the second input sequence + @param[in] srcBLen length of the second input sequence + @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + +/** + @brief Correlation of Q15 sequences (fast version). + @param[in] pSrcA points to the first input sequence + @param[in] srcALen length of the first input sequence + @param[in] pSrcB points to the second input sequence + @param[in] srcBLen length of the second input sequence + @param[out] pDst points to the location where the output result is written. Length 2 * max(srcALen, srcBLen) - 1. + @return none + */ +void arm_correlate_fast_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + +/** + @brief Correlation of Q15 sequences (fast version). + @param[in] pSrcA points to the first input sequence. + @param[in] srcALen length of the first input sequence. + @param[in] pSrcB points to the second input sequence. + @param[in] srcBLen length of the second input sequence. + @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ +void arm_correlate_fast_opt_q15( + const q15_t * pSrcA, + uint32_t srcALen, + const q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + +/** + @brief Correlation of Q31 sequences (fast version). + @param[in] pSrcA points to the first input sequence + @param[in] srcALen length of the first input sequence + @param[in] pSrcB points to the second input sequence + @param[in] srcBLen length of the second input sequence + @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ +void arm_correlate_fast_q31( + const q31_t * pSrcA, + uint32_t srcALen, + const q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + const q7_t * pSrcA, + uint32_t srcALen, + const q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + const float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + const q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + const q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + const q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + const float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + const float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + const q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + const q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + const q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + const q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd
+   * 
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return processed output sample. + */ + __STATIC_FORCEINLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + +/** + @brief Process function for the Q31 PID Control. + @param[in,out] S points to an instance of the Q31 PID Control structure + @param[in] in input sample to process + @return processed output sample. + + \par Scaling and Overflow Behavior + The function is implemented using an internal 64-bit accumulator. + The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + Thus, if the accumulator result overflows it wraps around rather than clip. + In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ +__STATIC_FORCEINLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31U); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + +/** + @brief Process function for the Q15 PID Control. + @param[in,out] S points to an instance of the Q15 PID Control structure + @param[in] in input sample to process + @return processed output sample. + + \par Scaling and Overflow Behavior + The function is implemented using a 64-bit internal accumulator. + Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ +__STATIC_FORCEINLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#if defined (ARM_MATH_DSP) + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)read_q15x2 (S->state), (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((q31_t)(acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @return none + */ + __STATIC_FORCEINLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + +/** + @brief Clarke transform for Q31 version + @param[in] Ia input three-phase coordinate a + @param[in] Ib input three-phase coordinate b + @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + @param[out] pIbeta points to output two-phase orthogonal vector axis beta + @return none + + \par Scaling and Overflow Behavior + The function is implemented using an internal 32-bit accumulator. + The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + There is saturation on the addition, hence there is no risk of overflow. + */ +__STATIC_FORCEINLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * @return none + */ + __STATIC_FORCEINLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + +/** + @brief Inverse Clarke transform for Q31 version + @param[in] Ialpha input two-phase orthogonal vector axis alpha + @param[in] Ibeta input two-phase orthogonal vector axis beta + @param[out] pIa points to output three-phase coordinate a + @param[out] pIb points to output three-phase coordinate b + @return none + + \par Scaling and Overflow Behavior + The function is implemented using an internal 32-bit accumulator. + The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + There is saturation on the subtraction, hence there is no risk of overflow. + */ +__STATIC_FORCEINLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * @return none + * + * The function implements the forward Park transform. + * + */ + __STATIC_FORCEINLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + +/** + @brief Park transform for Q31 version + @param[in] Ialpha input two-phase vector coordinate alpha + @param[in] Ibeta input two-phase vector coordinate beta + @param[out] pId points to output rotor reference frame d + @param[out] pIq points to output rotor reference frame q + @param[in] sinVal sine value of rotation angle theta + @param[in] cosVal cosine value of rotation angle theta + @return none + + \par Scaling and Overflow Behavior + The function is implemented using an internal 32-bit accumulator. + The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ +__STATIC_FORCEINLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * @return none + */ + __STATIC_FORCEINLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + +/** + @brief Inverse Park transform for Q31 version + @param[in] Id input coordinate of rotor reference frame d + @param[in] Iq input coordinate of rotor reference frame q + @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + @param[out] pIbeta points to output two-phase orthogonal vector axis beta + @param[in] sinVal sine value of rotation angle theta + @param[in] cosVal cosine value of rotation angle theta + @return none + + @par Scaling and Overflow Behavior + The function is implemented using an internal 32-bit accumulator. + The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + There is saturation on the addition, hence there is no risk of overflow. + */ +__STATIC_FORCEINLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + __STATIC_FORCEINLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if (i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if ((uint32_t)i >= (S->nValues - 1)) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + __STATIC_FORCEINLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1U); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + __STATIC_FORCEINLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + __STATIC_FORCEINLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if (index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + +/** + @brief Floating-point vector of log values. + @param[in] pSrc points to the input vector + @param[out] pDst points to the output vector + @param[in] blockSize number of samples in each vector + @return none + */ + void arm_vlog_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + +/** + @brief Floating-point vector of exp values. + @param[in] pSrc points to the input vector + @param[out] pDst points to the output vector + @param[in] blockSize number of samples in each vector + @return none + */ + void arm_vexp_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + +/** + @brief Floating-point square root function. + @param[in] in input value + @param[out] pOut square root of input value + @return execution status + - \ref ARM_MATH_SUCCESS : input value is positive + - \ref ARM_MATH_ARGUMENT_ERROR : input value is negative; *pOut is set to 0 + */ +__STATIC_FORCEINLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if (in >= 0.0f) + { +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + *pOut = __sqrtf(in); + #else + *pOut = sqrtf(in); + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); + #else + *pOut = sqrtf(in); + #endif + +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + +/** + @brief Q31 square root function. + @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF + @param[out] pOut points to square root of input value + @return execution status + - \ref ARM_MATH_SUCCESS : input value is positive + - \ref ARM_MATH_ARGUMENT_ERROR : input value is negative; *pOut is set to 0 + */ +arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + +/** + @brief Q15 square root function. + @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF + @param[out] pOut points to square root of input value + @return execution status + - \ref ARM_MATH_SUCCESS : input value is positive + - \ref ARM_MATH_ARGUMENT_ERROR : input value is negative; *pOut is set to 0 + */ +arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @brief Vector Floating-point square root function. + * @param[in] pIn input vector. + * @param[out] pOut vector of square roots of input elements. + * @param[in] len length of input vector. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + void arm_vsqrt_f32( + float32_t * pIn, + float32_t * pOut, + uint16_t len); + + void arm_vsqrt_q31( + q31_t * pIn, + q31_t * pOut, + uint16_t len); + + void arm_vsqrt_q15( + q15_t * pIn, + q15_t * pOut, + uint16_t len); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + __STATIC_FORCEINLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + __STATIC_FORCEINLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t rOffset; + int32_t* dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = dst_base + dst_length; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + __STATIC_FORCEINLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + __STATIC_FORCEINLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset; + q15_t* dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = dst_base + dst_length; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + __STATIC_FORCEINLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + __STATIC_FORCEINLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset; + q7_t* dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = dst_base + dst_length; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + const q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + const q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + const q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + const q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + const float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + const q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + const q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + const q15_t * pSrcCmplx, + const q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + const q31_t * pSrcCmplx, + const q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + const float32_t * pSrcCmplx, + const float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + const q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + const q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + const q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + const q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + const float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + /** + @brief Maximum value of a floating-point vector. + @param[in] pSrc points to the input vector + @param[in] blockSize number of samples in input vector + @param[out] pResult maximum value returned here + @return none + */ + void arm_max_no_idx_f32( + const float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + const q15_t * pSrcA, + const q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + const q31_t * pSrcA, + const q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + const float32_t * pSrcA, + const float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + const float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + const float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + const float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + const q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + const q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + const q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + const q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + const q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + const q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + const q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + const q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + const q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + +/** + * @brief Struct for specifying SVM Kernel + */ +typedef enum +{ + ARM_ML_KERNEL_LINEAR = 0, + /**< Linear kernel */ + ARM_ML_KERNEL_POLYNOMIAL = 1, + /**< Polynomial kernel */ + ARM_ML_KERNEL_RBF = 2, + /**< Radial Basis Function kernel */ + ARM_ML_KERNEL_SIGMOID = 3 + /**< Sigmoid kernel */ +} arm_ml_kernel_type; + + +/** + * @brief Instance structure for linear SVM prediction function. + */ +typedef struct +{ + uint32_t nbOfSupportVectors; /**< Number of support vectors */ + uint32_t vectorDimension; /**< Dimension of vector space */ + float32_t intercept; /**< Intercept */ + const float32_t *dualCoefficients; /**< Dual coefficients */ + const float32_t *supportVectors; /**< Support vectors */ + const int32_t *classes; /**< The two SVM classes */ +} arm_svm_linear_instance_f32; + + +/** + * @brief Instance structure for polynomial SVM prediction function. + */ +typedef struct +{ + uint32_t nbOfSupportVectors; /**< Number of support vectors */ + uint32_t vectorDimension; /**< Dimension of vector space */ + float32_t intercept; /**< Intercept */ + const float32_t *dualCoefficients; /**< Dual coefficients */ + const float32_t *supportVectors; /**< Support vectors */ + const int32_t *classes; /**< The two SVM classes */ + int32_t degree; /**< Polynomial degree */ + float32_t coef0; /**< Polynomial constant */ + float32_t gamma; /**< Gamma factor */ +} arm_svm_polynomial_instance_f32; + +/** + * @brief Instance structure for rbf SVM prediction function. + */ +typedef struct +{ + uint32_t nbOfSupportVectors; /**< Number of support vectors */ + uint32_t vectorDimension; /**< Dimension of vector space */ + float32_t intercept; /**< Intercept */ + const float32_t *dualCoefficients; /**< Dual coefficients */ + const float32_t *supportVectors; /**< Support vectors */ + const int32_t *classes; /**< The two SVM classes */ + float32_t gamma; /**< Gamma factor */ +} arm_svm_rbf_instance_f32; + +/** + * @brief Instance structure for sigmoid SVM prediction function. + */ +typedef struct +{ + uint32_t nbOfSupportVectors; /**< Number of support vectors */ + uint32_t vectorDimension; /**< Dimension of vector space */ + float32_t intercept; /**< Intercept */ + const float32_t *dualCoefficients; /**< Dual coefficients */ + const float32_t *supportVectors; /**< Support vectors */ + const int32_t *classes; /**< The two SVM classes */ + float32_t coef0; /**< Independant constant */ + float32_t gamma; /**< Gamma factor */ +} arm_svm_sigmoid_instance_f32; + +/** + * @brief SVM linear instance init function + * @param[in] S Parameters for SVM functions + * @param[in] nbOfSupportVectors Number of support vectors + * @param[in] vectorDimension Dimension of vector space + * @param[in] intercept Intercept + * @param[in] dualCoefficients Array of dual coefficients + * @param[in] supportVectors Array of support vectors + * @param[in] classes Array of 2 classes ID + * @return none. + * + */ + + +void arm_svm_linear_init_f32(arm_svm_linear_instance_f32 *S, + uint32_t nbOfSupportVectors, + uint32_t vectorDimension, + float32_t intercept, + const float32_t *dualCoefficients, + const float32_t *supportVectors, + const int32_t *classes); + +/** + * @brief SVM linear prediction + * @param[in] S Pointer to an instance of the linear SVM structure. + * @param[in] in Pointer to input vector + * @param[out] pResult Decision value + * @return none. + * + */ + +void arm_svm_linear_predict_f32(const arm_svm_linear_instance_f32 *S, + const float32_t * in, + int32_t * pResult); + + +/** + * @brief SVM polynomial instance init function + * @param[in] S points to an instance of the polynomial SVM structure. + * @param[in] nbOfSupportVectors Number of support vectors + * @param[in] vectorDimension Dimension of vector space + * @param[in] intercept Intercept + * @param[in] dualCoefficients Array of dual coefficients + * @param[in] supportVectors Array of support vectors + * @param[in] classes Array of 2 classes ID + * @param[in] degree Polynomial degree + * @param[in] coef0 coeff0 (scikit-learn terminology) + * @param[in] gamma gamma (scikit-learn terminology) + * @return none. + * + */ + + +void arm_svm_polynomial_init_f32(arm_svm_polynomial_instance_f32 *S, + uint32_t nbOfSupportVectors, + uint32_t vectorDimension, + float32_t intercept, + const float32_t *dualCoefficients, + const float32_t *supportVectors, + const int32_t *classes, + int32_t degree, + float32_t coef0, + float32_t gamma + ); + +/** + * @brief SVM polynomial prediction + * @param[in] S Pointer to an instance of the polynomial SVM structure. + * @param[in] in Pointer to input vector + * @param[out] pResult Decision value + * @return none. + * + */ +void arm_svm_polynomial_predict_f32(const arm_svm_polynomial_instance_f32 *S, + const float32_t * in, + int32_t * pResult); + + +/** + * @brief SVM radial basis function instance init function + * @param[in] S points to an instance of the polynomial SVM structure. + * @param[in] nbOfSupportVectors Number of support vectors + * @param[in] vectorDimension Dimension of vector space + * @param[in] intercept Intercept + * @param[in] dualCoefficients Array of dual coefficients + * @param[in] supportVectors Array of support vectors + * @param[in] classes Array of 2 classes ID + * @param[in] gamma gamma (scikit-learn terminology) + * @return none. + * + */ + +void arm_svm_rbf_init_f32(arm_svm_rbf_instance_f32 *S, + uint32_t nbOfSupportVectors, + uint32_t vectorDimension, + float32_t intercept, + const float32_t *dualCoefficients, + const float32_t *supportVectors, + const int32_t *classes, + float32_t gamma + ); + +/** + * @brief SVM rbf prediction + * @param[in] S Pointer to an instance of the rbf SVM structure. + * @param[in] in Pointer to input vector + * @param[out] pResult decision value + * @return none. + * + */ +void arm_svm_rbf_predict_f32(const arm_svm_rbf_instance_f32 *S, + const float32_t * in, + int32_t * pResult); + +/** + * @brief SVM sigmoid instance init function + * @param[in] S points to an instance of the rbf SVM structure. + * @param[in] nbOfSupportVectors Number of support vectors + * @param[in] vectorDimension Dimension of vector space + * @param[in] intercept Intercept + * @param[in] dualCoefficients Array of dual coefficients + * @param[in] supportVectors Array of support vectors + * @param[in] classes Array of 2 classes ID + * @param[in] coef0 coeff0 (scikit-learn terminology) + * @param[in] gamma gamma (scikit-learn terminology) + * @return none. + * + */ + +void arm_svm_sigmoid_init_f32(arm_svm_sigmoid_instance_f32 *S, + uint32_t nbOfSupportVectors, + uint32_t vectorDimension, + float32_t intercept, + const float32_t *dualCoefficients, + const float32_t *supportVectors, + const int32_t *classes, + float32_t coef0, + float32_t gamma + ); + +/** + * @brief SVM sigmoid prediction + * @param[in] S Pointer to an instance of the rbf SVM structure. + * @param[in] in Pointer to input vector + * @param[out] pResult Decision value + * @return none. + * + */ +void arm_svm_sigmoid_predict_f32(const arm_svm_sigmoid_instance_f32 *S, + const float32_t * in, + int32_t * pResult); + + + +/** + * @brief Instance structure for Naive Gaussian Bayesian estimator. + */ +typedef struct +{ + uint32_t vectorDimension; /**< Dimension of vector space */ + uint32_t numberOfClasses; /**< Number of different classes */ + const float32_t *theta; /**< Mean values for the Gaussians */ + const float32_t *sigma; /**< Variances for the Gaussians */ + const float32_t *classPriors; /**< Class prior probabilities */ + float32_t epsilon; /**< Additive value to variances */ +} arm_gaussian_naive_bayes_instance_f32; + +/** + * @brief Naive Gaussian Bayesian Estimator + * + * @param[in] S points to a naive bayes instance structure + * @param[in] in points to the elements of the input vector. + * @param[in] pBuffer points to a buffer of length numberOfClasses + * @return The predicted class + * + */ + + +uint32_t arm_gaussian_naive_bayes_predict_f32(const arm_gaussian_naive_bayes_instance_f32 *S, + const float32_t * in, + float32_t *pBuffer); + +/** + * @brief Computation of the LogSumExp + * + * In probabilistic computations, the dynamic of the probability values can be very + * wide because they come from gaussian functions. + * To avoid underflow and overflow issues, the values are represented by their log. + * In this representation, multiplying the original exp values is easy : their logs are added. + * But adding the original exp values is requiring some special handling and it is the + * goal of the LogSumExp function. + * + * If the values are x1...xn, the function is computing: + * + * ln(exp(x1) + ... + exp(xn)) and the computation is done in such a way that + * rounding issues are minimised. + * + * The max xm of the values is extracted and the function is computing: + * xm + ln(exp(x1 - xm) + ... + exp(xn - xm)) + * + * @param[in] *in Pointer to an array of input values. + * @param[in] blockSize Number of samples in the input array. + * @return LogSumExp + * + */ + + +float32_t arm_logsumexp_f32(const float32_t *in, uint32_t blockSize); + +/** + * @brief Dot product with log arithmetic + * + * Vectors are containing the log of the samples + * + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[in] pTmpBuffer temporary buffer of length blockSize + * @return The log of the dot product . + * + */ + + +float32_t arm_logsumexp_dot_prod_f32(const float32_t * pSrcA, + const float32_t * pSrcB, + uint32_t blockSize, + float32_t *pTmpBuffer); + +/** + * @brief Entropy + * + * @param[in] pSrcA Array of input values. + * @param[in] blockSize Number of samples in the input array. + * @return Entropy -Sum(p ln p) + * + */ + + +float32_t arm_entropy_f32(const float32_t * pSrcA,uint32_t blockSize); + + +/** + * @brief Entropy + * + * @param[in] pSrcA Array of input values. + * @param[in] blockSize Number of samples in the input array. + * @return Entropy -Sum(p ln p) + * + */ + + +float64_t arm_entropy_f64(const float64_t * pSrcA, uint32_t blockSize); + + +/** + * @brief Kullback-Leibler + * + * @param[in] pSrcA Pointer to an array of input values for probability distribution A. + * @param[in] pSrcB Pointer to an array of input values for probability distribution B. + * @param[in] blockSize Number of samples in the input array. + * @return Kullback-Leibler Divergence D(A || B) + * + */ +float32_t arm_kullback_leibler_f32(const float32_t * pSrcA + ,const float32_t * pSrcB + ,uint32_t blockSize); + + +/** + * @brief Kullback-Leibler + * + * @param[in] pSrcA Pointer to an array of input values for probability distribution A. + * @param[in] pSrcB Pointer to an array of input values for probability distribution B. + * @param[in] blockSize Number of samples in the input array. + * @return Kullback-Leibler Divergence D(A || B) + * + */ +float64_t arm_kullback_leibler_f64(const float64_t * pSrcA, + const float64_t * pSrcB, + uint32_t blockSize); + + +/** + * @brief Weighted sum + * + * + * @param[in] *in Array of input values. + * @param[in] *weigths Weights + * @param[in] blockSize Number of samples in the input array. + * @return Weighted sum + * + */ +float32_t arm_weighted_sum_f32(const float32_t *in + , const float32_t *weigths + , uint32_t blockSize); + + +/** + * @brief Barycenter + * + * + * @param[in] in List of vectors + * @param[in] weights Weights of the vectors + * @param[out] out Barycenter + * @param[in] nbVectors Number of vectors + * @param[in] vecDim Dimension of space (vector dimension) + * @return None + * + */ +void arm_barycenter_f32(const float32_t *in + , const float32_t *weights + , float32_t *out + , uint32_t nbVectors + , uint32_t vecDim); + +/** + * @brief Euclidean distance between two vectors + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ + +float32_t arm_euclidean_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + +/** + * @brief Bray-Curtis distance between two vectors + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ +float32_t arm_braycurtis_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + +/** + * @brief Canberra distance between two vectors + * + * This function may divide by zero when samples pA[i] and pB[i] are both zero. + * The result of the computation will be correct. So the division per zero may be + * ignored. + * + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ +float32_t arm_canberra_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + + +/** + * @brief Chebyshev distance between two vectors + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ +float32_t arm_chebyshev_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + + +/** + * @brief Cityblock (Manhattan) distance between two vectors + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ +float32_t arm_cityblock_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + +/** + * @brief Correlation distance between two vectors + * + * The input vectors are modified in place ! + * + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ +float32_t arm_correlation_distance_f32(float32_t *pA,float32_t *pB, uint32_t blockSize); + +/** + * @brief Cosine distance between two vectors + * + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ + +float32_t arm_cosine_distance_f32(const float32_t *pA,const float32_t *pB, uint32_t blockSize); + +/** + * @brief Jensen-Shannon distance between two vectors + * + * This function is assuming that elements of second vector are > 0 + * and 0 only when the corresponding element of first vector is 0. + * Otherwise the result of the computation does not make sense + * and for speed reasons, the cases returning NaN or Infinity are not + * managed. + * + * When the function is computing x log (x / y) with x 0 and y 0, + * it will compute the right value (0) but a division per zero will occur + * and shoudl be ignored in client code. + * + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] blockSize vector length + * @return distance + * + */ + +float32_t arm_jensenshannon_distance_f32(const float32_t *pA,const float32_t *pB,uint32_t blockSize); + +/** + * @brief Minkowski distance between two vectors + * + * @param[in] pA First vector + * @param[in] pB Second vector + * @param[in] n Norm order (>= 2) + * @param[in] blockSize vector length + * @return distance + * + */ + + + +float32_t arm_minkowski_distance_f32(const float32_t *pA,const float32_t *pB, int32_t order, uint32_t blockSize); + +/** + * @brief Dice distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] order Distance order + * @param[in] blockSize Number of samples + * @return distance + * + */ + + +float32_t arm_dice_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Hamming distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_hamming_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Jaccard distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_jaccard_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Kulsinski distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_kulsinski_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Roger Stanimoto distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_rogerstanimoto_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Russell-Rao distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_russellrao_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Sokal-Michener distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_sokalmichener_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Sokal-Sneath distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_sokalsneath_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + +/** + * @brief Yule distance between two vectors + * + * @param[in] pA First vector of packed booleans + * @param[in] pB Second vector of packed booleans + * @param[in] numberOfBools Number of booleans + * @return distance + * + */ + +float32_t arm_yule_distance(const uint32_t *pA, const uint32_t *pB, uint32_t numberOfBools); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + /** + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + __STATIC_FORCEINLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (xIndex < 0 || xIndex > (S->numCols - 2) || yIndex < 0 || yIndex > (S->numRows - 2)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex ) + (yIndex ) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex ) + (yIndex+1) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + __STATIC_FORCEINLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numCols - 2) || cI < 0 || cI > (S->numRows - 2)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11U; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11U; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + __STATIC_FORCEINLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numCols - 2) || cI < 0 || cI > (S->numRows - 2)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0x0FFFFF - xfract)) >> 4U); + acc = ((q63_t) out * (0x0FFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0x0FFFFF - yfract)) >> 4U); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0x0FFFFF - xfract)) >> 4U); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4U); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + __STATIC_FORCEINLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numCols - 2) || cI < 0 || cI > (S->numRows - 2)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( __ARM_ARCH_7EM__ ) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined ( __ARM_ARCH_7EM__ ) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined (__ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __GNUC__ ) + #define LOW_OPTIMIZATION_ENTER \ + __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __ICCARM__ ) + /* Enter low optimization region - place directly above function definition */ + #if defined ( __ARM_ARCH_7EM__ ) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined ( __ARM_ARCH_7EM__ ) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TI_ARM__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __CSMC__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TASKING__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( _MSC_VER ) || defined(__GNUC_PYTHON__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#endif + + + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) +#pragma GCC diagnostic pop + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#elif defined ( _MSC_VER ) + +#else + #error Unknown compiler +#endif + +#ifdef __cplusplus +} +#endif + + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/Middlewares/ST/ARM/DSP/Lib/arm_ARMv8MMLlfsp_math.lib b/Middlewares/ST/ARM/DSP/Lib/arm_ARMv8MMLlfsp_math.lib new file mode 100644 index 0000000000000000000000000000000000000000..e6a10ab7faf7ebf85ee5d764ea7c2abe7e8105fb GIT binary patch literal 2669240 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Ν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