//Multiplies first two arguments, returns pointer to result //Should have sparse option //Returns: result, or null pointer if dimensions do not add up. matrix* matrix_mult(matrix* m1, matrix* m2) { //Scalar multiple case if (m1->size == 1) { matrix *res = malloc(sizeof(matrix)); matrix_init(res, m2->rows, m2->cols); for (uint32_t i = 1; i <= m2->rows; i++) { for (uint32_t j = 1; j <= m2->cols; j++) { matrix_insert(res, i,j, *matrix_elem(m1,1,1)*(*matrix_elem(m2,i,j))); } } return res; } //Check dimensionality if (m1->cols != m2->rows) return NULL; matrix *res = malloc(sizeof(matrix)); matrix_init(res, m1->rows, m2->cols); double val; for (uint32_t i = 1; i <= m1->rows; i++) { for (uint32_t j = 1; j <= m2->cols; j++) { val = 0.0; for (uint32_t k = 1; k <= m1->cols; k++) val += (*matrix_elem(m1,i,k))*(*matrix_elem(m2,k,j)); matrix_insert(res,i,j,val); } } return res; }
/* pomnoz dwie matrixe i zwroc do matrix wynikowa lub NULL w razie bledu */ matrix_t matrix_mul (matrix_t a, matrix_t b) { int i, j, k; matrix_t mret; if (a->rn != b->cn) { fprintf (stderr, "! matrixe nieprawidlowych rozmiarow."); return NULL; } if (!(mret = make_matrix (b->rn, b->cn))) return NULL; for (i = 0; i < b->cn; i++) { for (j = 0; j < b->rn; j++) { matrix_insert (mret, i, j, 0); for (k = 0; k < a->cn; k++) { mret->p[i][j] += a->p[k][i] * b->p[j][k]; } } } return mret; }
/* zamien kolumny w matrix; zwraca 0 lub -1 dla bledu */ int matrix_swap_col (matrix_t a, int source, int target) { int i; int mwidth = (*a).cn; matrix_t m_tmp; if (source == target) return 0; if (!(m_tmp = make_matrix (1, mwidth))) return -1; for (i = 0; i < mwidth; i++) matrix_insert (m_tmp, 0, i, matrix_get (a, source, i)); for (i = 0; i < mwidth; i++) matrix_insert (a, source, i, matrix_get (a, target, i)); for (i = 0; i < mwidth; i++) matrix_insert (a, target, i, matrix_get (m_tmp, 0, i)); free_matrix (m_tmp); return 0; }
/* zamien wiersze w matrix; zwraca 0 lub -1 dla bledu */ int matrix_swap_row (matrix_t a, int source, int target) { int i; int mwidth = (*a).rn; matrix_t m_tmp; if (source == target) return 0; if (!(m_tmp = make_matrix (mwidth, 1))) return -1; for (i = 0; i < mwidth; i++) matrix_insert (m_tmp, i, 0, matrix_get (a, i, source)); for (i = 0; i < mwidth; i++) matrix_insert (a, i, source, matrix_get (a, i, target)); for (i = 0; i < mwidth; i++) matrix_insert (a, i, target, matrix_get (m_tmp, i, 0)); free_matrix (m_tmp); return 0; }
/*wczytaj matrix ze strumienia; zwraca wskaznik do matrix_t lub NULL dla niepowodzenia*/ matrix_t wczytaj_matrix (FILE * p) { int n, m, i, j; /* zmienne robocze */ matrix_t matrix; if (fscanf (p, "%i x %i", &n, &m) != 2) return NULL; if (!(matrix = make_matrix (n, m))) return NULL; while ((i = fgetc (p)) == ' ') /* pomijamy spacje po liczbie elementow */ ; /* mamy znak rozny od spacji - powinien to byc znak '[' */ if (i != '[') { free_matrix (matrix); return NULL; /* nie jest - bledny format pliku */ } /* teraz czytamy n liczb */ for (j = 0; j < m; j++) { for (i = 0; i < n; i++) { float tmpval = 0; if (fscanf (p, "%f", &tmpval) != 1) { /* fscanf powinno zawsze zwracac 1 - jesli zwroci cos innego */ free_matrix (matrix); return NULL; /* to znaczy, ze format pliku jest zly */ } else { matrix_insert (matrix, i, j, tmpval); } } } /* mamy liczby, teraz szukamy zamykajacego nawiasu: */ while ((i = fgetc (p)) == ' ' || i == '\n') /* pomijamy spacje i \n */ ; /* mamy znak rozny od spacji - powinien to byc znak ']' */ if (i != ']') { free_matrix (matrix); return NULL; /* nie jest - bledny format pliku */ } /* jesli doszlismy juz tu, to wszystko jest ok, mamy w wektorze n liczb */ return matrix; }
/** * Rebuild matrix using database entries * \return negative on failure, positive on success, indicating the number of matrix entries */ static int db_reload_matrix(void) { db_key_t columns[3] = { &matrix_first_col, &matrix_second_col, &matrix_res_col }; db1_res_t *res; int i; int n = 0; if (matrix_dbf.use_table(matrix_dbh, &matrix_table) < 0) { LM_ERR("cannot use table '%.*s'.\n", matrix_table.len, matrix_table.s); return -1; } if (matrix_dbf.query(matrix_dbh, NULL, NULL, NULL, columns, 0, 3, NULL, &res) < 0) { LM_ERR("error while executing query.\n"); return -1; } /* critical section start: avoids dirty reads when updating d-tree */ lock_get(lock); matrix_clear(); if (RES_COL_N(res) > 2) { for(i = 0; i < RES_ROW_N(res); i++) { if ((!RES_ROWS(res)[i].values[0].nul) && (!RES_ROWS(res)[i].values[1].nul)) { if ((RES_ROWS(res)[i].values[0].type == DB1_INT) && (RES_ROWS(res)[i].values[1].type == DB1_INT) && (RES_ROWS(res)[i].values[2].type == DB1_INT)) { matrix_insert(RES_ROWS(res)[i].values[0].val.int_val, RES_ROWS(res)[i].values[1].val.int_val, RES_ROWS(res)[i].values[2].val.int_val); n++; } else { LM_ERR("got invalid result type from query.\n"); } } } } /* critical section end */ lock_release(lock); matrix_dbf.free_result(matrix_dbh, res); LM_INFO("loaded %d matrix entries.", n); return n; }