CMSIS-DSP lib 矩阵运算示例和源码

Matrix interface

Matrix Initialization

初始化底层矩阵数据结构。 这些函数设置矩阵数据结构的 numRows、numCols 和 pData 字段。

/**
   @brief 浮点矩阵初始化。
   @param[in,out] S 指向浮点矩阵结构的一个实例
   @param[in] nRows 矩阵中的行数
   @param[in] nColumns 矩阵中的列数
   @param[in] pData 指向矩阵数据数组
   @return 无
*/

void 	arm_mat_init_f16 (arm_matrix_instance_f16 *S, uint16_t nRows, uint16_t nColumns, float16_t *pData)
 
void 	arm_mat_init_f32 (arm_matrix_instance_f32 *S, uint16_t nRows, uint16_t nColumns, float32_t *pData)
 
void 	arm_mat_init_q15 (arm_matrix_instance_q15 *S, uint16_t nRows, uint16_t nColumns, q15_t *pData)
 
void 	arm_mat_init_q31 (arm_matrix_instance_q31 *S, uint16_t nRows, uint16_t nColumns, q31_t *pData)

Matrix Addition

在这里插入图片描述

/**
 @brief         Floating-point matrix addition.
 @param[in]     pSrcA      指向第一个输入矩阵结构
 @param[in]     pSrcB      指向第二个输入矩阵结构
 @param[out]    pDst       指向输出矩阵结构
 @return        execution status
                   - \ref ARM_MATH_SUCCESS       : successful
                   - \ref ARM_MATH_SIZE_MISMATCH : 矩阵尺寸检查失败
*/
arm_status arm_mat_add_f16	(const arm_matrix_instance_f16 * pSrcA,
const arm_matrix_instance_f16 * pSrcB,
arm_matrix_instance_f16 * pDst);
    
arm_status arm_mat_add_f32(const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst);

arm_status arm_mat_add_q15(const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst);
    

arm_status arm_mat_add_q31(const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);

Matrix Subtraction

在这里插入图片描述

/**
   @brief 浮点矩阵减法。
   @param[in] pSrcA 指向第一个输入矩阵结构
   @param[in] pSrcB 指向第二个输入矩阵结构
   @param[out] pDst 指向输出矩阵结构
   @return 执行状态
                    - \ref ARM_MATH_SUCCESS : 操作成功
                    - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
  */

arm_status 	arm_mat_sub_f16 (const arm_matrix_instance_f16 *pSrcA, const arm_matrix_instance_f16 *pSrcB, arm_matrix_instance_f16 *pDst)
    
arm_status 	arm_mat_sub_f32 (const arm_matrix_instance_f32 *pSrcA, const arm_matrix_instance_f32 *pSrcB, arm_matrix_instance_f32 *pDst)
 
arm_status 	arm_mat_sub_f64 (const arm_matrix_instance_f64 *pSrcA, const arm_matrix_instance_f64 *pSrcB, arm_matrix_instance_f64 *pDst)
 
arm_status 	arm_mat_sub_q15 (const arm_matrix_instance_q15 *pSrcA, const arm_matrix_instance_q15 *pSrcB, arm_matrix_instance_q15 *pDst)
 
arm_status 	arm_mat_sub_q31 (const arm_matrix_instance_q31 *pSrcA, const arm_matrix_instance_q31 *pSrcB, arm_matrix_instance_q31 *pDst)

Matrix Multiplication

在这里插入图片描述

/**
  * @brief 浮点矩阵乘法。
  * @param[in] *pSrcA 指向第一个输入矩阵结构
  * @param[in] *pSrcB 指向第二个输入矩阵结构
  * @param[out] *pDst 指向输出矩阵结构
  * @return 函数返回任一
  * <code>ARM_MATH_SIZE_MISMATCH</code> 或 <code>ARM_MATH_SUCCESS</code> 基于大小检查的结果。
  */

arm_status 	arm_mat_mult_f16 (const arm_matrix_instance_f16 *pSrcA, const arm_matrix_instance_f16 *pSrcB, arm_matrix_instance_f16 *pDst)

arm_status 	arm_mat_mult_f32 (const arm_matrix_instance_f32 *pSrcA, const arm_matrix_instance_f32 *pSrcB, arm_matrix_instance_f32 *pDst)

arm_status 	arm_mat_mult_f64 (const arm_matrix_instance_f64 *pSrcA, const arm_matrix_instance_f64 *pSrcB, arm_matrix_instance_f64 *pDst)
 
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)
 
arm_status 	arm_mat_mult_fast_q31 (const arm_matrix_instance_q31 *pSrcA, const arm_matrix_instance_q31 *pSrcB, arm_matrix_instance_q31 *pDst)
 
arm_status 	arm_mat_mult_opt_q31 (const arm_matrix_instance_q31 *pSrcA, const arm_matrix_instance_q31 *pSrcB, arm_matrix_instance_q31 *pDst, q31_t *pState)
 
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)

arm_status 	arm_mat_mult_q31 (const arm_matrix_instance_q31 *pSrcA, const arm_matrix_instance_q31 *pSrcB, arm_matrix_instance_q31 *pDst)
 
arm_status 	arm_mat_mult_q7 (const arm_matrix_instance_q7 *pSrcA, const arm_matrix_instance_q7 *pSrcB, arm_matrix_instance_q7 *pDst, q7_t *pState)

Complex Matrix Multiplication

只有当第一个矩阵的列数等于第二个矩阵的行数时,才定义复矩阵乘法。 将 M x N 矩阵与 N x P 矩阵相乘得到 M x P 矩阵。

/**
  * @brief 浮点矩阵乘法。
  * @param[in] *pSrcA 指向第一个输入矩阵结构
  * @param[in] *pSrcB 指向第二个输入矩阵结构
  * @param[out] *pDst 指向输出矩阵结构
  * @return 函数返回任一
  * <code>ARM_MATH_SIZE_MISMATCH</code> 或 <code>ARM_MATH_SUCCESS</code> 基于大小检查的结果。
*/
arm_status 	arm_mat_cmplx_mult_f16 (const arm_matrix_instance_f16 *pSrcA, const arm_matrix_instance_f16 *pSrcB, arm_matrix_instance_f16 *pDst);

arm_status 	arm_mat_cmplx_mult_f32 (const arm_matrix_instance_f32 *pSrcA, const arm_matrix_instance_f32 *pSrcB, arm_matrix_instance_f32 *pDst);

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

arm_status 	arm_mat_cmplx_mult_q31 (const arm_matrix_instance_q31 *pSrcA, const arm_matrix_instance_q31 *pSrcB, arm_matrix_instance_q31 *pDst);

Matrix Vector Multiplication

将矩阵和向量相乘。

/**
  * @brief 浮点矩阵和向量乘法。
  * @param[in] *pSrcMat 指向输入矩阵结构
  * @param[in] *pVec 指向输入向量
  * @param[out] *pDst 指向输出向量
  */
void 	arm_mat_vec_mult_f16 (const arm_matrix_instance_f16 *pSrcMat, const float16_t *pVec, float16_t *pDst)
    
void 	arm_mat_vec_mult_f32 (const arm_matrix_instance_f32 *pSrcMat, const float32_t *pVec, float32_t *pDst)
 
void 	arm_mat_vec_mult_q15 (const arm_matrix_instance_q15 *pSrcMat, const q15_t *pVec, q15_t *pDst)
 
void 	arm_mat_vec_mult_q31 (const arm_matrix_instance_q31 *pSrcMat, const q31_t *pVec, q31_t *pDst)
 
void 	arm_mat_vec_mult_q7 (const arm_matrix_instance_q7 *pSrcMat, const q7_t *pVec, q7_t *pDst)

Matrix Scale

在这里插入图片描述


/**
   @brief 浮点矩阵缩放。
   @param[in] pSrc 指向输入矩阵
   @param[in] 要应用的比例比例因子
   @param[out] pDst 指向输出矩阵结构
   @return 执行状态
                    - \ref ARM_MATH_SUCCESS : 操作成功
                    - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
 */
arm_status 	arm_mat_scale_f16 (const arm_matrix_instance_f16 *pSrc, float16_t scale, arm_matrix_instance_f16 *pDst)
 
arm_status 	arm_mat_scale_f32 (const arm_matrix_instance_f32 *pSrc, float32_t scale, arm_matrix_instance_f32 *pDst)

/**
   @brief Q15 矩阵缩放。
   @param[in] pSrc 指向输入矩阵
   @param[in] scaleFract 比例因子的小数部分
   @param[in] 移位位数以将结果移位
   @param[out] pDst 指向输出矩阵结构
   @return 执行状态
                    - \ref ARM_MATH_SUCCESS : 操作成功
                    - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
  */

arm_status 	arm_mat_scale_q15 (const arm_matrix_instance_q15 *pSrc, q15_t scaleFract, int32_t shift, arm_matrix_instance_q15 *pDst)
 
arm_status 	arm_mat_scale_q31 (const arm_matrix_instance_q31 *pSrc, q31_t scaleFract, int32_t shift, arm_matrix_instance_q31 *pDst)

Matrix Transpose

在这里插入图片描述

/**
   @brief 浮点矩阵转置。
   @param[in] pSrc 指向输入矩阵
   @param[out] pDst 指向输出矩阵
   @return 执行状态
                    - \ref ARM_MATH_SUCCESS : 操作成功
                    - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
  */
arm_status 	arm_mat_trans_f16 (const arm_matrix_instance_f16 *pSrc, arm_matrix_instance_f16 *pDst)
    
arm_status 	arm_mat_trans_f32 (const arm_matrix_instance_f32 *pSrc, arm_matrix_instance_f32 *pDst)
 
arm_status 	arm_mat_trans_f64 (const arm_matrix_instance_f64 *pSrc, arm_matrix_instance_f64 *pDst)
 
arm_status 	arm_mat_trans_q15 (const arm_matrix_instance_q15 *pSrc, arm_matrix_instance_q15 *pDst)
 
arm_status 	arm_mat_trans_q31 (const arm_matrix_instance_q31 *pSrc, arm_matrix_instance_q31 *pDst)
 
arm_status 	arm_mat_trans_q7 (const arm_matrix_instance_q7 *pSrc, arm_matrix_instance_q7 *pDst)

Complex Matrix Transpose

在这里插入图片描述

/**
   @brief 浮点矩阵转置。
   @param[in] pSrc 指向输入矩阵
   @param[out] pDst 指向输出矩阵
   @return 执行状态
           - \ref ARM_MATH_SUCCESS : 操作成功
           - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
*/
arm_status 	arm_mat_cmplx_trans_f16 (const arm_matrix_instance_f16 *pSrc, arm_matrix_instance_f16 *pDst)
 
arm_status 	arm_mat_cmplx_trans_f32 (const arm_matrix_instance_f32 *pSrc, arm_matrix_instance_f32 *pDst)
 
arm_status 	arm_mat_cmplx_trans_q15 (const arm_matrix_instance_q15 *pSrc, arm_matrix_instance_q15 *pDst)
 
arm_status 	arm_mat_cmplx_trans_q31 (const arm_matrix_instance_q31 *pSrc, arm_matrix_instance_q31 *pDst)

Matrix Inverse

计算矩阵的逆。仅当输入矩阵是方阵且非奇异(行列式非零)时才定义逆矩阵。 该函数检查输入和输出矩阵是否为正方形且大小相同。矩阵求逆对数值敏感,CMSIS DSP 库仅支持浮点矩阵的矩阵求逆。

算法Gauss-Jordan 方法用于求逆。 该算法执行一系列基本的行操作,直到将输入矩阵简化为单位矩阵。 将相同的基本行操作序列应用于单位矩阵会产生逆矩阵。 如果输入矩阵是奇异的,则算法终止并返回错误状态 ARM_MATH_SINGULAR。
在这里插入图片描述

/**
   @brief 浮点矩阵逆。
   @param[in] pSrc 指向输入矩阵结构。 源矩阵由函数修改。
   @param[out] pDst 指向输出矩阵结构
   @return 执行状态
          - \ref ARM_MATH_SUCCESS : 操作成功
          - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
          - \ref ARM_MATH_SINGULAR : 输入矩阵被发现是奇异的(不可逆的)
 */
arm_status 	arm_mat_inverse_f16 (const arm_matrix_instance_f16 *pSrc, arm_matrix_instance_f16 *pDst)
 
arm_status 	arm_mat_inverse_f32 (const arm_matrix_instance_f32 *pSrc, arm_matrix_instance_f32 *pDst)
 
arm_status 	arm_mat_inverse_f64 (const arm_matrix_instance_f64 *pSrc, arm_matrix_instance_f64 *pDst)
//针对上下三角的特殊运算
参数
[in] ut 上三角矩阵
[in] a 矩阵 a
[out] dst UT 的解 X。 X = 一个
退货

/**
   @brief 浮点矩阵逆。
   @param[in] ut 上三角矩阵
   @param[out] a 矩阵 a
   @param[out] dst 指向输出矩阵结构
   @return 执行状态
			如果系统无法求解,该函数返回 ARM_MATH_SINGULAR。
 */
arm_status 	arm_mat_solve_lower_triangular_f16 (const arm_matrix_instance_f16 *lt, const arm_matrix_instance_f16 *a, arm_matrix_instance_f16 *dst)

arm_status 	arm_mat_solve_lower_triangular_f32 (const arm_matrix_instance_f32 *lt, const arm_matrix_instance_f32 *a, arm_matrix_instance_f32 *dst)
 
arm_status 	arm_mat_solve_lower_triangular_f64 (const arm_matrix_instance_f64 *lt, const arm_matrix_instance_f64 *a, arm_matrix_instance_f64 *dst)
 
arm_status 	arm_mat_solve_upper_triangular_f16 (const arm_matrix_instance_f16 *ut, const arm_matrix_instance_f16 *a, arm_matrix_instance_f16 *dst)
 
arm_status 	arm_mat_solve_upper_triangular_f32 (const arm_matrix_instance_f32 *ut, const arm_matrix_instance_f32 *a, arm_matrix_instance_f32 *dst)
 
arm_status 	arm_mat_solve_upper_triangular_f64 (const arm_matrix_instance_f64 *ut, const arm_matrix_instance_f64 *a, arm_matrix_instance_f64 *dst)
 	

Cholesky and LDLT decompositions

计算矩阵的 Cholesky 或$LDLT 分解。

如果输入矩阵没有分解,则算法终止并返回错误状态 ARM_MATH_DECOMPOSITION_FAILURE。

/**
* @brief 正定矩阵的浮点 Cholesky 分解。
* @param[in] pSrc 指向输入浮点矩阵结构的实例。
* @param[out] pDst 指向输出浮点矩阵结构的实例。
* @return 如果维度不匹配,该函数返回 ARM_MATH_SIZE_MISMATCH。
* @return 执行状态
            - \ref ARM_MATH_SUCCESS : 操作成功
            - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
            - \ref ARM_MATH_DECOMPOSITION_FAILURE : 输入矩阵不能被分解
* 如果矩阵是病态的或只是半定的,那么最好使用 LDL^t 分解。
* A 的分解返回一个下三角矩阵 U,使得 A = U*U^t
*/
arm_status 	arm_mat_cholesky_f16 (const arm_matrix_instance_f16 *pSrc, arm_matrix_instance_f16 *pDst)
 
arm_status 	arm_mat_cholesky_f32 (const arm_matrix_instance_f32 *pSrc, arm_matrix_instance_f32 *pDst)

arm_status 	arm_mat_cholesky_f64 (const arm_matrix_instance_f64 *pSrc, arm_matrix_instance_f64 *pDst)
/**
* @brief 正半定矩阵的浮点 LDL^t 分解。
* @param[in] pSrc 指向输入浮点矩阵结构的实例。
* @param[out] pl 指向输出浮点三角矩阵结构的实例。
* @param[out] pd 指向输出浮点对角矩阵结构的实例。
* @param[out] pp 指向输出浮点置换向量的实例。
* @return 如果维度不匹配,该函数返回 ARM_MATH_SIZE_MISMATCH。
* @return 执行状态
                    - \ref ARM_MATH_SUCCESS : 操作成功
                    - \ref ARM_MATH_SIZE_MISMATCH : 矩阵大小检查失败
                    - \ref ARM_MATH_DECOMPOSITION_FAILURE : 输入矩阵不能被分解
* 计算矩阵 A 的 LDL^t 分解,使得 PAP^t = LDL^t。
*/
arm_status 	arm_mat_ldlt_f32 (const arm_matrix_instance_f32 *pSrc, arm_matrix_instance_f32 *pl, arm_matrix_instance_f32 *pd, uint16_t *pp)
    
arm_status 	arm_mat_ldlt_f64 (const arm_matrix_instance_f64 *pSrc, arm_matrix_instance_f64 *pl, arm_matrix_instance_f64 *pd, uint16_t *pp)

Matrix Example

示例如何使用矩阵转置、矩阵乘法和矩阵逆函数将最小二乘拟合应用于输入数据。 最小二乘拟合是寻找最佳拟合曲线的过程,该曲线使给定数据集的偏移平方和(最小二乘误差)最小化。

考虑的参数的线性组合如下:
A ∗ X = B A*X = B AX=B,其中 X 是未知值,可以从 A 和 B 估计。
最小二乘估计 X 由以下等式给出:
X = I n v e r s e ( A T ∗ A ) ∗ A T ∗ B X = Inverse(A^T * A)* A^T * B X=InverseATAATB

代码来自:arm_matrix_example_f32.c (arm-software.github.io)

#include "arm_math.h"
#include "math_helper.h"
#if defined(SEMIHOSTING)
#include <stdio.h>
#endif
#define SNR_THRESHOLD   90

//A_f32 线性组合方程中的输入矩阵
//B_f32 线性组合方程中的输出矩阵
//使用 A_f32 和 B_f32 矩阵估计的 X_f32 未知矩阵

/* --------------------------------------------------------------------------------
* Test input data(Cycles) taken from FIR Q15 module for differant cases of blockSize
* and tapSize
* --------------------------------------------------------------------------------- */
const float32_t B_f32[4] =
{
	782.0, 7577.0, 470.0, 4505.0
};
/* --------------------------------------------------------------------------------
* Formula to fit is  C1 + C2 * numTaps + C3 * blockSize + C4 * numTaps * blockSize
* -------------------------------------------------------------------------------- */
const float32_t A_f32[16] =
{
  	/* Const,   numTaps,   blockSize,   numTaps*blockSize */
  	1.0,     32.0,      4.0,     128.0,
  	1.0,     32.0,     64.0,    2048.0,
  	1.0,     16.0,      4.0,      64.0,
  	1.0,     16.0,     64.0,    1024.0,
};
/* ----------------------------------------------------------------------
* Temporary buffers  for storing intermediate values
* ------------------------------------------------------------------- */
/* Transpose of A Buffer */
float32_t AT_f32[16];
/* (Transpose of A * A) Buffer */
float32_t ATMA_f32[16];
/* Inverse(Transpose of A * A)  Buffer */
float32_t ATMAI_f32[16];
/* Test Output Buffer */
float32_t X_f32[4];
/* ----------------------------------------------------------------------
* Reference ouput buffer C1, C2, C3 and C4 taken from MATLAB
* ------------------------------------------------------------------- */
const float32_t xRef_f32[4] = {73.0, 8.0, 21.25, 2.875};
float32_t snr;
/* ----------------------------------------------------------------------
* Max magnitude FFT Bin test
* ------------------------------------------------------------------- */
int32_t main(void)
{
  	arm_matrix_instance_f32 A;      /* Matrix A Instance */
  	arm_matrix_instance_f32 AT;     /* Matrix AT(A transpose) instance */
  	arm_matrix_instance_f32 ATMA;   /* Matrix ATMA( AT multiply with A) instance */
  	arm_matrix_instance_f32 ATMAI;  /* Matrix ATMAI(Inverse of ATMA) instance */
  	arm_matrix_instance_f32 B;      /* Matrix B instance */
 	arm_matrix_instance_f32 X;      /* Matrix X(Unknown Matrix) instance */
  	uint32_t srcRows, srcColumns;  /* Temporary variables */
  	arm_status status;
  	/* Initialise A Matrix Instance with numRows, numCols and data array(A_f32) */
  	srcRows = 4;
  	srcColumns = 4;
  	arm_mat_init_f32(&A, srcRows, srcColumns, (float32_t *)A_f32);
  	
    /* Initialise Matrix Instance AT with numRows, numCols and data array(AT_f32) */
  	srcRows = 4;
  	srcColumns = 4;
  	arm_mat_init_f32(&AT, srcRows, srcColumns, AT_f32);
  	
    /* calculation of A transpose */
  	status = arm_mat_trans_f32(&A, &AT);
  	
    /* Initialise ATMA Matrix Instance with numRows, numCols and data array(ATMA_f32) */
  	srcRows = 4;
  	srcColumns = 4;
  	arm_mat_init_f32(&ATMA, srcRows, srcColumns, ATMA_f32);
  	
    /* calculation of AT Multiply with A */
  	status = arm_mat_mult_f32(&AT, &A, &ATMA);
  	
    /* Initialise ATMAI Matrix Instance with numRows, numCols and data array(ATMAI_f32) */
  	srcRows = 4;
 	srcColumns = 4;
 	arm_mat_init_f32(&ATMAI, srcRows, srcColumns, ATMAI_f32);
  	
    /* calculation of Inverse((Transpose(A) * A) */
  	status = arm_mat_inverse_f32(&ATMA, &ATMAI);
  	
    /* calculation of (Inverse((Transpose(A) * A)) *  Transpose(A)) */
  	status = arm_mat_mult_f32(&ATMAI, &AT, &ATMA);
  	
    /* Initialise B Matrix Instance with numRows, numCols and data array(B_f32) */
  	srcRows = 4;
  	srcColumns = 1;
  	arm_mat_init_f32(&B, srcRows, srcColumns, (float32_t *)B_f32);
  	
    /* Initialise X Matrix Instance with numRows, numCols and data array(X_f32) */
  	srcRows = 4;
  	srcColumns = 1;
  	arm_mat_init_f32(&X, srcRows, srcColumns, X_f32);
  	
    /* calculation ((Inverse((Transpose(A) * A)) *  Transpose(A)) * B) */
  	status = arm_mat_mult_f32(&ATMA, &B, &X);
  	
    /* Comparison of reference with test output */
  	snr = arm_snr_f32((float32_t *)xRef_f32, X_f32, 4);
  	/*------------------------------------------------------------------------------
  	*            Initialise status depending on SNR calculations
  	*------------------------------------------------------------------------------*/
  	status = (snr < SNR_THRESHOLD) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
}

参考:

Matrix Example (arm-software.github.io)

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KPer_Yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值