1. 程式人生 > >我的C語言矩陣庫02

我的C語言矩陣庫02

之前實現的矩陣庫能夠完成功能,但是在使用上有些麻煩,有的地方使用&,有的地方只有*,而有的地方什麼都不用加,就顯得符號比較混亂。造成這個問題的原因就是我把所有矩陣的記憶體空間都分配在棧上了!而且由於棧記憶體是有限的,所以當我的矩陣定義過多過後,把STM32的棧給撐爆了。。。表現起來就是:在主函式中多定義一個變數,然後在其他地方莫名其妙卡住了。程式的棧記憶體是用來儲存臨時變數的,由系統自動管理和釋放,體現在彙編上就是PUSH和POP指令,一個程式的棧是有限的,這個棧空間大小在系統啟動的時候定義,如STM32的啟動檔案(startup_stm32f10x_hd.s)中開頭就定義到:

Stack_Size      EQU
0x00000400

這就是STM32預設棧空間的大小,為1KB,當我把這個值該為2KB後,之前出錯的地方就全部正常了,但這只是權宜之計,最根本的辦法使用malloc動態分配記憶體,將所有的矩陣都分配到堆記憶體中。
之前的工程中沒有使用系統的malloc函式,為了方便起見這裡使用的是原子的mymalloc函式,新的矩陣庫下載點選:
https://code.csdn.net/snippets/2597808
其中新加入了matrix_t_malloc函式和matrix_t_free函式。

/* 給矩陣動態申請一個記憶體空間 */
void matrix_t_malloc(struct matrix_t *A, u8 row, u8 column)
{
    A->m = mymalloc(column * row * sizeof
(float)); A->row = row; A->column = column; } /* 釋放矩陣佔用的記憶體空間 */ void matrix_t_free(struct matrix_t *A) { myfree(A->m); A->m = 0; A->row = 0; A->column = 0; }

使用起來也很簡單

int main(void){
    ...
    struct matrix_t A;
    matrix_t_malloc(&A, 3, 3);
    matrix_t_zero(&A);
    matrix_t_show("A"
, &A); matrix_t_free(&A); return 0; }

新的矩陣庫中也加入了一些新的函式,如matlab中的conv,用來求多項式的乘積,還有將矩陣清零的函式:

/* 多項式相乘函式,如conv([1 2], [3 4])表示: (1+2x)(3+4x)
* A = conv(A, B),A和B必須是行向量 
* 這裡要根據輸入行向量的大小動態初始化臨時變數的大小,所以必須用malloc動態申請記憶體
*/
int8_t matrix_t_conv(struct matrix_t *A, const struct matrix_t *B, const struct matrix_t *C)
{
    float *tmp;
    float *tmp1;
    u8 i,j;
    struct matrix_t TMP, TMP1;
    if(B->row != 1 || C->row != 1 || A->row != 1){
        return -1;
    }
    if(A->column != (B->column+C->column-1)){
        return -2;
    }
    tmp = mymalloc(B->column * 1 * sizeof(float));
    tmp1 = mymalloc(B->column * C->column * sizeof(float));
    MATRIX_INIT(TMP, tmp, B->column, 1);
    MATRIX_INIT(TMP1, tmp1, B->column, C->column);

    memset(A->m, 0, A->column * A->row * sizeof(float));
    matrix_t_T(&TMP, B);
    matrix_t_mul(&TMP1, &TMP, C, 1);
    for(i=0; i<TMP1.row; i++){
        for(j=0; j<TMP1.column; j++){
            *(A->m+i+j) += *(tmp1+i*TMP1.column+j);
        }
    }
    myfree(tmp);
    myfree(tmp1);
    return 0;
}

// 將一個矩陣清零
void matrix_t_zero(struct matrix_t *A)
{
    memset(A->m, 0, A->column * A->row * sizeof(float));
}

另外transport函式也進行了更改,支援將矩陣逆序再傳遞到另一個矩陣中。

/* A = B(x1:x2, y1:y2),支援x1<x2, y1<y2,此時矩陣將逆序傳遞
*/
int8_t matrix_t_transport(struct matrix_t *A, const struct matrix_t *B, 
                u8 x1, u8 x2, u8 y1, u8 y2)
{
    int i,j;
    if(B->row < (MAX(x1,x2)+1) || B->column < (MAX(y1,y2)+1)){
        return -1;
    }
    if(A->row != (abs(x2-x1)+1) || A->column != (abs(y2-y1)+1)){ 
        return -2;
    }
    for(i=0; i<A->row; i++){
        for(j=0; j<A->column; j++){
            if(x1 <= x2 && y1 <= y2){
                A->m[i * A->column + j] = B->m[(x1+i) * B->column + y1 + j];
            }else if(x1 >= x2 && y1 >= y2){
                A->m[i * A->column + j] = B->m[(x1-i) * B->column + y1 - j];
            }else{
                return -3;
            }
        }
    }
    return 0;
}