This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

CMSIS-DSP: Matrix Inverse problem

Hello,

While debugging a DSP algorithm, I realized the problem is duo to the CMSIS matrix inverse function: arm_mat_inverse_f32. It's really strange and is driving me crazy. arm_mat_inverse_f32 returns the right result for some Matrices but wrong result for some other! I assure you the matrices are not singular or anything like this, the algorithm works just fine with the same input data on MATLAB. I have no idea what the problem could be, any suggestions?

Regards

Parents
  • Hello all,

    The fumction arm_mat_init_f32() stores only a pointer to the matrix data in the matrix instance. It does not copy the matrix data.
    The function arm_mat_inverse_f32() overwrites the matrix data from the source matrix when it generates the inverse matrix.
    This behaviour is not yet documented in the CMSIS DSP_Lib documentation.

    Please see code below for matrix inversion. This test uses the data mentioned above.

    #include "arm_math.h"
    #include "math_helper.h"
    
    #define SIZE (6)
    
    float32_t Matrix1[SIZE*SIZE] ={
        7.6294,  1.1843,  1.0842,  1.7056,  1.3111,  0.8036,
        1.1843,  7.0938,  1.4429,  1.9244,  0.9154,  1.0024,
        1.0842,  1.4429,  7.6006,  0.7976,  1.1649,  1.1927,
        1.7056,  1.9244,  0.7976,  6.0714,  1.2414,  0.9802,
        1.3111,  0.9154,  1.1649,  1.2414,  7.3110,  0.2683,
        0.8036,  1.0024,  1.1927,  0.9802,  0.2683,  7.6469  };
    
    float32_t Matrix1S[SIZE*SIZE];   /* Second Matrix */
    float32_t Matrix1I[SIZE*SIZE];   /* Inverse Matrix */
    float32_t Matrix1U[SIZE*SIZE];   /* Unity Matrix */
    arm_matrix_instance_f32 m1;      /* Matrix 1 Instance */
    arm_matrix_instance_f32 m1S;     /* Matrix 1 Second Instance */
    arm_matrix_instance_f32 m1I;     /* Matrix 1 Inverse Instance */
    arm_matrix_instance_f32 m1U;     /* Matrix 1 Unity Instance */
    
    int32_t main(void) {
      uint32_t   i;
      arm_status status  = ARM_MATH_TEST_FAILURE;
      uint16_t   rows    = SIZE;
      uint16_t   columns = SIZE;
    
      /* copy matrix data because arm_mat_inverse_f32(...)
         overwrites the data from the source matrix        */
      for (i = 0; i < (SIZE*SIZE); i++)
              Matrix1S[i] = Matrix1[i];
      /* initialize the used matrix instances */
      arm_mat_init_f32(&m1,  rows, columns, Matrix1);
      arm_mat_init_f32(&m1S, rows, columns, Matrix1S);
      arm_mat_init_f32(&m1I, rows, columns, Matrix1I);
      arm_mat_init_f32(&m1U, rows, columns, Matrix1U);
      /* generate the inverse matrix */
      status = arm_mat_inverse_f32(&m1S ,&m1I);
      /* matrix * inverse matrix = unity matrix */
      status = arm_mat_mult_f32(&m1, &m1I, &m1U);
    
      while(1);
    }
    

    Best regards, Martin Guenther

Reply
  • Hello all,

    The fumction arm_mat_init_f32() stores only a pointer to the matrix data in the matrix instance. It does not copy the matrix data.
    The function arm_mat_inverse_f32() overwrites the matrix data from the source matrix when it generates the inverse matrix.
    This behaviour is not yet documented in the CMSIS DSP_Lib documentation.

    Please see code below for matrix inversion. This test uses the data mentioned above.

    #include "arm_math.h"
    #include "math_helper.h"
    
    #define SIZE (6)
    
    float32_t Matrix1[SIZE*SIZE] ={
        7.6294,  1.1843,  1.0842,  1.7056,  1.3111,  0.8036,
        1.1843,  7.0938,  1.4429,  1.9244,  0.9154,  1.0024,
        1.0842,  1.4429,  7.6006,  0.7976,  1.1649,  1.1927,
        1.7056,  1.9244,  0.7976,  6.0714,  1.2414,  0.9802,
        1.3111,  0.9154,  1.1649,  1.2414,  7.3110,  0.2683,
        0.8036,  1.0024,  1.1927,  0.9802,  0.2683,  7.6469  };
    
    float32_t Matrix1S[SIZE*SIZE];   /* Second Matrix */
    float32_t Matrix1I[SIZE*SIZE];   /* Inverse Matrix */
    float32_t Matrix1U[SIZE*SIZE];   /* Unity Matrix */
    arm_matrix_instance_f32 m1;      /* Matrix 1 Instance */
    arm_matrix_instance_f32 m1S;     /* Matrix 1 Second Instance */
    arm_matrix_instance_f32 m1I;     /* Matrix 1 Inverse Instance */
    arm_matrix_instance_f32 m1U;     /* Matrix 1 Unity Instance */
    
    int32_t main(void) {
      uint32_t   i;
      arm_status status  = ARM_MATH_TEST_FAILURE;
      uint16_t   rows    = SIZE;
      uint16_t   columns = SIZE;
    
      /* copy matrix data because arm_mat_inverse_f32(...)
         overwrites the data from the source matrix        */
      for (i = 0; i < (SIZE*SIZE); i++)
              Matrix1S[i] = Matrix1[i];
      /* initialize the used matrix instances */
      arm_mat_init_f32(&m1,  rows, columns, Matrix1);
      arm_mat_init_f32(&m1S, rows, columns, Matrix1S);
      arm_mat_init_f32(&m1I, rows, columns, Matrix1I);
      arm_mat_init_f32(&m1U, rows, columns, Matrix1U);
      /* generate the inverse matrix */
      status = arm_mat_inverse_f32(&m1S ,&m1I);
      /* matrix * inverse matrix = unity matrix */
      status = arm_mat_mult_f32(&m1, &m1I, &m1U);
    
      while(1);
    }
    

    Best regards, Martin Guenther

Children