float SparMatrix_get(struct SparMatrix *m, int row_num, int col_num) { struct SparMatrixRow *p_row; struct SparMatrixCell *p_cell; if (row_num < 0 || row_num >= m->h || col_num < 0 || col_num >= m->w) { WARNING("SparMatrix_get(): " "Invalid Index (row = %d, col = %d)\n", row_num, col_num); return 0; } p_row = _get_row(m, row_num); if (p_row == NULL) { return 0; } p_cell = p_row->cells; while (p_cell && p_cell->col_num < col_num) { p_cell = p_cell->next; } /* cell found */ if (p_cell && p_cell->col_num == col_num) { return p_cell->data; } return 0; }
/** * Fills in a square PETSc matrix from MTJ's CompDiagMatrix internal storage * * @param env a pointer to the JNI environment * @param A a pointer to the the PETSc matrix to fill * @param index a pointer to the indices from CompDiagMatrix.getIndex() * @param diagonals a pointer to the diagonals from * CompDiagMatrix.getDiagonals() * @return 0 on success, PetscErrorCode on failure */ PetscErrorCode _fill_matrix(JNIEnv *env, Mat *A, jintArray *index, jobjectArray *diagonals) { // Get matrix dimension PetscInt n; PetscErrorCode ierr; ierr = MatGetSize(*A, &n, NULL); CHKERRQ(ierr); // Get size and base pointer for array of diagonal indices jsize index_length = (*env) -> GetArrayLength(env, *index); jint *index_array = (*env) -> GetIntArrayElements(env, *index, 0); // Loop through the array of diagonals for (int i = 0; i < index_length; i++) { // Get the current diagonal, its size and its base pointer jdoubleArray diag = (jdoubleArray) (*env) -> GetObjectArrayElement( env, *diagonals, i); jsize diag_length = (*env) -> GetArrayLength(env, diag); jdouble *diag_array = (*env) -> GetDoubleArrayElements(env, diag, 0); // Loop through current diagonal for (int j = 0; j < diag_length; j++) { int row = _get_row(index_array[i], j); int col = _get_col(index_array[i], j); ierr = MatSetValue(*A, row, col, diag_array[j], INSERT_VALUES); CHKERRQ(ierr); } (*env) -> ReleaseDoubleArrayElements(env, diag, diag_array, 0); } (*env) -> ReleaseIntArrayElements(env, *index, index_array, 0); return 0; }
/* [A] [X] = [B], to calculate [X], [X] returned in [B]*/ void SparMatrix_Gauss( struct SparMatrix *A, /* will be dirty, backup by user */ struct SparMatrix *B /* will be dirty, backup by user */ ) { int row; int progress = 0; if (!(A && B)) { WARNING("SparMatrix_Gauss(A, B): A and B can not be NULL.\n"); return; } if (B->w != 1) { WARNING("SparMatrix_Gauss(A, B): " "B must be a vertical vector.\n"); return; } if (A->h != B->h) { WARNING("SparMatrix_Gauss(A, B): " "A and B must have the same Height.\n"); return; } for (row = 0; row < A->h; ++row) { int row_i; struct SparMatrixRow *p_row; struct SparMatrixCell *p_cell; float factor; float b; if ((row*100 / A->h) == progress) { printf("%d%%\n", progress); progress += 5; } row_i = find_left_abs_largest(A, row); if (row_i < 0) { /* continue; */ break; } TRACE("EXCHANGE line %d and %d\n", row, row_i); SparMatrix_exchange_row(A, row_i, row); SparMatrix_exchange_row(B, row_i, row); p_row = _get_row(A, row); p_cell = p_row->cells; factor = p_cell->data; p_cell->data = 1; p_cell = p_cell->next; while (p_cell) { p_cell->data /= factor; p_cell = p_cell->next; } TRACE("Line %d divide %f\n", row, factor); b = SparMatrix_get(B, row, 0); if (b != 0) { b /= factor; SparMatrix_set(B, row, 0, b); } for (row_i = 0; row_i < A->h; ++row_i) { if (row_i == row) { continue; } p_cell = p_row->cells; /* recycled variable factor */ factor = SparMatrix_get(A, row_i, p_cell->col_num); if (factor != 0) { TRACE("Line %d eliminated from line %d, " "factor = %f\n", row_i, row, factor); /* Update [A] */ SparMatrix_set(A, row_i, p_cell->col_num, 0); p_cell = p_cell->next; while (p_cell) { float value = SparMatrix_get(A, row_i, p_cell->col_num); SparMatrix_set(A, row_i, p_cell->col_num, value - factor*p_cell->data); p_cell = p_cell->next; } /* Update [B] */ if (b != 0) { float value = SparMatrix_get(B, row_i, 0); SparMatrix_set(B, row_i, 0, value - b*factor); } } } // { // int i,j; // printf("DUMP Matrizen:\n"); // for (i = 0; i < A->h; ++i) { // float val; // for (j = 0; j < A->w; ++j) { // val = SparMatrix_get(A, i, j); // if (val != 0) { // printf("[0m[00;33m%5.2f[0m ", val); // } else { // printf("%5.2f ", val); // } // } // val = SparMatrix_get(B, i, 0); // if (val != 0) { // printf("[0m[00;33m %9.4f[0m ", val); // } else { // printf(" %9.4f", val); // } // printf("\n"); // } // } } }
void SparMatrix_set(struct SparMatrix *m, int row_num, int col_num, float value) { struct SparMatrixRow *p_row; if (row_num < 0 || row_num >= m->h || col_num < 0 || col_num >= m->w) { WARNING("SparMatrix_set(): " "Invalid Index (row = %d, col = %d)\n", row_num, col_num); return; } if (value != 0) { p_row = insert_row(m, row_num); if (p_row == NULL) { WARNING("SparMatrix_set(): Can not insert a row.\n"); } insert_col(p_row, col_num, value); } else { /* Delete Cell */ struct SparMatrixRow *p_row; struct SparMatrixCell *p_cell, *p_cell_pre; /* find the row */ p_row = _get_row(m, row_num); if (p_row == NULL) { return; /* the row does not exist, needn't to release */ } /* find the col */ p_cell_pre = NULL; /* p_cell_pre := the cell before the target*/ p_cell = p_row->cells; /* p_cell := the target cell (will be deleted) */ while (p_cell && (p_cell->col_num < col_num)) { p_cell_pre = p_cell; p_cell = p_cell->next; } if (p_cell == NULL) { /* the row will not at this place be deleted */ return; /* cell does not exist */ } /* delete this cell and perhaps its row */ if (p_cell->col_num == col_num) { if (p_cell_pre == NULL) { /* delete cell */ p_row->cells = p_cell->next; free(p_cell); /* then delete the row */ if (p_row->cells == NULL) { struct SparMatrixRow *q_row; q_row = m->rows; while (/*q_row &&*/ q_row->next != p_row) { q_row = q_row->next; } /* there is no doubt, that p_row must exist, so the NULL situation will not be checked */ q_row->next = p_row->next; free(p_row); } return; } else { /* only delete this cell */ p_cell_pre->next = p_cell->next; free(p_cell); } } /* otherwise: p_cell->col_num > col_num, this cell does not exist*/ } }
void test__get_row() { assert(2 == _get_row(1, 2)); // above diagonal assert(1 == _get_row(0, 1)); // on diagonal assert(2 == _get_row(-1, 1)); // below digaonal }