7.16. MATH

Overview

提供FFT接口使用示例和常见问题。

7.16.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.16.2. 常见问题

7.16.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);