/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003, 2004, 2005 Gabor Csardi MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "types.h" #include "memory.h" #include "random.h" #include "error.h" #include #include /* memcpy & co. */ #include /** * \section igraph_matrix_constructor_and_destructor Matrix constructors and * destructors */ /** * \ingroup matrix * \function igraph_matrix_init * \brief Initializes a matrix. * * * Every matrix needs to be initialized before using it, this is done * by calling this function. A matrix has to be destroyed if it is not * needed any more, see \ref igraph_matrix_destroy(). * \param m Pointer to a not yet initialized matrix object to be * initialized. * \param nrow The number of rows in the matrix. * \param ncol The number of columns in the matrix. * \return Error code. * * Time complexity: usually O(n), * n is the * number of elements in the matrix. */ int igraph_matrix_init(igraph_matrix_t *m, long int nrow, long int ncol) { int ret1; ret1=igraph_vector_init(&m->data, nrow*ncol); m->nrow=nrow; m->ncol=ncol; return ret1; } /** * \ingroup matrix * \function igraph_matrix_destroy * \brief Destroys a matrix object. * * * This function frees all the memory allocated for a matrix * object. The destroyed object needs to be reinitialized before using * it again. * \param m The matrix to destroy. * * Time complexity: operating system dependent. */ void igraph_matrix_destroy(igraph_matrix_t *m) { igraph_vector_destroy(&m->data); } /** * \section igraph_matrix_accessing_elements Accessing elements of a matrix */ /** * \ingroup matrix * \function igraph_matrix_resize * \brief Resizes a matrix. * * * This function resizes a matrix by adding more elements to it. * The matrix contains arbitrary data after resizing it. * Ie. after calling this function you cannot expect that element * (i,j) in the matrix remains the * same as before. * \param m Pointer to an already initialized matrix object. * \param nrow The number of rows in the resized matrix. * \param ncol The number of columns in the resized matrix. * \return Error code. * * Time complexity: O(1) if the * matrix gets smaller, usually O(n) * if it gets larger, n is the * number of elements in the resized matrix. */ int igraph_matrix_resize(igraph_matrix_t *m, long int nrow, long int ncol) { igraph_vector_resize(&m->data, nrow*ncol); m->nrow=nrow; m->ncol=ncol; return 0; } /** * \ingroup matrix * \function igraph_matrix_size * \brief The number of elements in a matrix. * * \param m Pointer to an initialized matrix object. * \return The size of the matrix. * * Time complexity: O(1). */ long int igraph_matrix_size(const igraph_matrix_t *m) { return (m->nrow) * (m->ncol); } /** * \ingroup matrix * \function igraph_matrix_nrow * \brief The number of rows in a matrix. * * \param m Pointer to an initialized matrix object. * \return The number of rows in the matrix. * * Time complexity: O(1). */ long int igraph_matrix_nrow(const igraph_matrix_t *m) { return m->nrow; } /** * \ingroup matrix * \function igraph_matrix_ncol * \brief The number of columns in a matrix. * * \param m Pointer to an initialized matrix object. * \return The number of columns in the matrix. * * Time complexity: O(1). */ long int igraph_matrix_ncol(const igraph_matrix_t *m) { return m->ncol; } /** * \ingroup matrix * \brief Copies a matrix to a regular C array. * * * The matrix is copied columnwise, as this is the format most * programs and languages use. * The C array should be of sufficient size, there are (of course) not * range checks done. * \param m Pointer to an initialized matrix object. * \param to Pointer to a C array, the place to copy the data to. * \return Error code. * * Time complexity: O(n), * n is the number of * elements in the matrix. */ int igraph_matrix_copy_to(const igraph_matrix_t *m, igraph_real_t *to) { igraph_vector_copy_to(&m->data, to); return 0; } /** * \ingroup matrix * \brief Sets all element in a matrix to zero. * * \param m Pointer to an initialized matrix object. * \return Error code, always returns with success. * * Time complexity: O(n), * n is the number of elements in * the matrix. */ int igraph_matrix_null(igraph_matrix_t *m) { igraph_vector_null(&m->data); return 0; } /** * \ingroup matrix * \function igraph_matrix_add_cols * \brief Adds columns to a matrix. * \param m The matrix object. * \param n The number of columns to add. * \return Error code, \c IGRAPH_ENOMEM if there is * not enough memory to perform the operation. * * Time complexity: linear with the number of elements of the new, * resized matrix. */ int igraph_matrix_add_cols(igraph_matrix_t *m, long int n) { igraph_matrix_resize(m, m->nrow, m->ncol+n); return 0; } /** * \ingroup matrix * \function igraph_matrix_add_rows * \brief Adds rows to a matrix. * \param m The matrix object. * \param n The number of rows to add. * \return Error code, \c IGRAPH_ENOMEM if there * isn't enough memory for the operation. * * Time complexity: linear with the number of elements of the new, * resized, matrix. */ int igraph_matrix_add_rows(igraph_matrix_t *m, long int n) { long int i; igraph_vector_resize(&m->data, (m->ncol)*(m->nrow+n)); for (i=m->ncol-1; i>=0; i--) { igraph_vector_move_interval(&m->data, (m->nrow)*i, (m->nrow)*(i+1), (m->nrow+n)*i); } m->nrow += n; return 0; } /** * \ingroup matrix * \function igraph_matrix_remove_col * \brief Removes a column from a matrix. * * \param m The matrix object. * \param col The column to remove. * \return Error code, always returns with success. * * Time complexity: linear with the number of elements of the new, * resized matrix. */ int igraph_matrix_remove_col(igraph_matrix_t *m, long int col) { igraph_vector_remove_section(&m->data, (m->nrow)*col, (m->nrow)*(col+1)); m->ncol--; return 0; } /** * \ingroup matrix * \function igraph_matrix_permdelete_rows * \brief Removes columns from a matrix (for internal use). * * Time complexity: linear with the number of elements of the original * matrix. */ int igraph_matrix_permdelete_rows(igraph_matrix_t *m, long int *index, long int nremove) { long int i, j; for (i=0; incol; i++) { for (j=0; jnrow; j++) { if (index[j] != 0) { MATRIX(*m, index[j]-1, i) = MATRIX(*m, j, i); } } } igraph_matrix_resize(m, m->nrow-nremove, m->ncol); return 0; } /** * \ingroup matrix * \function igraph_matrix_delete_rows_neg * \brief Removes columns from a matrix (for internal use). * * Time complexity: linear with the number of elements of the original * matrix. */ int igraph_matrix_delete_rows_neg(igraph_matrix_t *m, igraph_vector_t *neg, long int nremove) { long int i, j, idx=0; for (i=0; incol; i++) { for (j=0; jnrow; j++) { if (VECTOR(*neg)[j] >= 0) { MATRIX(*m, idx++, i) = MATRIX(*m, j, i); } } idx=0; } igraph_matrix_resize(m, m->nrow-nremove, m->ncol); return 0; } /** * \ingroup matrix * \function igraph_matrix_copy * \brief Copies a matrix. * * * Creates a matrix object by copying another one. * \param to Pointer to an uninitialized matrix object. * \param from The initialized matrix object to copy. * \return Error code, \c IGRAPH_ENOMEM if there * isn't enough memory to allocate the new matrix. * * Time complexity: O(n), the number * of elements in the matrix. */ int igraph_matrix_copy(igraph_matrix_t *to, const igraph_matrix_t *from) { to->nrow = from->nrow; to->ncol = from->ncol; return igraph_vector_copy(&to->data, &from->data); } /** * \function igraph_matrix_max * * Returns the maximal element of a matrix. * \param m The matrix object. * \return The maximum element. For empty matrix the returned value is * undefined. * * Added in version 0.2. * * Time complexity: O(n), the number of elements in the matrix. */ igraph_real_t igraph_matrix_max(const igraph_matrix_t *m) { return igraph_vector_max(&m->data); } /** * \function igraph_matrix_multiply * * Multiplies each element of the matrix by a constant. * \param m The matrix. * \param by The constant. * * Added in version 0.2. * * Time complexity: O(n), the number of elements in the matrix. */ void igraph_matrix_multiply(igraph_matrix_t *m, igraph_real_t by) { igraph_vector_multiply(&m->data, by); } int igraph_matrix_select_rows(const igraph_matrix_t *m, igraph_matrix_t *res, const igraph_vector_t *rows) { long int norows=igraph_vector_size(rows); long int i, j, ncols=igraph_matrix_ncol(m); IGRAPH_CHECK(igraph_matrix_resize(res, norows, ncols)); for (i=0; idata, res, nrow*index, nrow*(index+1))); return 0; } igraph_real_t igraph_matrix_sum(const igraph_matrix_t *m) { return igraph_vector_sum(&m->data); } igraph_bool_t igraph_matrix_is_equal(const igraph_matrix_t *m1, const igraph_matrix_t *m2) { return igraph_vector_is_equal(&m1->data, &m2->data); } igraph_real_t igraph_matrix_maxdifference(const igraph_matrix_t *m1, const igraph_matrix_t *m2) { long int col1=igraph_matrix_ncol(m1); long int col2=igraph_matrix_ncol(m2); long int row1=igraph_matrix_nrow(m1); long int row2=igraph_matrix_nrow(m2); if (col1 != col2 || row1 != row2) { IGRAPH_WARNING("Comparing non-conformant matrices"); } return igraph_vector_maxdifference(&m1->data, &m2->data); }