int main(int argc, char** argv) { printf("--------verify--------\n"); verify_matrix(); printf("----------------------\n"); // autorelease関数をbeginとendにはさまないで使うのはNG // 全てのallocされた関数は // (1) free // (2) release // (3) begin-endの中でautorelease // のいずれかを行う必要がある。 // 擬似逆行列演算がこれくらい簡単に記述できる。 /* 3*2行列aを確保、成分ごとの代入 */ matrix_t* a = matrix_alloc(3, 2); ELEMENT(a, 0, 0) = 1; ELEMENT(a, 0, 1) = 4; ELEMENT(a, 1, 0) = 2; ELEMENT(a, 1, 1) = 5; ELEMENT(a, 2, 0) = 3; ELEMENT(a, 2, 1) = 6; /* 擬似逆行列の演算 */ // auto releaseモードに入る matrix_begin(); // 擬似逆行列を求める。一行だけ! matrix_t* inva = matrix_product(matrix_inverse(matrix_product(matrix_transpose(a), a)), matrix_transpose(a)); // 擬似逆行列の表示 (invaはmatrix_endで解放されるので、begin-end内で。) matrix_print(inva); // release poolを開放する matrix_end(); /* ちなみに擬似逆行列を求める関数は内部に組んだので、それを使うこともできる。 */ // auto releaseモードに入る matrix_begin(); // 擬似逆行列を求める関数を呼ぶ。 matrix_t* inva_simple = matrix_pseudo_inverse(a); // 擬似逆行列の表示 (invaはmatrix_endで解放されるので、begin-end内で。) matrix_print(inva_simple); // release poolを開放する matrix_end(); // これはautorelease対象でないので、しっかり自分でfree。 // リテインカウントを実装してあるので、理解できればreleaseの方が高性能。 //matrix_free(a); matrix_release(a); return 0; }
void init_mat(void) { matrix_begin(); matrix_t* A = matrix_matrix(2, 2); ELEMENT(A, 0, 0) = 1.0; ELEMENT(A, 0, 0) = 3.0; ELEMENT(A, 0, 0) = 2.0; ELEMENT(A, 0, 0) = 4.0; sq_init_matrix(A); matrix_end(); }
// autorelease function matrix_t* matrix_pseudo_inverse(matrix_t* m) { if (m->rows == m->cols) { return matrix_inverse(m); } else if (m->rows > m->cols) { matrix_begin(); // (A^T A)^{-1} A^T matrix_t* ret = matrix_product(matrix_inverse(matrix_product(matrix_transpose(m), m)),matrix_transpose(m)); matrix_retain(ret); matrix_end(); return matrix_autorelease(ret); } else { matrix_begin(); // A^T (A A^T)^{-1} matrix_t* ret = matrix_product(matrix_transpose(m), matrix_inverse(matrix_product(m, matrix_transpose(m)))); matrix_retain(ret); matrix_end(); return matrix_autorelease(ret); } }
// autorelease function matrix_t* matrix_inverse(matrix_t* m) { if (m->rows != m->cols) { assert(0); // not a square matrix } int i, j; int maxi; int nrc; nrc = m->rows; matrix_t* minv = matrix_alloc(nrc, nrc); matrix_t* vtmp = matrix_alloc(1, nrc); float tmp; matrix_begin(); matrix_t* mtmp = matrix_copy(m); for (i = 0; i < nrc * nrc; i++) { if (i / nrc == i % nrc) ELEMENT(minv,i/nrc,i%nrc) = 1.0f; else ELEMENT(minv,i/nrc,i%nrc) = 0.0f; } if (mtmp == NULL || minv == NULL) return NULL; for (i=0; i<nrc; i++) { maxi = i; for (j=i+1; j<nrc; j++) { if(ABS(ELEMENT(mtmp,maxi,i)) < ABS(ELEMENT(mtmp,j,i))) maxi = j; } if (ELEMENT(mtmp,maxi,i) == 0.0f) { printf("input matrix is invalid!\n"); break; } // 行入れ替え matrix_copy_row(mtmp, i, vtmp, 0); matrix_copy_row(mtmp, maxi, mtmp, i); matrix_copy_row(vtmp, 0, mtmp, maxi); // 行入れ替え matrix_copy_row(minv, i, vtmp, 0); matrix_copy_row(minv, maxi, minv, i); matrix_copy_row(vtmp, 0, minv, maxi); tmp = ELEMENT(mtmp,i,i); for (j=0; j<nrc; j++) { // j:列番号 ELEMENT(mtmp, i, j) = ELEMENT(mtmp, i, j)/tmp; ELEMENT(minv, i, j) = ELEMENT(minv, i, j)/tmp; } for (j=0; j<nrc; j++) { // j:行番号 if (i!=j) { tmp = ELEMENT(mtmp,j,i); matrix_row_linear_comb(-tmp, mtmp, i, 1.0f, mtmp, j, mtmp, j); matrix_row_linear_comb(-tmp, minv, i, 1.0f, minv, j, minv, j); } } } matrix_end(); matrix_free(vtmp); return matrix_autorelease(minv); }