void gs_matrix_set(gs_matrix_t *m, unsigned row, unsigned col, double val) { assert(row < m->c_rows); assert(col < m->c_rows); row_col_t *the_row = &m->rows[row]; if (row == col) { /* Note that we store the diagonal inverted to turn divisions to mults * in matrix_gauss_seidel(). */ assert(val != 0.0); the_row->diag = 1.0 / val; return; } /* Search for correct column */ col_val_t *cols = the_row->cols; unsigned min = 0; unsigned max = the_row->n_cols; unsigned c = max/2; while (min < max) { unsigned idx = cols[c].col_idx; if (idx < col) min = MAX(c, min+1); else if (idx > col) max = MIN(c, max-1); else break; c = (min+max)/2; } /* Have we found the entry? */ if (c < the_row->n_cols && the_row->cols[c].col_idx == col) { the_row->cols[c].v = val; if (val == 0.0) m->n_zero_entries++; return; } /* We haven't found the entry, so we must create a new one. * Is there enough space? */ if (the_row->n_cols <= the_row->c_cols) alloc_cols(the_row, the_row->c_cols + 16); /* Shift right-most entries to the right by one */ for (unsigned i = the_row->n_cols; i > c; --i) the_row->cols[i] = the_row->cols[i-1]; /* Finally insert the new entry */ the_row->n_cols++; the_row->cols[c].col_idx = col; the_row->cols[c].v = val; /* Check that the entries are sorted */ assert(c==0 || the_row->cols[c-1].col_idx < the_row->cols[c].col_idx); assert(c>=the_row->n_cols-1 || the_row->cols[c].col_idx < the_row->cols[c+1].col_idx); }
static void alloc_rows(gs_matrix_t *m, unsigned c_rows, unsigned c_cols, unsigned begin_init) { assert(c_rows > m->c_rows); m->c_rows = c_rows; m->rows = XREALLOC(m->rows, row_col_t, c_rows); for (unsigned i = begin_init; i < c_rows; ++i) { m->rows[i].c_cols = 0; m->rows[i].n_cols = 0; m->rows[i].diag = 0.0; m->rows[i].cols = NULL; if (c_cols > 0) alloc_cols(&m->rows[i], c_cols); } }
static inline void alloc_rows(gs_matrix_t *m, int c_rows, int c_cols, int begin_init) { int i; assert(c_rows > m->c_rows); m->c_rows = c_rows; m->rows = XREALLOC(m->rows, row_col_t, c_rows); for (i = begin_init; i < c_rows; ++i) { m->rows[i].c_cols = 0; m->rows[i].n_cols = 0; m->rows[i].diag = 0.0; m->rows[i].cols = NULL; if (c_cols > 0) alloc_cols(&m->rows[i], c_cols); } }
void gs_matrix_set(gs_matrix_t *m, int row, int col, double val) { row_col_t *the_row; col_val_t *cols; int min, max, c, i; if (row >= m->c_rows) { int new_c_rows = (int)(ROW_INCREASE_FACTOR * row); alloc_rows(m, new_c_rows, m->initial_col_increase, m->c_rows); } the_row = &m->rows[row]; if (row == col) { /* Note that we store the diagonal inverted to turn divisions to mults in * matrix_gauss_seidel(). */ assert(val != 0.0); the_row->diag = 1.0 / val; return; } // Search for correct column cols = the_row->cols; min = 0; max = the_row->n_cols; c = max/2; while (min < max) { int idx = cols[c].col_idx; if (idx < col) min = MAX(c, min+1); else if (idx > col) max = MIN(c, max-1); else break; c = (max+min)/2; } // Have we found the entry? if (c < the_row->n_cols && the_row->cols[c].col_idx == col) { the_row->cols[c].v = val; if (val == 0.0) m->n_zero_entries++; return; } // We haven't found the entry, so we must create a new one. // Is there enough space? if (the_row->c_cols == the_row->n_cols) alloc_cols(the_row, the_row->c_cols + COL_INCREASE); // Shift right-most entries to the right by one for (i = the_row->n_cols; i > c; --i) the_row->cols[i] = the_row->cols[i-1]; // Finally insert the new entry the_row->n_cols++; the_row->cols[c].col_idx = col; the_row->cols[c].v = val; // Check that the entries are sorted assert(c==0 || the_row->cols[c-1].col_idx < the_row->cols[c].col_idx); assert(c>=the_row->n_cols-1 || the_row->cols[c].col_idx < the_row->cols[c+1].col_idx); }
void gs_matrix_assure_row_capacity(gs_matrix_t *m, int row, int min_capacity) { row_col_t *the_row = &m->rows[row]; if (the_row->c_cols < min_capacity) alloc_cols(the_row, min_capacity); }