7.15. MATH
Overview
提供FFT接口使用示例和常见问题。
7.15.1. 应用示例
示例演示:
FFT和IFFT的使用
example: 进入 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_MATH_TEST_DEMO
。
Note
说明:
1.需增加依赖文件
代码文件 |
头文件 |
用途 |
---|---|---|
flfft_core_pi32v2.c |
/ |
浮点fft和ifft运算 |
jl_fft.c |
/ |
硬件fft接口 |
kiss_fft.c |
kiss_fft.h |
软件fft接口, jl_fft.c文件开启#define KISS_FFT宏使用软件加速 |
jl_math.c |
/ |
实现向量加减乘除, ASM_ENABLE == 1, 软件加速; ASM_ENABLE == 2, 汇编方式优化; ASM_ENABLE == 3, 硬件加速 |
nn_function_vec.c |
/ |
实现个位宽向量加减乘除, 如果数据放SDRAM性能会差, 不建议使用 |
driver/cpu/wl82/math/math.c(cpu.a) |
include_lib/driver/cpu/wl82/asm/math.h |
三角函数相关 |
7.15.2. 常见问题
7.15.3. API Reference
nn_function_vec.c
Note
加减法不支持 32 位和差溢出保护,需保证输入数据加减结果不大于 2147483647 或小于-2147483648。
实数乘加减,乘法部分运算完后会做饱和处理(最大 32 位)。
复数平方64位输出不做移位操作(/2^q),其余位宽均有做移位操作。
输出数据需满足 32bit 倍数,即 8bit 位宽至少 4 个,16bit 位宽至少 2 个,32bit 位宽至少 1 个。
- 各个vector函数的作用与参数说明:
注意: 某些函数需要打开特定宏才能使用, 如调用函数发现未定义, 检查特定宏是否打开.
/* --------------------------------------------------------------------------*/
/**
* @brief 两个二维实数数组的点乘累加
* @z[n] = sum(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为8bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 为单次运算长度(二维数组data[m *n] 对应的宽(m)
* @param [in] loop 循环次数, 对应高(n)
* @param [in] x_inc 每次循环的xptr地址增量, 由于xptr是8bit数据,所以增量为对应len,可根据实际情况修改
* @param [in] y_inc 每次循环的yptr地址增量, 由于yptr是8bit数据,所以增量为对应len,可根据实际情况修改
* @param [in] z_inc 每次循环的zptr地址增量, 由于xptr是32bit数据,且每次循环只得一个数据,所以增量为4,可根据实际情况修改
* @param [in] q zptr结果输出前除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_matrix_ys8_xs8(long *zptr, long *yptr, long *xptr, short len, short loop, short x_inc, short y_inc, short z_inc, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个二维实数数组的点乘累加
* @z[n] = sum(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为16bit数据
* @param [in] len 为单次运算长度(二维数组data[m *n] 对应的宽(m)
* @param [in] loop 循环次数, 对应高(n)
* @param [in] x_inc 每次循环的xptr地址增量, 由于xptr是16bit数据,所以增量为对应len*2,可根据实际情况修改
* @param [in] y_inc 每次循环的yptr地址增量, 由于yptr是32bit数据,所以增量为对应len*4,可根据实际情况修改
* @param [in] z_inc 每次循环的zptr地址增量, 由于xptr是32bit数据,且每次循环只得一个数据,所以增量为4,可根据实际情况修改
* @param [in] q zptr结果输出前除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_matrix_ys32_xs16(long *zptr, long *yptr, long *xptr, short len, short loop, short x_inc, short y_inc, short z_inc, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个二维实数数组的点乘累加
* @z[n] = sum(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 为单次运算长度(二维数组data[m *n] 对应的宽(m)
* @param [in] loop 循环次数, 对应高(n)
* @param [in] x_inc 每次循环的xptr地址增量, 由于xptr是8bit数据,所以增量为对应len,可根据实际情况修改
* @param [in] y_inc 每次循环的yptr地址增量, 由于yptr是32bit数据,所以增量为对应len*4,可根据实际情况修改
* @param [in] z_inc 每次循环的zptr地址增量, 由于xptr是32bit数据,且每次循环只得一个数据,所以增量为4,可根据实际情况修改
* @param [in] q zptr结果输出前除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_matrix_ys32_xs8(long *zptr, long *yptr, long *xptr, short len, short loop, short x_inc, short y_inc, short z_inc, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相加
* @z[n] = saturated( y[n] + x[n] ) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_add_xs32(void *zptr, void *yptr, void *xptr, short len);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相加
* @z[n] = saturated( y[n] + x[n] ) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为16bit数据
* @param [in] len 输入数据长度
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_add_xs16(void *zptr, void *yptr, void *xptr, short len);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相减
* @z[n] = saturated( y[n] - x[n] ) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据个数
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_sub_xs32(void *zptr, void *yptr, void *xptr, short len);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组乘一个常数
* @z[n] = (x[n] * const_dat/ 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q zptr结果输出前除于2^q
* @param [in] const_dat 输入常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_scale_s32(void *zptr, void *xptr, short len, char q, long const_dat);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_mul_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为16bit数据
* @param [in] xptr 输入为16bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys16_mul_xs16(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为16bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_mul_xs16(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_mul_xs8(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为8bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys8_mul_xs8(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组的相加除2^q
* @z[n] = sum(x[n]) / 2^q // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q 结果除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_sum_xs32(void *zptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组的乘常数除2^q
* @z[n] = (x[n] * const_dat/ 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为8bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q 结果除于2^q
* @param [in] const_dat 输入常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs8_x32_mul_const(void *zptr, void *xptr, short len, char q, long const_dat);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组的乘常数除2^q
* @z[n] = (x[n] * const_dat/ 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q 结果除于2^q
* @param [in] const_dat 输入常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_x32_mul_const(void *zptr, void *xptr, short len, char q, long const_dat);
}
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘
* @z[n] = x[n] + z[n] * const_dat / 2^q // 0 <= n < len
*
* @param [in/out] zptr 输入输出为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
* @param [in] const_dat 输入常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys32_mac_xs32(void *zptr, void *xptr, short len, char q, long const_dat);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维实数数组的相乘后相加,输出一个数
* @z[n] = sum(y[n] * x[n] / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据
* @param [in] yptr 输入为8bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_ys8_dot_product_xs8(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维复数数组的相加
* @z[n] = saturated( y[n] + x[n] ) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_add_xs32(void *zptr, void *yptr, void *xptr, short len);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维复数数组的相减
* @z[n] = saturated( y[n] - x[n] ) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_sub_xs32(void *zptr, void *yptr, void *xptr, short len);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维复数数组的点乘
* @z[n] = saturated(y[n]. * x[n]. / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为8bit数据
* @param [in] xptr 输入为8bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q 输出结果除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys8_mul_xs8(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief 两个一维复数数组的点乘除于2^q
* @z[n] = saturated(y[n]. * x[n]. / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q 输出结果除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_mul_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组先共轭除2^q后与yptr一位复数数组的点乘
* @z[n] = saturated(y[n]. * x[n]. / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_mul_conj_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组先共轭除2^q后与yptr一位复数数组的点乘
* @z[n] = saturated(y[n]. * x[n]. / 2^q) // 0 <= n < len
*
* @param [out] zptr 输出为64bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs64_ys32_mul_conj_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组实部虚部分别平方相加
* @z[n] = saturated((x[n].real^2 + x[n].imag^2) / 2^q) // 0 <= n < len/2
*
* @param [out] zptr 输出为64bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs64_qdt_xs32(void *zptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组实部虚部分别平方相加
* @z[n] = saturated((x[n].real^2 + x[n].imag^2) / 2^q) // 0 <= n < len/2
*
* @param [out] zptr 输出为32bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_qdt_xs32(void *zptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组除2^q后与yptr一位复数数组的点乘,后加上zptr
* @z[n] = saturated(z. + (y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_mac_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr一维复数数组先共轭除2^q后与yptr一位复数数组的点乘,后加上zptr
* @z[n] = saturated(z. + (y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_mac_conj_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief zptr 减去 xptr一维复数数组除2^q后与yptr一位复数数组的点乘
* @z[n] = saturated(z. - (y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
*
* @param [out] zptr 输出为32bit数据,可以是xptr或yptr
* @param [in] yptr 输入为32bit数据
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度(复数的个数)
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_complex_zs32_ys32_msc_xs32(void *zptr, void *yptr, void *xptr, short len, char q);
/* --------------------------------------------------------------------------*/
/**
* @brief xptr与常量比较取最大值后除2^q
* @z = x*cosnt /2^q
*
* @param [out] zptr 输出为32bit数据,可以是xptr
* @param [in] xptr 输入为32bit数据
* @param [in] len 输入数据长度
* @param [in] q xptr除于2^q
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_x32_max_scale(long *zptr, long *xptr, short len, char q, long const_dat);
/* --------------------------------------------------------------------------*/
/**
* @brief max_const与xptr中取最大值
* @x[n] =max( x[n], const)
*
* @param [in/out] xptr 输入输出为64bit数据
* @param [in] max_const 常数
* @param [in] len 输入数据长度
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs64_x64_max_scale(long long *xptr, long long max_const, long len);
/* --------------------------------------------------------------------------*/
/**
* @brief const_dat与xptr中取最小值
* @x[n] =min( x[n], const)
*
* @param [in/out] xptr 输入输出为32bit数据
* @param [in] min_const 常数
* @param [in] len 输入数据长度
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs32_x32_min_scale(long *zptr, long *xptr, short len, char q, long const_dat);
/* --------------------------------------------------------------------------*/
/**
* @brief min_const与xptr中取最小值
* @x[n] =min( x[n], const)
*
* @param [in/out] xptr 输入输出为64bit数据
* @param [in] min_const 常数
* @param [in] len 输入数据长度
*/
/* --------------------------------------------------------------------------*/
void vector_real_zs64_x64_min_scale(long long *xptr, long long min_const, long len);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组相减(zptr-xptr)乘lamda后除于2^q再加上xptr
* @z[n] =x[n] + ((z[n]- x[n])*lamda )/2^q
*
* @param [in/out] zptr 输入输出为64bit数据
* @param [in] xptr 输入为64bit数据
* @param [in] len 输入数据长度
* @param [in] q 常数
* @param [in] lamda 常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_smooth_zs64_xs64(long long *zptr, long long *xptr, unsigned long len, char q, long lamda);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维实数数组相减(zptr-xptr)乘lamda后除于2^q再加上xptr
* @z[n] =x[n] + ((z[n]- x[n])*lamda )/2^q
*
* @param [in/out] zptr 输入输出为32bit数据
* @param [in] xptr 输入为64bit数据
* @param [in] len 输入数据长度
* @param [in] q 常数
* @param [in] lamda 常数
*/
/* --------------------------------------------------------------------------*/
void vector_real_smooth_zs32_xs32(long *zptr, long *xptr, unsigned long len, char q, long lamda);
/* --------------------------------------------------------------------------*/
/**
* @brief 一维复数数组相减(zptr-xptr)乘lamda后除于2^q再加上xptr
* @z[n] =x[n] + ((z[n]- x[n])*lamda )/2^q
*
* @param [in/out] zptr 输入输出为32bit数据
* @param [in] xptr 输入为64bit数据
* @param [in] len 输入数据长度(复数长度)
* @param [in] q 常数
* @param [in] lamda 常数
*/
/* --------------------------------------------------------------------------*/
void vector_complex_smooth_zs32_xs32(long *zptr, long *xptr, unsigned long len, char q, long lamda);
//该函数暂时不能用
//=====================================
// z[0] = (x[0]^2 + x[1]^2)^0.5
// z[1] = (x[2]^2 + x[3]^2)^0.5
//...
// z[n] = (x[2*n]^2 + x[2*n+1]^2)^0.5
// result effective precision : 22bit
//=====================================
void complex_abs_s32(unsigned long *zptr, long *xptr, unsigned long len);