Coverage Report

Created: 2026-10-22 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/igraph/src/core/matrix.pmt
Line
Count
Source
1
/*
2
   igraph library.
3
   Copyright (C) 2003-2012  Gabor Csardi <csardi.gabor@gmail.com>
4
   334 Harvard street, Cambridge, MA 02139 USA
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
   02110-1301 USA
20
21
*/
22
23
#include "igraph_error.h"
24
25
#include "math/safe_intop.h"
26
27
#include <string.h>         /* memcpy & co. */
28
#include <stdlib.h>
29
30
/**
31
 * \section about_igraph_matrix_t_objects About \type igraph_matrix_t objects
32
 *
33
 * <para>This type is just an interface to \type igraph_vector_t.</para>
34
 *
35
 * <para>The \type igraph_matrix_t type usually stores n
36
 * elements in O(n) space, but not always. See the documentation of
37
 * the vector type.</para>
38
 */
39
40
/**
41
 * \section igraph_matrix_constructor_and_destructor Matrix constructors and
42
 * destructors
43
 */
44
45
/**
46
 * \ingroup matrix
47
 * \function igraph_matrix_init
48
 * \brief Initializes a matrix.
49
 *
50
 * </para><para>
51
 * Every matrix needs to be initialized before using it. This is done
52
 * by calling this function. A matrix has to be destroyed if it is not
53
 * needed any more; see \ref igraph_matrix_destroy().
54
 * \param m Pointer to a not yet initialized matrix object to be
55
 *        initialized.
56
 * \param nrow The number of rows in the matrix.
57
 * \param ncol The number of columns in the matrix.
58
 * \return Error code.
59
 *
60
 * Time complexity: usually O(n), n is the number of elements in the matrix.
61
 */
62
63
igraph_error_t FUNCTION(igraph_matrix, init)(
64
26.5k
        TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
65
26.5k
    igraph_int_t size;
66
26.5k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
67
26.5k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
68
26.5k
    IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&m->data, size));
69
26.5k
    m->nrow = nrow;
70
26.5k
    m->ncol = ncol;
71
26.5k
    return IGRAPH_SUCCESS;
72
26.5k
}
igraph_matrix_init
Line
Count
Source
64
12.6k
        TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
65
12.6k
    igraph_int_t size;
66
12.6k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
67
12.6k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
68
12.6k
    IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&m->data, size));
69
12.6k
    m->nrow = nrow;
70
12.6k
    m->ncol = ncol;
71
12.6k
    return IGRAPH_SUCCESS;
72
12.6k
}
igraph_matrix_int_init
Line
Count
Source
64
13.9k
        TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
65
13.9k
    igraph_int_t size;
66
13.9k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
67
13.9k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
68
13.9k
    IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&m->data, size));
69
13.9k
    m->nrow = nrow;
70
13.9k
    m->ncol = ncol;
71
13.9k
    return IGRAPH_SUCCESS;
72
13.9k
}
Unexecuted instantiation: igraph_matrix_char_init
Unexecuted instantiation: igraph_matrix_bool_init
Unexecuted instantiation: igraph_matrix_complex_init
73
74
/**
75
 * \ingroup matrix
76
 * \function igraph_matrix_view
77
 * \brief Creates a matrix view into an existing array.
78
 *
79
 * </para><para>
80
 * This function lets you treat an existing C array as a matrix. The elements
81
 * of the matrix are assumed to be stored in column-major order in the array,
82
 * i.e. the elements of the first column are stored first, followed by the
83
 * second column and so on.
84
 *
85
 * </para><para>
86
 * Since this function creates a view into an existing array, you must \em not
87
 * destroy the \type igraph_matrix_t object when you are done with it. Similarly,
88
 * you must \em not call any function on it that may attempt to modify the size
89
 * of the matrix. Modifying an element in the matrix will modify the underlying
90
 * array as the two share the same memory block.
91
 *
92
 * \param data The raw array that the matrix provides a view into.
93
 * \param nrow The number of rows in the matrix.
94
 * \param ncol The number of columns in the matrix.
95
 * \return The matrix object providing the view into the array.
96
 *
97
 * Time complexity: O(1).
98
 */
99
100
TYPE(igraph_matrix) FUNCTION(igraph_matrix, view)(
101
        const BASE *data,
102
4.27k
        igraph_int_t nrow, igraph_int_t ncol) {
103
104
    /* temporarily cast away the constness */
105
4.27k
    TYPE(igraph_matrix) m;
106
107
    /* No overflow checking, as this function does not return igraph_error_t.
108
     * It is the caller's resposibility to ensure that the size of 'data'
109
     * matches nrow*ncol, which also implies that nrow*ncol does not overflow. */
110
111
4.27k
    m.data = FUNCTION(igraph_vector, view)(data, ncol * nrow);
112
4.27k
    m.nrow = nrow;
113
4.27k
    m.ncol = ncol;
114
115
4.27k
    return m;
116
4.27k
}
igraph_matrix_view
Line
Count
Source
102
4.27k
        igraph_int_t nrow, igraph_int_t ncol) {
103
104
    /* temporarily cast away the constness */
105
4.27k
    TYPE(igraph_matrix) m;
106
107
    /* No overflow checking, as this function does not return igraph_error_t.
108
     * It is the caller's resposibility to ensure that the size of 'data'
109
     * matches nrow*ncol, which also implies that nrow*ncol does not overflow. */
110
111
4.27k
    m.data = FUNCTION(igraph_vector, view)(data, ncol * nrow);
112
4.27k
    m.nrow = nrow;
113
4.27k
    m.ncol = ncol;
114
115
4.27k
    return m;
116
4.27k
}
Unexecuted instantiation: igraph_matrix_int_view
Unexecuted instantiation: igraph_matrix_char_view
Unexecuted instantiation: igraph_matrix_bool_view
Unexecuted instantiation: igraph_matrix_complex_view
117
118
/**
119
 * \ingroup matrix
120
 * \function igraph_matrix_view_from_vector
121
 * \brief Creates a matrix view that treats an existing vector as a matrix.
122
 *
123
 * </para><para>
124
 * This function lets you treat an existing igraph vector as a matrix. The
125
 * elements of the matrix are assumed to be stored in column-major order in the
126
 * vector, i.e. the elements of the first column are stored first, followed by
127
 * the second column and so on.
128
 *
129
 * </para><para>
130
 * Since this function creates a view into an existing vector, you must \em not
131
 * destroy the \c igraph_matrix_t object when you are done with it. Similarly,
132
 * you must \em not call any function on it that may attempt to modify the size
133
 * of the vector. Modifying an element in the matrix will modify the underlying
134
 * vector as the two share the same memory block.
135
 *
136
 * </para><para>
137
 * Additionally, you must \em not attempt to grow the underlying vector by any
138
 * vector operation as that may result in a re-allocation of the backing memory
139
 * block of the vector, and the matrix view will not be informed about the
140
 * re-allocation so it will point to an invalid memory area afterwards.
141
 *
142
 * \param v The vector that the matrix will provide a view into.
143
 * \param nrow The number of rows in the matrix. The number of columns will be
144
 *        derived implicitly from the size of the vector. If the number of
145
 *        items in the vector is not divisible by the number of rows, the
146
 *        last few elements of the vector will not be covered by the view.
147
 * \return The matrix object providing the view into the vector.
148
 *
149
 * Time complexity: O(1).
150
 */
151
152
TYPE(igraph_matrix) FUNCTION(igraph_matrix, view_from_vector)(
153
    const TYPE(igraph_vector) *v,
154
    igraph_int_t nrow
155
0
) {
156
0
    igraph_int_t size = FUNCTION(igraph_vector, size)(v);
157
0
    igraph_int_t ncol = nrow > 0 ? size / nrow : 0;
158
159
0
    return FUNCTION(igraph_matrix, view)(VECTOR(*v), nrow, ncol);
160
0
}
Unexecuted instantiation: igraph_matrix_view_from_vector
Unexecuted instantiation: igraph_matrix_int_view_from_vector
Unexecuted instantiation: igraph_matrix_char_view_from_vector
Unexecuted instantiation: igraph_matrix_bool_view_from_vector
Unexecuted instantiation: igraph_matrix_complex_view_from_vector
161
162
/**
163
 * \ingroup matrix
164
 * \function igraph_matrix_destroy
165
 * \brief Destroys a matrix object.
166
 *
167
 * </para><para>
168
 * This function frees all the memory allocated for a matrix
169
 * object. The destroyed object needs to be reinitialized before using
170
 * it again.
171
 * \param m The matrix to destroy.
172
 *
173
 * Time complexity: operating system dependent.
174
 */
175
176
26.5k
void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m) {
177
26.5k
    FUNCTION(igraph_vector, destroy)(&m->data);
178
26.5k
}
igraph_matrix_destroy
Line
Count
Source
176
12.6k
void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m) {
177
12.6k
    FUNCTION(igraph_vector, destroy)(&m->data);
178
12.6k
}
igraph_matrix_int_destroy
Line
Count
Source
176
13.9k
void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m) {
177
13.9k
    FUNCTION(igraph_vector, destroy)(&m->data);
178
13.9k
}
Unexecuted instantiation: igraph_matrix_char_destroy
Unexecuted instantiation: igraph_matrix_bool_destroy
Unexecuted instantiation: igraph_matrix_complex_destroy
179
180
/**
181
 * \ingroup matrix
182
 * \function igraph_matrix_capacity
183
 * \brief Returns the number of elements allocated for a matrix.
184
 *
185
 * Note that this might be different from the size of the matrix (as
186
 * queried by \ref igraph_matrix_size()), and specifies how many elements
187
 * the matrix can hold, without reallocation.
188
 * \param v Pointer to the (previously initialized) matrix object
189
 *          to query.
190
 * \return The allocated capacity.
191
 *
192
 * \sa \ref igraph_matrix_size(), \ref igraph_matrix_nrow(),
193
 * \ref igraph_matrix_ncol().
194
 *
195
 * Time complexity: O(1).
196
 */
197
198
0
igraph_int_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m) {
199
0
    return FUNCTION(igraph_vector, capacity)(&m->data);
200
0
}
Unexecuted instantiation: igraph_matrix_capacity
Unexecuted instantiation: igraph_matrix_int_capacity
Unexecuted instantiation: igraph_matrix_char_capacity
Unexecuted instantiation: igraph_matrix_bool_capacity
Unexecuted instantiation: igraph_matrix_complex_capacity
201
202
203
/**
204
 * \section igraph_matrix_accessing_elements Accessing elements of a matrix
205
 */
206
207
/**
208
 * \ingroup matrix
209
 * \function igraph_matrix_resize
210
 * \brief Resizes a matrix.
211
 *
212
 * </para><para>
213
 * This function resizes a matrix by adding more elements to it.
214
 * The matrix contains arbitrary data after resizing it.
215
 * That is, after calling this function you cannot expect that element
216
 * (i,j) in the matrix remains the
217
 * same as before.
218
 * \param m Pointer to an already initialized matrix object.
219
 * \param nrow The number of rows in the resized matrix.
220
 * \param ncol The number of columns in the resized matrix.
221
 * \return Error code.
222
 *
223
 * Time complexity: O(1) if the
224
 * matrix gets smaller, usually O(n)
225
 * if it gets larger, n is the
226
 * number of elements in the resized matrix.
227
 */
228
229
70.7k
igraph_error_t FUNCTION(igraph_matrix, resize)(TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
230
70.7k
    igraph_int_t size;
231
70.7k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
232
70.7k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
233
70.7k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, size));
234
70.7k
    m->nrow = nrow;
235
70.7k
    m->ncol = ncol;
236
70.7k
    return IGRAPH_SUCCESS;
237
70.7k
}
igraph_matrix_resize
Line
Count
Source
229
36.5k
igraph_error_t FUNCTION(igraph_matrix, resize)(TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
230
36.5k
    igraph_int_t size;
231
36.5k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
232
36.5k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
233
36.5k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, size));
234
36.5k
    m->nrow = nrow;
235
36.5k
    m->ncol = ncol;
236
36.5k
    return IGRAPH_SUCCESS;
237
36.5k
}
igraph_matrix_int_resize
Line
Count
Source
229
34.1k
igraph_error_t FUNCTION(igraph_matrix, resize)(TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) {
230
34.1k
    igraph_int_t size;
231
34.1k
    IGRAPH_ASSERT(nrow >= 0 && ncol >= 0);
232
34.1k
    IGRAPH_SAFE_MULT(nrow, ncol, &size);
233
34.1k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, size));
234
34.1k
    m->nrow = nrow;
235
34.1k
    m->ncol = ncol;
236
34.1k
    return IGRAPH_SUCCESS;
237
34.1k
}
Unexecuted instantiation: igraph_matrix_char_resize
Unexecuted instantiation: igraph_matrix_bool_resize
Unexecuted instantiation: igraph_matrix_complex_resize
238
239
/**
240
 * \ingroup matrix
241
 * \function igraph_matrix_resize_min
242
 * \brief Deallocates unused memory for a matrix.
243
 *
244
 * This function attempts to deallocate the unused reserved storage
245
 * of a matrix.
246
 *
247
 * \param m Pointer to an initialized matrix.
248
 *
249
 * \sa \ref igraph_matrix_resize().
250
 *
251
 * Time complexity: operating system dependent, O(n) at worst.
252
 */
253
254
0
void FUNCTION(igraph_matrix, resize_min)(TYPE(igraph_matrix) *m) {
255
0
    FUNCTION(igraph_vector, resize_min)(&m->data);
256
0
}
Unexecuted instantiation: igraph_matrix_resize_min
Unexecuted instantiation: igraph_matrix_int_resize_min
Unexecuted instantiation: igraph_matrix_char_resize_min
Unexecuted instantiation: igraph_matrix_bool_resize_min
Unexecuted instantiation: igraph_matrix_complex_resize_min
257
258
259
/**
260
 * \ingroup matrix
261
 * \function igraph_matrix_size
262
 * \brief The number of elements in a matrix.
263
 *
264
 * \param m Pointer to an initialized matrix object.
265
 * \return The size of the matrix.
266
 *
267
 * Time complexity: O(1).
268
 */
269
270
0
igraph_int_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m) {
271
0
    return (m->nrow) * (m->ncol);
272
0
}
Unexecuted instantiation: igraph_matrix_size
Unexecuted instantiation: igraph_matrix_int_size
Unexecuted instantiation: igraph_matrix_char_size
Unexecuted instantiation: igraph_matrix_bool_size
Unexecuted instantiation: igraph_matrix_complex_size
273
274
/**
275
 * \ingroup matrix
276
 * \function igraph_matrix_nrow
277
 * \brief The number of rows in a matrix.
278
 *
279
 * \param m Pointer to an initialized matrix object.
280
 * \return The number of rows in the matrix.
281
 *
282
 * Time complexity: O(1).
283
 */
284
285
33.1k
igraph_int_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) {
286
33.1k
    return m->nrow;
287
33.1k
}
igraph_matrix_nrow
Line
Count
Source
285
12.9k
igraph_int_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) {
286
12.9k
    return m->nrow;
287
12.9k
}
igraph_matrix_int_nrow
Line
Count
Source
285
20.1k
igraph_int_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) {
286
20.1k
    return m->nrow;
287
20.1k
}
Unexecuted instantiation: igraph_matrix_char_nrow
Unexecuted instantiation: igraph_matrix_bool_nrow
Unexecuted instantiation: igraph_matrix_complex_nrow
288
289
/**
290
 * \ingroup matrix
291
 * \function igraph_matrix_ncol
292
 * \brief The number of columns in a matrix.
293
 *
294
 * \param m Pointer to an initialized matrix object.
295
 * \return The number of columns in the matrix.
296
 *
297
 * Time complexity: O(1).
298
 */
299
300
23.5k
igraph_int_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m) {
301
23.5k
    return m->ncol;
302
23.5k
}
igraph_matrix_ncol
Line
Count
Source
300
9.58k
igraph_int_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m) {
301
9.58k
    return m->ncol;
302
9.58k
}
igraph_matrix_int_ncol
Line
Count
Source
300
13.9k
igraph_int_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m) {
301
13.9k
    return m->ncol;
302
13.9k
}
Unexecuted instantiation: igraph_matrix_char_ncol
Unexecuted instantiation: igraph_matrix_bool_ncol
Unexecuted instantiation: igraph_matrix_complex_ncol
303
304
/**
305
 * Copies matrix data stored contiguously while transposing. Applications include implementing
306
 * matrix transposition as well as changing between row-major and column-major storage formats.
307
 *
308
 * \param dst Data will be copied into this vector. It must have length m-by-n. It will not be resized.
309
 * \param src Vector containing the data to be copied. It is assumed to have length m-by-n.
310
 *   Must not be the same as \p dst .
311
 * \param m The size of contiguous blocks. This is the number of columns when using column-major
312
 *   storage format, or the number of rows when using row-major format.
313
 * \param n The number of blocks. This is the number of rows when using column-major format,
314
 *   or the number of columns when using row-major format.
315
 */
316
static void FUNCTION(igraph_i, transpose_copy)(
317
        TYPE(igraph_vector) *dst, const TYPE(igraph_vector) *src,
318
0
        size_t m, size_t n) {
319
320
0
    IGRAPH_ASSERT(dst != src);
321
322
    /* Block size of 4 was found to yield the best performance when benchmarking with:
323
     *  - Intel Core i7-7920HQ on macOS.
324
     *  - AMD Ryzen Threadripper 3990X on Linux.
325
     */
326
0
    const size_t blocksize = 4;
327
0
    for (size_t i=0; i < m; i += blocksize) {
328
0
        for (size_t j=0; j < n; j++) {
329
0
            for (size_t k=0; k < blocksize && i+k < m; k++) {
330
0
                VECTOR(*dst)[j + (i+k)*n] = VECTOR(*src)[i+k + j*m];
331
0
            }
332
0
        }
333
0
    }
334
0
}
Unexecuted instantiation: matrix.c:igraph_i_transpose_copy
Unexecuted instantiation: matrix.c:igraph_i_int_transpose_copy
Unexecuted instantiation: matrix.c:igraph_i_char_transpose_copy
Unexecuted instantiation: matrix.c:igraph_i_bool_transpose_copy
Unexecuted instantiation: matrix.c:igraph_i_complex_transpose_copy
335
336
/**
337
 * \ingroup matrix
338
 * \function igraph_matrix_copy_to
339
 * \brief Copies a matrix to a regular C array.
340
 *
341
 * </para><para>
342
 * The C array should be of sufficient size; there are (of course) no
343
 * range checks.
344
 *
345
 * \param m Pointer to an initialized matrix object.
346
 * \param to Pointer to a C array; the place to copy the data to.
347
 * \param storage \c IGRAPH_ROW_MAJOR to write the data in row-major format,
348
 *    \c IGRAPH_COLUMN_MAJOR to write it in column-major format. Currently
349
 *    igraph uses column-major storage internally, thus \c IGRAPH_COLUMN_MAJOR
350
 *    is much faster.
351
 * \return Error code.
352
 *
353
 * Time complexity: O(n),
354
 * n is the number of
355
 * elements in the matrix.
356
 */
357
0
void FUNCTION(igraph_matrix, copy_to)(const TYPE(igraph_matrix) *m, BASE *to, igraph_matrix_storage_t storage) {
358
0
    if (storage == IGRAPH_ROW_MAJOR) {
359
0
        TYPE(igraph_vector) dst = FUNCTION(igraph_vector, view)(to, m->nrow * m->ncol);
360
0
        FUNCTION(igraph_i, transpose_copy)(&dst, &m->data, m->nrow, m->ncol);
361
0
    } else if (storage == IGRAPH_COLUMN_MAJOR) {
362
0
        FUNCTION(igraph_vector, copy_to)(&m->data, to);
363
0
    } else {
364
0
        IGRAPH_FATAL("Invalid matrix storage format.");
365
0
    }
366
0
}
Unexecuted instantiation: igraph_matrix_copy_to
Unexecuted instantiation: igraph_matrix_int_copy_to
Unexecuted instantiation: igraph_matrix_char_copy_to
Unexecuted instantiation: igraph_matrix_bool_copy_to
Unexecuted instantiation: igraph_matrix_complex_copy_to
367
368
/**
369
 * \ingroup matrix
370
 * \function igraph_matrix_null
371
 * \brief Sets all elements in a matrix to zero.
372
 *
373
 * \param m Pointer to an initialized matrix object.
374
 *
375
 * Time complexity: O(n),
376
 * n is the number of elements in
377
 * the matrix.
378
 */
379
380
29.9k
void FUNCTION(igraph_matrix, null)(TYPE(igraph_matrix) *m) {
381
29.9k
    FUNCTION(igraph_vector, null)(&m->data);
382
29.9k
}
igraph_matrix_null
Line
Count
Source
380
22.9k
void FUNCTION(igraph_matrix, null)(TYPE(igraph_matrix) *m) {
381
22.9k
    FUNCTION(igraph_vector, null)(&m->data);
382
22.9k
}
igraph_matrix_int_null
Line
Count
Source
380
6.98k
void FUNCTION(igraph_matrix, null)(TYPE(igraph_matrix) *m) {
381
6.98k
    FUNCTION(igraph_vector, null)(&m->data);
382
6.98k
}
Unexecuted instantiation: igraph_matrix_char_null
Unexecuted instantiation: igraph_matrix_bool_null
Unexecuted instantiation: igraph_matrix_complex_null
383
384
/**
385
 * \ingroup matrix
386
 * \function igraph_matrix_add_cols
387
 * \brief Adds columns to a matrix.
388
 * \param m The matrix object.
389
 * \param n The number of columns to add.
390
 * \return Error code, \c IGRAPH_ENOMEM if there is
391
 *   not enough memory to perform the operation.
392
 *
393
 * Time complexity: linear with the number of elements of the new,
394
 * resized matrix.
395
 */
396
397
0
igraph_error_t FUNCTION(igraph_matrix, add_cols)(TYPE(igraph_matrix) *m, igraph_int_t n) {
398
0
    igraph_int_t new_ncol;
399
0
    IGRAPH_SAFE_ADD(m->ncol, n, &new_ncol);
400
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(m, m->nrow, new_ncol));
401
0
    return IGRAPH_SUCCESS;
402
0
}
Unexecuted instantiation: igraph_matrix_add_cols
Unexecuted instantiation: igraph_matrix_int_add_cols
Unexecuted instantiation: igraph_matrix_char_add_cols
Unexecuted instantiation: igraph_matrix_bool_add_cols
Unexecuted instantiation: igraph_matrix_complex_add_cols
403
404
/**
405
 * \ingroup matrix
406
 * \function igraph_matrix_add_rows
407
 * \brief Adds rows to a matrix.
408
 * \param m The matrix object.
409
 * \param n The number of rows to add.
410
 * \return Error code, \c IGRAPH_ENOMEM if there
411
 *   isn't enough memory for the operation.
412
 *
413
 * Time complexity: linear with the number of elements of the new,
414
 * resized matrix.
415
 */
416
417
8.90k
igraph_error_t FUNCTION(igraph_matrix, add_rows)(TYPE(igraph_matrix) *m, igraph_int_t n) {
418
8.90k
    igraph_int_t new_nrow, new_size;
419
8.90k
    IGRAPH_SAFE_ADD(m->nrow, n, &new_nrow);
420
8.90k
    IGRAPH_SAFE_MULT(m->ncol, new_nrow, &new_size);
421
8.90k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, new_size));
422
440k
    for (igraph_int_t i = m->ncol - 1; i >= 0; i--) {
423
431k
        FUNCTION(igraph_vector, move_interval)(&m->data, (m->nrow)*i, (m->nrow) * (i + 1),
424
431k
                                                new_nrow * i);
425
431k
    }
426
8.90k
    m->nrow = new_nrow;
427
8.90k
    return IGRAPH_SUCCESS;
428
8.90k
}
Unexecuted instantiation: igraph_matrix_add_rows
igraph_matrix_int_add_rows
Line
Count
Source
417
8.90k
igraph_error_t FUNCTION(igraph_matrix, add_rows)(TYPE(igraph_matrix) *m, igraph_int_t n) {
418
8.90k
    igraph_int_t new_nrow, new_size;
419
8.90k
    IGRAPH_SAFE_ADD(m->nrow, n, &new_nrow);
420
8.90k
    IGRAPH_SAFE_MULT(m->ncol, new_nrow, &new_size);
421
8.90k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, new_size));
422
440k
    for (igraph_int_t i = m->ncol - 1; i >= 0; i--) {
423
431k
        FUNCTION(igraph_vector, move_interval)(&m->data, (m->nrow)*i, (m->nrow) * (i + 1),
424
431k
                                                new_nrow * i);
425
431k
    }
426
8.90k
    m->nrow = new_nrow;
427
8.90k
    return IGRAPH_SUCCESS;
428
8.90k
}
Unexecuted instantiation: igraph_matrix_char_add_rows
Unexecuted instantiation: igraph_matrix_bool_add_rows
Unexecuted instantiation: igraph_matrix_complex_add_rows
429
430
/**
431
 * \ingroup matrix
432
 * \function igraph_matrix_remove_col
433
 * \brief Removes a column from a matrix.
434
 *
435
 * \param m The matrix object.
436
 * \param col The column to remove.
437
 * \return Error code, always returns with success.
438
 *
439
 * Time complexity: linear with the number of elements of the new,
440
 * resized matrix.
441
 */
442
443
0
igraph_error_t FUNCTION(igraph_matrix, remove_col)(TYPE(igraph_matrix) *m, igraph_int_t col) {
444
0
    FUNCTION(igraph_vector, remove_section)(&m->data, (m->nrow)*col, (m->nrow) * (col + 1));
445
0
    m->ncol--;
446
0
    return IGRAPH_SUCCESS;
447
0
}
Unexecuted instantiation: igraph_matrix_remove_col
Unexecuted instantiation: igraph_matrix_int_remove_col
Unexecuted instantiation: igraph_matrix_char_remove_col
Unexecuted instantiation: igraph_matrix_bool_remove_col
Unexecuted instantiation: igraph_matrix_complex_remove_col
448
449
/**
450
 * \ingroup matrix
451
 * \function igraph_matrix_permdelete_rows
452
 * \brief Removes rows from a matrix (for internal use).
453
 *
454
 * Time complexity: linear with the number of elements of the original
455
 * matrix.
456
 */
457
458
igraph_error_t FUNCTION(igraph_matrix, permdelete_rows)(
459
6.22k
        TYPE(igraph_matrix) *m, igraph_int_t *index, igraph_int_t nremove) {
460
6.22k
    igraph_int_t i, j;
461
309k
    for (j = 0; j < m->nrow; j++) {
462
303k
        if (index[j] != 0) {
463
234k
            for (i = 0; i < m->ncol; i++) {
464
156k
                MATRIX(*m, index[j] - 1, i) = MATRIX(*m, j, i);
465
156k
            }
466
78.2k
        }
467
303k
    }
468
    /* Remove unnecessary elements from the end of each column */
469
18.6k
    for (i = 0; i < m->ncol; i++)
470
12.4k
        FUNCTION(igraph_vector, remove_section)(&m->data,
471
12.4k
                                                (i + 1) * (m->nrow - nremove), (i + 1) * (m->nrow - nremove) + nremove);
472
6.22k
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(m, m->nrow - nremove, m->ncol));
473
474
6.22k
    return IGRAPH_SUCCESS;
475
6.22k
}
Unexecuted instantiation: igraph_matrix_permdelete_rows
igraph_matrix_int_permdelete_rows
Line
Count
Source
459
6.22k
        TYPE(igraph_matrix) *m, igraph_int_t *index, igraph_int_t nremove) {
460
6.22k
    igraph_int_t i, j;
461
309k
    for (j = 0; j < m->nrow; j++) {
462
303k
        if (index[j] != 0) {
463
234k
            for (i = 0; i < m->ncol; i++) {
464
156k
                MATRIX(*m, index[j] - 1, i) = MATRIX(*m, j, i);
465
156k
            }
466
78.2k
        }
467
303k
    }
468
    /* Remove unnecessary elements from the end of each column */
469
18.6k
    for (i = 0; i < m->ncol; i++)
470
12.4k
        FUNCTION(igraph_vector, remove_section)(&m->data,
471
12.4k
                                                (i + 1) * (m->nrow - nremove), (i + 1) * (m->nrow - nremove) + nremove);
472
6.22k
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(m, m->nrow - nremove, m->ncol));
473
474
6.22k
    return IGRAPH_SUCCESS;
475
6.22k
}
Unexecuted instantiation: igraph_matrix_char_permdelete_rows
Unexecuted instantiation: igraph_matrix_bool_permdelete_rows
Unexecuted instantiation: igraph_matrix_complex_permdelete_rows
476
477
/**
478
 * \ingroup matrix
479
 * \function igraph_matrix_init_array
480
 * \brief Initializes a matrix from an ordinary C array (constructor).
481
 *
482
 * The array is assumed to store the matrix data contiguously, either in
483
 * a column-major or row-major format. In other words, \p data may
484
 * store concatenated matrix columns or concatenated matrix rows.
485
 * Constructing a matrix from column-major data is faster, as this is
486
 * igraph's native storage format.
487
 *
488
 * \param v Pointer to an uninitialized matrix object.
489
 * \param data A regular C array, storing the elements of the matrix in
490
 *        column-major order, i.e. the elements of the first column are stored
491
 *        first, followed by the second column and so on.
492
 * \param nrow The number of rows in the matrix.
493
 * \param ncol The number of columns in the matrix.
494
 * \param storage \c IGRAPH_ROW_MAJOR if the array is in row-major format,
495
          \c IGRAPH_COLUMN_MAJOR if the array is in column-major format.
496
 * \return Error code:
497
 *         \c IGRAPH_ENOMEM if there is not enough memory.
498
 *
499
 * Time complexity: operating system specific, usually
500
 * O(\p nrow \p ncol).
501
 */
502
503
igraph_error_t FUNCTION(igraph_matrix, init_array)(
504
        TYPE(igraph_matrix) *m, const BASE *data,
505
        igraph_int_t nrow, igraph_int_t ncol,
506
0
        igraph_matrix_storage_t storage) {
507
508
0
    igraph_int_t length;
509
0
    IGRAPH_SAFE_MULT(nrow, ncol, &length);
510
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, init)(m, nrow, ncol));
511
0
    const TYPE(igraph_vector) v = FUNCTION(igraph_vector, view)(data, length);
512
513
0
    if (storage == IGRAPH_COLUMN_MAJOR) {
514
0
        IGRAPH_CHECK(FUNCTION(igraph_vector, update)(&m->data, &v));
515
0
    } else if (storage == IGRAPH_ROW_MAJOR) {
516
0
        FUNCTION(igraph_i, transpose_copy)(&m->data, &v, ncol, nrow);
517
0
    } else {
518
0
        IGRAPH_ERROR("Invalid storage type argument.", IGRAPH_EINVAL);
519
0
    }
520
521
0
    return IGRAPH_SUCCESS;
522
0
}
Unexecuted instantiation: igraph_matrix_init_array
Unexecuted instantiation: igraph_matrix_int_init_array
Unexecuted instantiation: igraph_matrix_char_init_array
Unexecuted instantiation: igraph_matrix_bool_init_array
Unexecuted instantiation: igraph_matrix_complex_init_array
523
524
/**
525
 * \ingroup matrix
526
 * \function igraph_matrix_init_copy
527
 * \brief Copies a matrix.
528
 *
529
 * </para><para>
530
 * Creates a matrix object by copying from an existing matrix.
531
 * \param to Pointer to an uninitialized matrix object.
532
 * \param from The initialized matrix object to copy.
533
 * \return Error code, \c IGRAPH_ENOMEM if there
534
 *   isn't enough memory to allocate the new matrix.
535
 *
536
 * Time complexity: O(n), the number
537
 * of elements in the matrix.
538
 */
539
540
0
igraph_error_t FUNCTION(igraph_matrix, init_copy)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from) {
541
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, init_copy)(&to->data, &from->data));
542
0
    to->nrow = from->nrow;
543
0
    to->ncol = from->ncol;
544
0
    return IGRAPH_SUCCESS;
545
0
}
Unexecuted instantiation: igraph_matrix_init_copy
Unexecuted instantiation: igraph_matrix_int_init_copy
Unexecuted instantiation: igraph_matrix_char_init_copy
Unexecuted instantiation: igraph_matrix_bool_init_copy
Unexecuted instantiation: igraph_matrix_complex_init_copy
546
547
#ifndef NOTORDERED
548
549
/**
550
 * \function igraph_matrix_max
551
 * \brief Largest element of a matrix.
552
 *
553
 * </para><para>
554
 * If the matrix is empty, an arbitrary number is returned.
555
 * \param m The matrix object.
556
 * \return The maximum element of \p m, or NaN if any element is NaN.
557
 *
558
 * Added in version 0.2.</para><para>
559
 *
560
 * Time complexity: O(mn), the number of elements in the matrix.
561
 */
562
563
0
igraph_real_t FUNCTION(igraph_matrix, max)(const TYPE(igraph_matrix) *m) {
564
0
    return FUNCTION(igraph_vector, max)(&m->data);
565
0
}
Unexecuted instantiation: igraph_matrix_max
Unexecuted instantiation: igraph_matrix_int_max
Unexecuted instantiation: igraph_matrix_char_max
566
567
#endif
568
569
/**
570
 * \function igraph_matrix_scale
571
 *
572
 * Multiplies each element of the matrix by a constant.
573
 * \param m The matrix.
574
 * \param by The constant.
575
 *
576
 * Added in version 0.2.</para><para>
577
 *
578
 * Time complexity: O(n), the number of elements in the matrix.
579
 */
580
581
3.02k
void FUNCTION(igraph_matrix, scale)(TYPE(igraph_matrix) *m, BASE by) {
582
3.02k
    FUNCTION(igraph_vector, scale)(&m->data, by);
583
3.02k
}
igraph_matrix_scale
Line
Count
Source
581
3.02k
void FUNCTION(igraph_matrix, scale)(TYPE(igraph_matrix) *m, BASE by) {
582
3.02k
    FUNCTION(igraph_vector, scale)(&m->data, by);
583
3.02k
}
Unexecuted instantiation: igraph_matrix_int_scale
Unexecuted instantiation: igraph_matrix_char_scale
Unexecuted instantiation: igraph_matrix_bool_scale
Unexecuted instantiation: igraph_matrix_complex_scale
584
585
/**
586
 * \function igraph_matrix_select_rows
587
 * \brief Selects some rows of a matrix.
588
 *
589
 * This function selects some rows of a matrix and returns them in a
590
 * new matrix. The result matrix should be initialized before calling
591
 * the function.
592
 * \param m The input matrix.
593
 * \param res The result matrix. It should be initialized and will be
594
 *    resized as needed.
595
 * \param rows Vector; it contains the row indices (starting with
596
 *    zero) to extract. Note that no range checking is performed.
597
 * \return Error code.
598
 *
599
 * Time complexity: O(nm), n is the number of rows, m the number of
600
 * columns of the result matrix.
601
 */
602
603
igraph_error_t FUNCTION(igraph_matrix, select_rows)(const TYPE(igraph_matrix) *m,
604
        TYPE(igraph_matrix) *res,
605
0
        const igraph_vector_int_t *rows) {
606
0
    igraph_int_t norows = igraph_vector_int_size(rows);
607
0
    igraph_int_t i, j, ncols = FUNCTION(igraph_matrix, ncol)(m);
608
609
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, norows, ncols));
610
    /* Iterate in column-major order for better performance. */
611
0
    for (j = 0; j < ncols; j++) {
612
0
        for (i = 0; i < norows; i++) {
613
0
            MATRIX(*res, i, j) = MATRIX(*m, VECTOR(*rows)[i], j);
614
0
        }
615
0
    }
616
617
0
    return IGRAPH_SUCCESS;
618
0
}
Unexecuted instantiation: igraph_matrix_select_rows
Unexecuted instantiation: igraph_matrix_int_select_rows
Unexecuted instantiation: igraph_matrix_char_select_rows
Unexecuted instantiation: igraph_matrix_bool_select_rows
Unexecuted instantiation: igraph_matrix_complex_select_rows
619
620
/**
621
 * \function igraph_matrix_select_rows_cols
622
 * \brief Selects some rows and columns of a matrix.
623
 *
624
 * This function selects some rows and columns of a matrix and returns
625
 * them in a new matrix. The result matrix should be initialized before
626
 * calling the function.
627
 * \param m The input matrix.
628
 * \param res The result matrix. It should be initialized and will be
629
 *    resized as needed.
630
 * \param rows Vector; it contains the row indices (starting with
631
 *    zero) to extract. Note that no range checking is performed.
632
 * \param cols Vector; it contains the column indices (starting with
633
 *    zero) to extract. Note that no range checking is performed.
634
 * \return Error code.
635
 *
636
 * Time complexity: O(nm), n is the number of rows, m the number of
637
 * columns of the result matrix.
638
 */
639
640
igraph_error_t FUNCTION(igraph_matrix, select_rows_cols)(const TYPE(igraph_matrix) *m,
641
        TYPE(igraph_matrix) *res,
642
        const igraph_vector_int_t *rows,
643
0
        const igraph_vector_int_t *cols) {
644
0
    igraph_int_t nrows = igraph_vector_int_size(rows);
645
0
    igraph_int_t ncols = igraph_vector_int_size(cols);
646
0
    igraph_int_t i, j;
647
648
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, nrows, ncols));
649
    /* Iterate in column-major order for better performance. */
650
0
    for (j = 0; j < ncols; j++) {
651
0
        for (i = 0; i < nrows; i++) {
652
0
            MATRIX(*res, i, j) = MATRIX(*m, VECTOR(*rows)[i], VECTOR(*cols)[j]);
653
0
        }
654
0
    }
655
656
0
    return IGRAPH_SUCCESS;
657
0
}
Unexecuted instantiation: igraph_matrix_select_rows_cols
Unexecuted instantiation: igraph_matrix_int_select_rows_cols
Unexecuted instantiation: igraph_matrix_char_select_rows_cols
Unexecuted instantiation: igraph_matrix_bool_select_rows_cols
Unexecuted instantiation: igraph_matrix_complex_select_rows_cols
658
659
/**
660
 * \function igraph_matrix_get_col
661
 * \brief Selects a column.
662
 *
663
 * Extract a column of a matrix and return it as a vector.
664
 * \param m The input matrix.
665
 * \param res The result will be stored in this vector. It should be
666
 *   initialized and will be resized as needed.
667
 * \param index The index of the column to select.
668
 * \return Error code.
669
 *
670
 * Time complexity: O(n), the number of rows in the matrix.
671
 */
672
673
igraph_error_t FUNCTION(igraph_matrix, get_col)(const TYPE(igraph_matrix) *m,
674
                                     TYPE(igraph_vector) *res,
675
0
                                     igraph_int_t index) {
676
0
    igraph_int_t nrow = FUNCTION(igraph_matrix, nrow)(m);
677
678
0
    if (index >= m->ncol) {
679
0
        IGRAPH_ERROR("Index out of range for selecting matrix column.", IGRAPH_EINVAL);
680
0
    }
681
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, get_interval)(&m->data, res,
682
0
                 nrow * index, nrow * (index + 1)));
683
0
    return IGRAPH_SUCCESS;
684
0
}
Unexecuted instantiation: igraph_matrix_get_col
Unexecuted instantiation: igraph_matrix_int_get_col
Unexecuted instantiation: igraph_matrix_char_get_col
Unexecuted instantiation: igraph_matrix_bool_get_col
Unexecuted instantiation: igraph_matrix_complex_get_col
685
686
/**
687
 * \function igraph_matrix_sum
688
 * \brief Sum of elements.
689
 *
690
 * Returns the sum of the elements of a matrix.
691
 * \param m The input matrix.
692
 * \return The sum of the elements.
693
 *
694
 * Time complexity: O(mn), the number of elements in the matrix.
695
 */
696
697
0
BASE FUNCTION(igraph_matrix, sum)(const TYPE(igraph_matrix) *m) {
698
0
    return FUNCTION(igraph_vector, sum)(&m->data);
699
0
}
Unexecuted instantiation: igraph_matrix_sum
Unexecuted instantiation: igraph_matrix_int_sum
Unexecuted instantiation: igraph_matrix_char_sum
Unexecuted instantiation: igraph_matrix_bool_sum
Unexecuted instantiation: igraph_matrix_complex_sum
700
701
/**
702
 * \function igraph_matrix_all_e
703
 * \brief Are all elements equal?
704
 *
705
 * Checks element-wise equality of two matrices. For matrices containing floating
706
 * point values, consider using \ref igraph_matrix_all_almost_e().
707
 *
708
 * \param lhs The first matrix.
709
 * \param rhs The second matrix.
710
 * \return True if the elements in the \p lhs are all
711
 *    equal to the corresponding elements in \p rhs. Returns false
712
 *    if the dimensions of the matrices don't match.
713
 *
714
 * Time complexity: O(nm), the size of the matrices.
715
 */
716
717
igraph_bool_t FUNCTION(igraph_matrix, all_e)(const TYPE(igraph_matrix) *lhs,
718
0
        const TYPE(igraph_matrix) *rhs) {
719
0
    return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow &&
720
0
           FUNCTION(igraph_vector, all_e)(&lhs->data, &rhs->data);
721
0
}
Unexecuted instantiation: igraph_matrix_all_e
Unexecuted instantiation: igraph_matrix_int_all_e
Unexecuted instantiation: igraph_matrix_char_all_e
Unexecuted instantiation: igraph_matrix_bool_all_e
Unexecuted instantiation: igraph_matrix_complex_all_e
722
723
igraph_bool_t
724
FUNCTION(igraph_matrix, is_equal)(const TYPE(igraph_matrix) *lhs,
725
0
                                  const TYPE(igraph_matrix) *rhs) {
726
0
    return FUNCTION(igraph_matrix, all_e)(lhs, rhs);
727
0
}
Unexecuted instantiation: igraph_matrix_is_equal
Unexecuted instantiation: igraph_matrix_int_is_equal
Unexecuted instantiation: igraph_matrix_char_is_equal
Unexecuted instantiation: igraph_matrix_bool_is_equal
Unexecuted instantiation: igraph_matrix_complex_is_equal
728
729
#ifndef NOTORDERED
730
731
/**
732
 * \function igraph_matrix_all_l
733
 * \brief Are all elements less?
734
 *
735
 * \param lhs The first matrix.
736
 * \param rhs The second matrix.
737
 * \return True if the elements in the \p lhs are all
738
 *    less than the corresponding elements in \p rhs. Returns false
739
 *    if the dimensions of the matrices don't match.
740
 *
741
 * Time complexity: O(nm), the size of the matrices.
742
 */
743
744
igraph_bool_t FUNCTION(igraph_matrix, all_l)(const TYPE(igraph_matrix) *lhs,
745
0
        const TYPE(igraph_matrix) *rhs) {
746
0
    return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow &&
747
0
           FUNCTION(igraph_vector, all_l)(&lhs->data, &rhs->data);
748
0
}
Unexecuted instantiation: igraph_matrix_all_l
Unexecuted instantiation: igraph_matrix_int_all_l
Unexecuted instantiation: igraph_matrix_char_all_l
749
750
/**
751
 * \function igraph_matrix_all_g
752
 * \brief Are all elements greater?
753
 *
754
 * \param lhs The first matrix.
755
 * \param rhs The second matrix.
756
 * \return True if the elements in the \p lhs are all
757
 *    greater than the corresponding elements in \p rhs. Returns false
758
 *    if the dimensions of the matrices don't match.
759
 *
760
 * Time complexity: O(nm), the size of the matrices.
761
 */
762
763
igraph_bool_t FUNCTION(igraph_matrix, all_g)(const TYPE(igraph_matrix) *lhs,
764
0
        const TYPE(igraph_matrix) *rhs) {
765
0
    return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow &&
766
0
           FUNCTION(igraph_vector, all_g)(&lhs->data, &rhs->data);
767
0
}
Unexecuted instantiation: igraph_matrix_all_g
Unexecuted instantiation: igraph_matrix_int_all_g
Unexecuted instantiation: igraph_matrix_char_all_g
768
769
/**
770
 * \function igraph_matrix_all_le
771
 * \brief Are all elements less or equal?
772
 *
773
 * \param lhs The first matrix.
774
 * \param rhs The second matrix.
775
 * \return True if the elements in the \p lhs are all
776
 *    less than or equal to the corresponding elements in \p
777
 *    rhs. Returns false if the dimensions of the matrices
778
 *    don't match.
779
 *
780
 * Time complexity: O(nm), the size of the matrices.
781
 */
782
783
igraph_bool_t
784
FUNCTION(igraph_matrix, all_le)(const TYPE(igraph_matrix) *lhs,
785
0
                                const TYPE(igraph_matrix) *rhs) {
786
0
    return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow &&
787
0
           FUNCTION(igraph_vector, all_le)(&lhs->data, &rhs->data);
788
0
}
Unexecuted instantiation: igraph_matrix_all_le
Unexecuted instantiation: igraph_matrix_int_all_le
Unexecuted instantiation: igraph_matrix_char_all_le
789
790
/**
791
 * \function igraph_matrix_all_ge
792
 * \brief Are all elements greater or equal?
793
 *
794
 * \param lhs The first matrix.
795
 * \param rhs The second matrix.
796
 * \return True if the elements in the \p lhs are all
797
 *    greater than or equal to the corresponding elements in \p
798
 *    rhs. Returns false if the dimensions of the matrices
799
 *    don't match.
800
 *
801
 * Time complexity: O(nm), the size of the matrices.
802
 */
803
804
igraph_bool_t
805
FUNCTION(igraph_matrix, all_ge)(const TYPE(igraph_matrix) *lhs,
806
0
                                const TYPE(igraph_matrix) *rhs) {
807
0
    return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow &&
808
0
           FUNCTION(igraph_vector, all_ge)(&lhs->data, &rhs->data);
809
0
}
Unexecuted instantiation: igraph_matrix_all_ge
Unexecuted instantiation: igraph_matrix_int_all_ge
Unexecuted instantiation: igraph_matrix_char_all_ge
810
811
#endif
812
813
#ifndef NOTORDERED
814
815
/**
816
 * \function igraph_matrix_maxdifference
817
 * \brief Maximum absolute difference between two matrices.
818
 *
819
 * Calculate the maximum absolute difference of two matrices. Both matrices
820
 * must be non-empty. If their dimensions differ then a warning is given and
821
 * the comparison is performed by vectors columnwise from both matrices.
822
 * The remaining elements in the larger vector are ignored.
823
 * \param m1 The first matrix.
824
 * \param m2 The second matrix.
825
 * \return The element with the largest absolute value in \c m1 - \c m2.
826
 *
827
 * Time complexity: O(mn), the elements in the smaller matrix.
828
 */
829
830
igraph_real_t FUNCTION(igraph_matrix, maxdifference)(const TYPE(igraph_matrix) *m1,
831
0
        const TYPE(igraph_matrix) *m2) {
832
0
    if (m1->ncol != m2->ncol || m1->nrow != m2->nrow) {
833
0
        IGRAPH_WARNING("Comparing non-conformant matrices.");
834
0
    }
835
0
    return FUNCTION(igraph_vector, maxdifference)(&m1->data, &m2->data);
836
0
}
Unexecuted instantiation: igraph_matrix_maxdifference
Unexecuted instantiation: igraph_matrix_int_maxdifference
Unexecuted instantiation: igraph_matrix_char_maxdifference
837
838
#endif
839
840
0
#define SWAP(TYPE,a,b) do { TYPE igraph_i_tmp = (a); (a) = (b); (b) = igraph_i_tmp; } while (0)
841
842
/**
843
 * \function igraph_matrix_transpose
844
 * \brief Transpose of a matrix.
845
 *
846
 * Calculates the transpose of a matrix. When the matrix is non-square,
847
 * this function reallocates the storage used for the matrix.
848
 *
849
 * \param m The input (and output) matrix.
850
 * \return Error code.
851
 *
852
 * Time complexity: O(mn), the number of elements in the matrix.
853
 */
854
855
0
igraph_error_t FUNCTION(igraph_matrix, transpose)(TYPE(igraph_matrix) *m) {
856
0
    if (m->nrow > 1 && m->ncol > 1) {
857
0
        if (m->nrow == m->ncol) {
858
            /* In-place transpose for square matrices. */
859
860
            /* Block size of 4 was found to yield the best performance during benchmarking,
861
             * see igraph_i_transpose_copy() */
862
0
            const size_t blocksize = 4;
863
0
            const size_t n = m->nrow;
864
0
            size_t k=0;
865
0
            for (k=0; k + blocksize - 1 < n; k += blocksize) {
866
0
                for (size_t i = k; i < k + blocksize; ++i) {
867
0
                    for (size_t j = i + 1; j < k + blocksize; ++j) {
868
0
                        SWAP(BASE, VECTOR(m->data)[j + i*n], VECTOR(m->data)[i + j*n]);
869
0
                    }
870
0
                }
871
0
                for (size_t i = k + blocksize; i < n; ++i) {
872
0
                    for (size_t j = k; j < k + blocksize; ++j) {
873
0
                        SWAP(BASE, VECTOR(m->data)[j + i*n], VECTOR(m->data)[i + j*n]);
874
0
                    }
875
0
                }
876
0
            }
877
0
            for (size_t i = k; i < n; ++i) {
878
0
                for (size_t j = i + 1; j < n; ++j) {
879
0
                    SWAP(BASE, VECTOR(m->data)[j + i*n], VECTOR(m->data)[i + j*n]);
880
0
                }
881
0
            }
882
0
        } else {
883
            /* Allocate new storage for non-square matrices. */
884
0
            TYPE(igraph_vector) newdata;
885
0
            IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&newdata, m->nrow * m->ncol));
886
0
            FUNCTION(igraph_i, transpose_copy)(&newdata, &m->data, m->nrow, m->ncol);
887
0
            FUNCTION(igraph_vector, destroy)(&m->data);
888
0
            m->data = newdata;
889
0
        }
890
0
    }
891
892
0
    SWAP(igraph_int_t, m->nrow, m->ncol);
893
894
0
    return IGRAPH_SUCCESS;
895
0
}
Unexecuted instantiation: igraph_matrix_transpose
Unexecuted instantiation: igraph_matrix_int_transpose
Unexecuted instantiation: igraph_matrix_char_transpose
Unexecuted instantiation: igraph_matrix_bool_transpose
Unexecuted instantiation: igraph_matrix_complex_transpose
896
897
#undef SWAP
898
899
/**
900
 * \function igraph_matrix_get
901
 * Extract an element from a matrix.
902
 *
903
 * Use this if you need a function for some reason and cannot use the
904
 * \ref MATRIX macro. Note that no range checking is performed.
905
 * \param m The input matrix.
906
 * \param row The row index.
907
 * \param col The column index.
908
 * \return The element in the given row and column.
909
 *
910
 * Time complexity: O(1).
911
 */
912
913
BASE FUNCTION(igraph_matrix, get)(const TYPE(igraph_matrix) *m,
914
0
                                igraph_int_t row, igraph_int_t col) {
915
0
    return MATRIX(*m, row, col);
916
0
}
Unexecuted instantiation: igraph_matrix_get
Unexecuted instantiation: igraph_matrix_int_get
Unexecuted instantiation: igraph_matrix_char_get
Unexecuted instantiation: igraph_matrix_bool_get
Unexecuted instantiation: igraph_matrix_complex_get
917
918
/**
919
 * \function igraph_matrix_get_ptr
920
 * Pointer to an element of a matrix.
921
 *
922
 * The function returns a pointer to an element. No range checking is
923
 * performed.
924
 * \param m The input matrix.
925
 * \param row The row index.
926
 * \param col The column index.
927
 * \return Pointer to the element in the given row and column.
928
 *
929
 * Time complexity: O(1).
930
 */
931
932
BASE* FUNCTION(igraph_matrix, get_ptr)(const TYPE(igraph_matrix) *m,
933
0
                                       igraph_int_t row, igraph_int_t col) {
934
0
    return &MATRIX(*m, row, col);
935
0
}
Unexecuted instantiation: igraph_matrix_get_ptr
Unexecuted instantiation: igraph_matrix_int_get_ptr
Unexecuted instantiation: igraph_matrix_char_get_ptr
Unexecuted instantiation: igraph_matrix_bool_get_ptr
Unexecuted instantiation: igraph_matrix_complex_get_ptr
936
937
/**
938
 * \function igraph_matrix_set
939
 * Set an element.
940
 *
941
 * Set an element of a matrix. No range checking is performed.
942
 * \param m The input matrix.
943
 * \param row The row index.
944
 * \param col The column index.
945
 * \param value The new value of the element.
946
 *
947
 * Time complexity: O(1).
948
 */
949
950
void FUNCTION(igraph_matrix, set)(
951
        TYPE(igraph_matrix)* m, igraph_int_t row, igraph_int_t col,
952
0
        BASE value) {
953
0
    MATRIX(*m, row, col) = value;
954
0
}
Unexecuted instantiation: igraph_matrix_set
Unexecuted instantiation: igraph_matrix_int_set
Unexecuted instantiation: igraph_matrix_char_set
Unexecuted instantiation: igraph_matrix_bool_set
Unexecuted instantiation: igraph_matrix_complex_set
955
956
/**
957
 * \function igraph_matrix_fill
958
 * Fill with an element.
959
 *
960
 * Set the matrix to a constant matrix.
961
 * \param m The input matrix.
962
 * \param e The element to set.
963
 *
964
 * Time complexity: O(mn), the number of elements.
965
 */
966
967
10.6k
void FUNCTION(igraph_matrix, fill)(TYPE(igraph_matrix) *m, BASE e) {
968
10.6k
    FUNCTION(igraph_vector, fill)(&m->data, e);
969
10.6k
}
igraph_matrix_fill
Line
Count
Source
967
10.6k
void FUNCTION(igraph_matrix, fill)(TYPE(igraph_matrix) *m, BASE e) {
968
10.6k
    FUNCTION(igraph_vector, fill)(&m->data, e);
969
10.6k
}
Unexecuted instantiation: igraph_matrix_int_fill
Unexecuted instantiation: igraph_matrix_char_fill
Unexecuted instantiation: igraph_matrix_bool_fill
Unexecuted instantiation: igraph_matrix_complex_fill
970
971
/**
972
 * \function igraph_matrix_update
973
 * Update from another matrix.
974
 *
975
 * This function replicates \p from in the matrix \p to.
976
 * Note that \p to must be already initialized.
977
 * \param to The result matrix.
978
 * \param from The matrix to replicate; it is left unchanged.
979
 * \return Error code.
980
 *
981
 * Time complexity: O(mn), the number of elements.
982
 */
983
984
igraph_error_t FUNCTION(igraph_matrix, update)(TYPE(igraph_matrix) *to,
985
0
                                    const TYPE(igraph_matrix) *from) {
986
987
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(to, from->nrow, from->ncol));
988
0
    FUNCTION(igraph_vector, update)(&to->data, &from->data); /* reserved */
989
0
    return IGRAPH_SUCCESS;
990
0
}
Unexecuted instantiation: igraph_matrix_update
Unexecuted instantiation: igraph_matrix_int_update
Unexecuted instantiation: igraph_matrix_char_update
Unexecuted instantiation: igraph_matrix_bool_update
Unexecuted instantiation: igraph_matrix_complex_update
991
992
/**
993
 * \function igraph_matrix_rbind
994
 * Combine two matrices rowwise.
995
 *
996
 * This function places the rows of \p from below the rows of \c to
997
 * and stores the result in \p to. The number of columns in the two
998
 * matrices must match.
999
 * \param to The upper matrix; the result is also stored here.
1000
 * \param from The lower matrix. It is left unchanged.
1001
 * \return Error code.
1002
 *
1003
 * Time complexity: O(mn), the number of elements in the newly created
1004
 * matrix.
1005
 */
1006
1007
igraph_error_t FUNCTION(igraph_matrix, rbind)(TYPE(igraph_matrix) *to,
1008
0
                                   const TYPE(igraph_matrix) *from) {
1009
0
    igraph_int_t tocols = to->ncol, fromcols = from->ncol;
1010
0
    igraph_int_t torows = to->nrow, fromrows = from->nrow;
1011
0
    igraph_int_t offset, c, r, index, offset2;
1012
0
    if (tocols != fromcols) {
1013
0
        IGRAPH_ERROR("Cannot do rbind, number of columns does not match.", IGRAPH_EINVAL);
1014
0
    }
1015
1016
0
    igraph_int_t new_size; /* new_size = tocols * (fromrows + torows) */
1017
0
    IGRAPH_SAFE_ADD(fromrows, torows, &new_size);
1018
0
    IGRAPH_SAFE_MULT(tocols, new_size, &new_size);
1019
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&to->data, new_size));
1020
0
    to->nrow += fromrows;
1021
1022
0
    offset = (tocols - 1) * fromrows;
1023
0
    index = tocols * torows - 1;
1024
0
    for (c = tocols - 1; c > 0; c--) {
1025
0
        for (r = 0; r < torows; r++, index--) {
1026
0
            VECTOR(to->data)[index + offset] = VECTOR(to->data)[index];
1027
0
        }
1028
0
        offset -= fromrows;
1029
0
    }
1030
1031
0
    offset = torows; offset2 = 0;
1032
0
    for (c = 0; c < tocols; c++) {
1033
0
        memcpy(VECTOR(to->data) + offset, VECTOR(from->data) + offset2,
1034
0
               sizeof(BASE) * fromrows);
1035
0
        offset += fromrows + torows;
1036
0
        offset2 += fromrows;
1037
0
    }
1038
0
    return IGRAPH_SUCCESS;
1039
0
}
Unexecuted instantiation: igraph_matrix_rbind
Unexecuted instantiation: igraph_matrix_int_rbind
Unexecuted instantiation: igraph_matrix_char_rbind
Unexecuted instantiation: igraph_matrix_bool_rbind
Unexecuted instantiation: igraph_matrix_complex_rbind
1040
1041
/**
1042
 * \function igraph_matrix_cbind
1043
 * Combine matrices columnwise.
1044
 *
1045
 * This function places the columns of \p from on the right of \p to,
1046
 * and stores the result in \p to.
1047
 * \param to The left matrix; the result is stored here too.
1048
 * \param from The right matrix. It is left unchanged.
1049
 * \return Error code.
1050
 *
1051
 * Time complexity: O(mn), the number of elements in the new matrix.
1052
 */
1053
1054
igraph_error_t FUNCTION(igraph_matrix, cbind)(TYPE(igraph_matrix) *to,
1055
0
                                   const TYPE(igraph_matrix) *from) {
1056
1057
0
    igraph_int_t tocols = to->ncol, fromcols = from->ncol;
1058
0
    igraph_int_t torows = to->nrow, fromrows = from->nrow;
1059
0
    if (torows != fromrows) {
1060
0
        IGRAPH_ERROR("Cannot do rbind, number of rows does not match.", IGRAPH_EINVAL);
1061
0
    }
1062
1063
0
    igraph_int_t new_tocols;
1064
0
    IGRAPH_SAFE_ADD(tocols, fromcols, &new_tocols);
1065
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(to, torows, new_tocols));
1066
1067
0
    FUNCTION(igraph_vector, copy_to)(&from->data, VECTOR(to->data) + tocols * torows);
1068
1069
0
    return IGRAPH_SUCCESS;
1070
0
}
Unexecuted instantiation: igraph_matrix_cbind
Unexecuted instantiation: igraph_matrix_int_cbind
Unexecuted instantiation: igraph_matrix_char_cbind
Unexecuted instantiation: igraph_matrix_bool_cbind
Unexecuted instantiation: igraph_matrix_complex_cbind
1071
1072
/**
1073
 * \function igraph_matrix_swap
1074
 * \brief Swaps two matrices.
1075
 *
1076
 * The contents of the two matrices will be swapped.
1077
 * \param m1 The first matrix.
1078
 * \param m2 The second matrix.
1079
 *
1080
 * Time complexity: O(1).
1081
 */
1082
1083
0
void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2) {
1084
0
    igraph_int_t tmp;
1085
1086
0
    tmp = m1->nrow;
1087
0
    m1->nrow = m2->nrow;
1088
0
    m2->nrow = tmp;
1089
1090
0
    tmp = m1->ncol;
1091
0
    m1->ncol = m2->ncol;
1092
0
    m2->ncol = tmp;
1093
1094
0
    FUNCTION(igraph_vector, swap)(&m1->data, &m2->data);
1095
0
}
Unexecuted instantiation: igraph_matrix_swap
Unexecuted instantiation: igraph_matrix_int_swap
Unexecuted instantiation: igraph_matrix_char_swap
Unexecuted instantiation: igraph_matrix_bool_swap
Unexecuted instantiation: igraph_matrix_complex_swap
1096
1097
/**
1098
 * \function igraph_matrix_get_row
1099
 * Extract a row.
1100
 *
1101
 * Extract a row from a matrix and return it as a vector.
1102
 * \param m The input matrix.
1103
 * \param res Pointer to an initialized vector; it will be resized if
1104
 *   needed.
1105
 * \param index The index of the row to select.
1106
 * \return Error code.
1107
 *
1108
 * Time complexity: O(n), the number of columns in the matrix.
1109
 */
1110
1111
igraph_error_t FUNCTION(igraph_matrix, get_row)(const TYPE(igraph_matrix) *m,
1112
78.0k
                                     TYPE(igraph_vector) *res, igraph_int_t index) {
1113
78.0k
    igraph_int_t rows = m->nrow, cols = m->ncol;
1114
78.0k
    igraph_int_t i, j;
1115
1116
78.0k
    if (index >= rows) {
1117
0
        IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL);
1118
0
    }
1119
78.0k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, cols));
1120
1121
227k
    for (i = index, j = 0; j < cols; i += rows, j++) {
1122
149k
        VECTOR(*res)[j] = VECTOR(m->data)[i];
1123
149k
    }
1124
78.0k
    return IGRAPH_SUCCESS;
1125
78.0k
}
igraph_matrix_get_row
Line
Count
Source
1112
78.0k
                                     TYPE(igraph_vector) *res, igraph_int_t index) {
1113
78.0k
    igraph_int_t rows = m->nrow, cols = m->ncol;
1114
78.0k
    igraph_int_t i, j;
1115
1116
78.0k
    if (index >= rows) {
1117
0
        IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL);
1118
0
    }
1119
78.0k
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, cols));
1120
1121
227k
    for (i = index, j = 0; j < cols; i += rows, j++) {
1122
149k
        VECTOR(*res)[j] = VECTOR(m->data)[i];
1123
149k
    }
1124
78.0k
    return IGRAPH_SUCCESS;
1125
78.0k
}
Unexecuted instantiation: igraph_matrix_int_get_row
Unexecuted instantiation: igraph_matrix_char_get_row
Unexecuted instantiation: igraph_matrix_bool_get_row
Unexecuted instantiation: igraph_matrix_complex_get_row
1126
1127
/**
1128
 * \function igraph_matrix_set_row
1129
 * Set a row from a vector.
1130
 *
1131
 * Sets the elements of a row with the given vector. This has the effect of
1132
 * setting row \c index to have the elements in the vector \c v. The length of
1133
 * the vector and the number of columns in the matrix must match,
1134
 * otherwise an error is triggered.
1135
 * \param m The input matrix.
1136
 * \param v The vector containing the new elements of the row.
1137
 * \param index Index of the row to set.
1138
 * \return Error code.
1139
 *
1140
 * Time complexity: O(n), the number of columns in the matrix.
1141
 */
1142
1143
igraph_error_t FUNCTION(igraph_matrix, set_row)(TYPE(igraph_matrix) *m,
1144
11.9k
                                     const TYPE(igraph_vector) *v, igraph_int_t index) {
1145
11.9k
    const igraph_int_t rows = m->nrow, cols = m->ncol;
1146
1147
11.9k
    if (index >= rows) {
1148
0
        IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL);
1149
0
    }
1150
11.9k
    if (FUNCTION(igraph_vector, size)(v) != cols) {
1151
0
        IGRAPH_ERROR("Cannot set matrix row, invalid vector length.", IGRAPH_EINVAL);
1152
0
    }
1153
1.02M
    for (igraph_int_t i = index, j = 0; j < cols; i += rows, j++) {
1154
1.01M
        VECTOR(m->data)[i] = VECTOR(*v)[j];
1155
1.01M
    }
1156
11.9k
    return IGRAPH_SUCCESS;
1157
11.9k
}
igraph_matrix_set_row
Line
Count
Source
1144
3.02k
                                     const TYPE(igraph_vector) *v, igraph_int_t index) {
1145
3.02k
    const igraph_int_t rows = m->nrow, cols = m->ncol;
1146
1147
3.02k
    if (index >= rows) {
1148
0
        IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL);
1149
0
    }
1150
3.02k
    if (FUNCTION(igraph_vector, size)(v) != cols) {
1151
0
        IGRAPH_ERROR("Cannot set matrix row, invalid vector length.", IGRAPH_EINVAL);
1152
0
    }
1153
586k
    for (igraph_int_t i = index, j = 0; j < cols; i += rows, j++) {
1154
583k
        VECTOR(m->data)[i] = VECTOR(*v)[j];
1155
583k
    }
1156
3.02k
    return IGRAPH_SUCCESS;
1157
3.02k
}
igraph_matrix_int_set_row
Line
Count
Source
1144
8.90k
                                     const TYPE(igraph_vector) *v, igraph_int_t index) {
1145
8.90k
    const igraph_int_t rows = m->nrow, cols = m->ncol;
1146
1147
8.90k
    if (index >= rows) {
1148
0
        IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL);
1149
0
    }
1150
8.90k
    if (FUNCTION(igraph_vector, size)(v) != cols) {
1151
0
        IGRAPH_ERROR("Cannot set matrix row, invalid vector length.", IGRAPH_EINVAL);
1152
0
    }
1153
440k
    for (igraph_int_t i = index, j = 0; j < cols; i += rows, j++) {
1154
431k
        VECTOR(m->data)[i] = VECTOR(*v)[j];
1155
431k
    }
1156
8.90k
    return IGRAPH_SUCCESS;
1157
8.90k
}
Unexecuted instantiation: igraph_matrix_char_set_row
Unexecuted instantiation: igraph_matrix_bool_set_row
Unexecuted instantiation: igraph_matrix_complex_set_row
1158
1159
/**
1160
 * \function igraph_matrix_set_col
1161
 * Set a column from a vector.
1162
 *
1163
 * Sets the elements of a column with the given vector. In effect, column
1164
 * \c index will be set with elements from the vector \c v. The length of
1165
 * the vector and the number of rows in the matrix must match,
1166
 * otherwise an error is triggered.
1167
 * \param m The input matrix.
1168
 * \param v The vector containing the new elements of the column.
1169
 * \param index Index of the column to set.
1170
 * \return Error code.
1171
 *
1172
 * Time complexity: O(m), the number of rows in the matrix.
1173
 */
1174
1175
igraph_error_t FUNCTION(igraph_matrix, set_col)(TYPE(igraph_matrix) *m,
1176
0
                                     const TYPE(igraph_vector) *v, igraph_int_t index) {
1177
0
    const igraph_int_t rows = m->nrow, cols = m->ncol;
1178
1179
0
    if (index >= cols) {
1180
0
        IGRAPH_ERROR("Index out of range for setting matrix column.", IGRAPH_EINVAL);
1181
0
    }
1182
0
    if (FUNCTION(igraph_vector, size)(v) != rows) {
1183
0
        IGRAPH_ERROR("Cannot set matrix column, invalid vector length.", IGRAPH_EINVAL);
1184
0
    }
1185
0
    for (igraph_int_t i = index * rows, j = 0; j < rows; i++, j++) {
1186
0
        VECTOR(m->data)[i] = VECTOR(*v)[j];
1187
0
    }
1188
0
    return IGRAPH_SUCCESS;
1189
0
}
Unexecuted instantiation: igraph_matrix_set_col
Unexecuted instantiation: igraph_matrix_int_set_col
Unexecuted instantiation: igraph_matrix_char_set_col
Unexecuted instantiation: igraph_matrix_bool_set_col
Unexecuted instantiation: igraph_matrix_complex_set_col
1190
1191
/**
1192
 * \function igraph_matrix_swap_rows
1193
 * Swap two rows.
1194
 *
1195
 * Swap two rows in the matrix.
1196
 * \param m The input matrix.
1197
 * \param i The index of the first row.
1198
 * \param j The index of the second row.
1199
 * \return Error code.
1200
 *
1201
 * Time complexity: O(n), the number of columns.
1202
 */
1203
1204
igraph_error_t FUNCTION(igraph_matrix, swap_rows)(TYPE(igraph_matrix) *m,
1205
0
                                       igraph_int_t i, igraph_int_t j) {
1206
0
    const igraph_int_t ncol = m->ncol, nrow = m->nrow;
1207
0
    const igraph_int_t n = nrow * ncol;
1208
1209
0
    if (i >= nrow || j >= nrow) {
1210
0
        IGRAPH_ERROR("Cannot swap rows, index out of range.", IGRAPH_EINVAL);
1211
0
    }
1212
0
    if (i == j) {
1213
0
        return IGRAPH_SUCCESS;
1214
0
    }
1215
0
    for (igraph_int_t index1 = i, index2 = j; index1 < n; index1 += nrow, index2 += nrow) {
1216
0
        BASE tmp;
1217
0
        tmp = VECTOR(m->data)[index1];
1218
0
        VECTOR(m->data)[index1] = VECTOR(m->data)[index2];
1219
0
        VECTOR(m->data)[index2] = tmp;
1220
0
    }
1221
0
    return IGRAPH_SUCCESS;
1222
0
}
Unexecuted instantiation: igraph_matrix_swap_rows
Unexecuted instantiation: igraph_matrix_int_swap_rows
Unexecuted instantiation: igraph_matrix_char_swap_rows
Unexecuted instantiation: igraph_matrix_bool_swap_rows
Unexecuted instantiation: igraph_matrix_complex_swap_rows
1223
1224
/**
1225
 * \function igraph_matrix_swap_cols
1226
 * Swap two columns.
1227
 *
1228
 * Swap two columns in the matrix.
1229
 * \param m The input matrix.
1230
 * \param i The index of the first column.
1231
 * \param j The index of the second column.
1232
 * \return Error code.
1233
 *
1234
 * Time complexity: O(m), the number of rows.
1235
 */
1236
1237
igraph_error_t FUNCTION(igraph_matrix, swap_cols)(TYPE(igraph_matrix) *m,
1238
0
                                       igraph_int_t i, igraph_int_t j) {
1239
0
    const igraph_int_t ncol = m->ncol, nrow = m->nrow;
1240
1241
0
    if (i >= ncol || j >= ncol) {
1242
0
        IGRAPH_ERROR("Cannot swap columns, index out of range.", IGRAPH_EINVAL);
1243
0
    }
1244
0
    if (i == j) {
1245
0
        return IGRAPH_SUCCESS;
1246
0
    }
1247
0
    for (igraph_int_t index1 = i * nrow, index2 = j * nrow, k = 0; k < nrow; k++, index1++, index2++) {
1248
0
        BASE tmp = VECTOR(m->data)[index1];
1249
0
        VECTOR(m->data)[index1] = VECTOR(m->data)[index2];
1250
0
        VECTOR(m->data)[index2] = tmp;
1251
0
    }
1252
0
    return IGRAPH_SUCCESS;
1253
0
}
Unexecuted instantiation: igraph_matrix_swap_cols
Unexecuted instantiation: igraph_matrix_int_swap_cols
Unexecuted instantiation: igraph_matrix_char_swap_cols
Unexecuted instantiation: igraph_matrix_bool_swap_cols
Unexecuted instantiation: igraph_matrix_complex_swap_cols
1254
1255
/**
1256
 * \function igraph_matrix_add_constant
1257
 * Add a constant to every element.
1258
 *
1259
 * \param m The input matrix.
1260
 * \param plud The constant to add.
1261
 *
1262
 * Time complexity: O(mn), the number of elements.
1263
 */
1264
1265
0
void FUNCTION(igraph_matrix, add_constant)(TYPE(igraph_matrix) *m, BASE plus) {
1266
0
    FUNCTION(igraph_vector, add_constant)(&m->data, plus);
1267
0
}
Unexecuted instantiation: igraph_matrix_add_constant
Unexecuted instantiation: igraph_matrix_int_add_constant
Unexecuted instantiation: igraph_matrix_char_add_constant
Unexecuted instantiation: igraph_matrix_bool_add_constant
Unexecuted instantiation: igraph_matrix_complex_add_constant
1268
1269
/**
1270
 * \function igraph_matrix_add
1271
 * Add two matrices.
1272
 *
1273
 * Add \p m2 to \p m1, and store the result in \p m1. The dimensions of the
1274
 * matrices must match.
1275
 * \param m1 The first matrix; the result will be stored here.
1276
 * \param m2 The second matrix; it is left unchanged.
1277
 * \return Error code.
1278
 *
1279
 * Time complexity: O(mn), the number of elements.
1280
 */
1281
1282
igraph_error_t FUNCTION(igraph_matrix, add)(TYPE(igraph_matrix) *m1,
1283
0
                                 const TYPE(igraph_matrix) *m2) {
1284
0
    if (m1->nrow != m2->nrow || m1->ncol != m2->ncol) {
1285
0
        IGRAPH_ERROR("Cannot add non-conformant matrices.", IGRAPH_EINVAL);
1286
0
    }
1287
0
    return FUNCTION(igraph_vector, add)(&m1->data, &m2->data);
1288
0
}
Unexecuted instantiation: igraph_matrix_add
Unexecuted instantiation: igraph_matrix_int_add
Unexecuted instantiation: igraph_matrix_char_add
Unexecuted instantiation: igraph_matrix_bool_add
Unexecuted instantiation: igraph_matrix_complex_add
1289
1290
/**
1291
 * \function igraph_matrix_sub
1292
 * Difference of two matrices.
1293
 *
1294
 * Subtract \p m2 from \p m1 and store the result in \p m1.
1295
 * The dimensions of the two matrices must match.
1296
 * \param m1 The first matrix; the result is stored here.
1297
 * \param m2 The second matrix; it is left unchanged.
1298
 * \return Error code.
1299
 *
1300
 * Time complexity: O(mn), the number of elements.
1301
 */
1302
1303
igraph_error_t FUNCTION(igraph_matrix, sub)(TYPE(igraph_matrix) *m1,
1304
0
                                 const TYPE(igraph_matrix) *m2) {
1305
0
    if (m1->nrow != m2->nrow || m1->ncol != m2->ncol) {
1306
0
        IGRAPH_ERROR("Cannot subtract non-conformant matrices.", IGRAPH_EINVAL);
1307
0
    }
1308
0
    return FUNCTION(igraph_vector, sub)(&m1->data, &m2->data);
1309
0
}
Unexecuted instantiation: igraph_matrix_sub
Unexecuted instantiation: igraph_matrix_int_sub
Unexecuted instantiation: igraph_matrix_char_sub
Unexecuted instantiation: igraph_matrix_bool_sub
Unexecuted instantiation: igraph_matrix_complex_sub
1310
1311
/**
1312
 * \function igraph_matrix_mul_elements
1313
 * \brief Elementwise matrix multiplication.
1314
 *
1315
 * Multiply \p m1 by \p m2 elementwise and store the result in \p m1.
1316
 * The dimensions of the two matrices must match.
1317
 *
1318
 * \param m1 The first matrix; the result is stored here.
1319
 * \param m2 The second matrix; it is left unchanged.
1320
 * \return Error code.
1321
 *
1322
 * Time complexity: O(mn), the number of elements.
1323
 */
1324
1325
igraph_error_t FUNCTION(igraph_matrix, mul_elements)(TYPE(igraph_matrix) *m1,
1326
0
        const TYPE(igraph_matrix) *m2) {
1327
0
    if (m1->nrow != m2->nrow || m1->ncol != m2->ncol) {
1328
0
        IGRAPH_ERROR("Cannot multiply elements of non-conformant matrices.", IGRAPH_EINVAL);
1329
0
    }
1330
0
    return FUNCTION(igraph_vector, mul)(&m1->data, &m2->data);
1331
0
}
Unexecuted instantiation: igraph_matrix_mul_elements
Unexecuted instantiation: igraph_matrix_int_mul_elements
Unexecuted instantiation: igraph_matrix_char_mul_elements
Unexecuted instantiation: igraph_matrix_bool_mul_elements
Unexecuted instantiation: igraph_matrix_complex_mul_elements
1332
1333
/**
1334
 * \function igraph_matrix_div_elements
1335
 * Elementwise division.
1336
 *
1337
 * Divide \p m1 by \p m2 elementwise and store the result in \p m1.
1338
 * The dimensions of the two matrices must match.
1339
 * \param m1 The dividend. The result is stored here.
1340
 * \param m2 The divisor. It is left unchanged.
1341
 * \return Error code.
1342
 *
1343
 * Time complexity: O(mn), the number of elements.
1344
 */
1345
1346
igraph_error_t FUNCTION(igraph_matrix, div_elements)(TYPE(igraph_matrix) *m1,
1347
0
        const TYPE(igraph_matrix) *m2) {
1348
0
    if (m1->nrow != m2->nrow || m1->ncol != m2->ncol) {
1349
0
        IGRAPH_ERROR("Cannot divide non-conformant matrices.", IGRAPH_EINVAL);
1350
0
    }
1351
0
    return FUNCTION(igraph_vector, div)(&m1->data, &m2->data);
1352
0
}
Unexecuted instantiation: igraph_matrix_div_elements
Unexecuted instantiation: igraph_matrix_int_div_elements
Unexecuted instantiation: igraph_matrix_char_div_elements
Unexecuted instantiation: igraph_matrix_bool_div_elements
Unexecuted instantiation: igraph_matrix_complex_div_elements
1353
1354
#ifndef NOTORDERED
1355
1356
/**
1357
 * \function igraph_matrix_min
1358
 * \brief Smallest element of a matrix.
1359
 *
1360
 * The matrix must be non-empty.
1361
 *
1362
 * \param m The input matrix.
1363
 * \return The smallest element of \p m, or NaN if any element is NaN.
1364
 *
1365
 * Time complexity: O(mn), the number of elements in the matrix.
1366
 */
1367
1368
0
igraph_real_t FUNCTION(igraph_matrix, min)(const TYPE(igraph_matrix) *m) {
1369
0
    return FUNCTION(igraph_vector, min)(&m->data);
1370
0
}
Unexecuted instantiation: igraph_matrix_min
Unexecuted instantiation: igraph_matrix_int_min
Unexecuted instantiation: igraph_matrix_char_min
1371
1372
/**
1373
 * \function igraph_matrix_which_min
1374
 * \brief Indices of the smallest element.
1375
 *
1376
 * The matrix must be non-empty. If the smallest element is not unique,
1377
 * then the indices of the first such element are returned. If the matrix contains
1378
 * NaN values, the indices of the first NaN value are returned.
1379
 *
1380
 * \param m The matrix.
1381
 * \param i Pointer to an <type>igraph_int_t</type>. The row index of the
1382
 *   minimum is stored here.
1383
 * \param j Pointer to an <type>igraph_int_t</type>. The column index of
1384
 *   the minimum is stored here.
1385
 *
1386
 * Time complexity: O(mn), the number of elements.
1387
 */
1388
1389
void FUNCTION(igraph_matrix, which_min)(
1390
0
        const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j) {
1391
0
    igraph_int_t vmin = FUNCTION(igraph_vector, which_min)(&m->data);
1392
0
    *i = vmin % m->nrow;
1393
0
    *j = vmin / m->nrow;
1394
0
}
Unexecuted instantiation: igraph_matrix_which_min
Unexecuted instantiation: igraph_matrix_int_which_min
Unexecuted instantiation: igraph_matrix_char_which_min
1395
1396
/**
1397
 * \function igraph_matrix_which_max
1398
 * \brief Indices of the largest element.
1399
 *
1400
 * The matrix must be non-empty. If the largest element is not unique,
1401
 * then the indices of the first such element are returned. If the matrix contains
1402
 * NaN values, the indices of the first NaN value are returned.
1403
 *
1404
 * \param m The matrix.
1405
 * \param i Pointer to an <type>igraph_int_t</type>. The row index of the
1406
 *   maximum is stored here.
1407
 * \param j Pointer to an <type>igraph_int_t</type>. The column index of
1408
 *   the maximum is stored here.
1409
 *
1410
 * Time complexity: O(mn), the number of elements.
1411
 */
1412
1413
void FUNCTION(igraph_matrix, which_max)(
1414
0
        const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j) {
1415
0
    igraph_int_t vmax = FUNCTION(igraph_vector, which_max)(&m->data);
1416
0
    *i = vmax % m->nrow;
1417
0
    *j = vmax / m->nrow;
1418
0
}
Unexecuted instantiation: igraph_matrix_which_max
Unexecuted instantiation: igraph_matrix_int_which_max
Unexecuted instantiation: igraph_matrix_char_which_max
1419
1420
/**
1421
 * \function igraph_matrix_minmax
1422
 * \brief Minimum and maximum elements of a matrix.
1423
 *
1424
 * Handy if you want to have both the smallest and largest element of
1425
 * a matrix. The matrix is only traversed once. The matrix must be non-empty.
1426
 * If a matrix contains at least one NaN, both \c min and \c max will be NaN.
1427
 *
1428
 * \param m The input matrix. It must contain at least one element.
1429
 * \param min Pointer to a base type variable. The minimum is stored here.
1430
 * \param max Pointer to a base type variable. The maximum is stored here.
1431
 *
1432
 * Time complexity: O(mn), the number of elements.
1433
 */
1434
1435
void FUNCTION(igraph_matrix, minmax)(const TYPE(igraph_matrix) *m,
1436
0
                                    BASE *min, BASE *max) {
1437
0
    FUNCTION(igraph_vector, minmax)(&m->data, min, max);
1438
0
}
Unexecuted instantiation: igraph_matrix_minmax
Unexecuted instantiation: igraph_matrix_int_minmax
Unexecuted instantiation: igraph_matrix_char_minmax
1439
1440
/**
1441
 * \function igraph_matrix_which_minmax
1442
 * \brief Indices of the minimum and maximum elements.
1443
 *
1444
 * Handy if you need the indices of the smallest and largest
1445
 * elements. The matrix is traversed only once. The matrix must be
1446
 * non-empty. If the minimum or maximum is not unique, the index
1447
 * of the first minimum or the first maximum is returned, respectively.
1448
 * If a matrix contains at least one NaN, both \c which_min and \c which_max
1449
 * will point to the first NaN value.
1450
 *
1451
 * \param m The input matrix.
1452
 * \param imin Pointer to an <type>igraph_int_t</type>, the row index of
1453
 *   the minimum is stored here.
1454
 * \param jmin Pointer to an <type>igraph_int_t</type>, the column index of
1455
 *   the minimum is stored here.
1456
 * \param imax Pointer to an <type>igraph_int_t</type>, the row index of
1457
 *   the maximum is stored here.
1458
 * \param jmax Pointer to an <type>igraph_int_t</type>, the column index of
1459
 *   the maximum is stored here.
1460
 *
1461
 * Time complexity: O(mn), the number of elements.
1462
 */
1463
1464
void FUNCTION(igraph_matrix, which_minmax)(const TYPE(igraph_matrix) *m,
1465
        igraph_int_t *imin, igraph_int_t *jmin,
1466
0
        igraph_int_t *imax, igraph_int_t *jmax) {
1467
0
    igraph_int_t vmin, vmax;
1468
0
    FUNCTION(igraph_vector, which_minmax)(&m->data, &vmin, &vmax);
1469
0
    *imin = vmin % m->nrow;
1470
0
    *jmin = vmin / m->nrow;
1471
0
    *imax = vmax % m->nrow;
1472
0
    *jmax = vmax / m->nrow;
1473
0
}
Unexecuted instantiation: igraph_matrix_which_minmax
Unexecuted instantiation: igraph_matrix_int_which_minmax
Unexecuted instantiation: igraph_matrix_char_which_minmax
1474
1475
#endif
1476
1477
/**
1478
 * \function igraph_matrix_isnull
1479
 * \brief Checks for a null matrix.
1480
 *
1481
 * Checks whether all elements are zero.
1482
 *
1483
 * \param m The input matrix.
1484
 * \return Boolean, \c true if \p m contains only zeros and \c false
1485
 *   otherwise.
1486
 *
1487
 * Time complexity: O(mn), the number of elements.
1488
 */
1489
1490
0
igraph_bool_t FUNCTION(igraph_matrix, isnull)(const TYPE(igraph_matrix) *m) {
1491
0
    return FUNCTION(igraph_vector, isnull)(&m->data);
1492
0
}
Unexecuted instantiation: igraph_matrix_isnull
Unexecuted instantiation: igraph_matrix_int_isnull
Unexecuted instantiation: igraph_matrix_char_isnull
Unexecuted instantiation: igraph_matrix_bool_isnull
Unexecuted instantiation: igraph_matrix_complex_isnull
1493
1494
/**
1495
 * \function igraph_matrix_empty
1496
 * \brief Is the matrix empty?
1497
 *
1498
 * It is possible to have a matrix with zero rows or zero columns, or
1499
 * even both. This function checks for these.
1500
 *
1501
 * \param m The input matrix.
1502
 * \return Boolean, \c true if the matrix contains zero elements, and
1503
 *    \c false otherwise.
1504
 *
1505
 * Time complexity: O(1).
1506
 */
1507
1508
0
igraph_bool_t FUNCTION(igraph_matrix, empty)(const TYPE(igraph_matrix) *m) {
1509
0
    return FUNCTION(igraph_vector, empty)(&m->data);
1510
0
}
Unexecuted instantiation: igraph_matrix_empty
Unexecuted instantiation: igraph_matrix_int_empty
Unexecuted instantiation: igraph_matrix_char_empty
Unexecuted instantiation: igraph_matrix_bool_empty
Unexecuted instantiation: igraph_matrix_complex_empty
1511
1512
/**
1513
 * \function igraph_matrix_is_symmetric
1514
 * \brief Is the matrix symmetric?
1515
 *
1516
 * A non-square matrix is not symmetric by definition.
1517
 *
1518
 * \param m The input matrix.
1519
 * \return Boolean, \c true if the matrix is square and symmetric, \c
1520
 *    false otherwise.
1521
 *
1522
 * Time complexity: O(mn), the number of elements. O(1) for non-square
1523
 * matrices.
1524
 */
1525
1526
0
igraph_bool_t FUNCTION(igraph_matrix, is_symmetric)(const TYPE(igraph_matrix) *m) {
1527
1528
0
    const igraph_int_t n = m->nrow;
1529
0
    if (m->ncol != n) {
1530
0
        return false;
1531
0
    }
1532
0
    for (igraph_int_t r = 1; r < n; r++) {
1533
0
        for (igraph_int_t c = 0; c < r; c++) {
1534
0
            BASE a1 = MATRIX(*m, r, c);
1535
0
            BASE a2 = MATRIX(*m, c, r);
1536
#ifdef EQ
1537
0
            if (!EQ(a1, a2)) {
1538
0
                return false;
1539
0
            }
1540
#else
1541
0
            if (a1 != a2) {
1542
0
                return false;
1543
0
            }
1544
#endif
1545
0
        }
1546
0
    }
1547
0
    return true;
1548
0
}
Unexecuted instantiation: igraph_matrix_is_symmetric
Unexecuted instantiation: igraph_matrix_int_is_symmetric
Unexecuted instantiation: igraph_matrix_char_is_symmetric
Unexecuted instantiation: igraph_matrix_bool_is_symmetric
Unexecuted instantiation: igraph_matrix_complex_is_symmetric
1549
1550
/**
1551
 * \function igraph_matrix_prod
1552
 * \brief Product of all matrix elements.
1553
 *
1554
 * Note that this function can result in overflow easily, even for not too
1555
 * big matrices. Overflow is not checked.
1556
 *
1557
 * \param m The input matrix.
1558
 * \return The product of the elements.
1559
 *
1560
 * Time complexity: O(mn), the number of elements.
1561
 */
1562
1563
0
BASE FUNCTION(igraph_matrix, prod)(const TYPE(igraph_matrix) *m) {
1564
0
    return FUNCTION(igraph_vector, prod)(&m->data);
1565
0
}
Unexecuted instantiation: igraph_matrix_prod
Unexecuted instantiation: igraph_matrix_int_prod
Unexecuted instantiation: igraph_matrix_char_prod
Unexecuted instantiation: igraph_matrix_bool_prod
Unexecuted instantiation: igraph_matrix_complex_prod
1566
1567
/**
1568
 * \function igraph_matrix_rowsum
1569
 * \brief Rowwise sum.
1570
 *
1571
 * Calculate the sum of the elements in each row.
1572
 *
1573
 * \param m The input matrix.
1574
 * \param res Pointer to an initialized vector; the result is stored
1575
 *   here. It will be resized if necessary.
1576
 * \return Error code.
1577
 *
1578
 * Time complexity: O(mn), the number of elements in the matrix.
1579
 */
1580
1581
igraph_error_t FUNCTION(igraph_matrix, rowsum)(const TYPE(igraph_matrix) *m,
1582
0
                                    TYPE(igraph_vector) *res) {
1583
0
    const igraph_int_t nrow = m->nrow, ncol = m->ncol;
1584
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, nrow));
1585
0
    FUNCTION(igraph_vector, null)(res);
1586
    /* Iterate in column-major order for better performance. */
1587
0
    for (igraph_int_t c = 0; c < ncol; c++) {
1588
0
        for (igraph_int_t r = 0; r < nrow; r++) {
1589
#ifdef SUM
1590
0
            SUM(VECTOR(*res)[r], VECTOR(*res)[r], MATRIX(*m, r, c));
1591
#else
1592
0
            VECTOR(*res)[r] += MATRIX(*m, r, c);
1593
#endif
1594
0
        }
1595
0
    }
1596
0
    return IGRAPH_SUCCESS;
1597
0
}
Unexecuted instantiation: igraph_matrix_rowsum
Unexecuted instantiation: igraph_matrix_int_rowsum
Unexecuted instantiation: igraph_matrix_char_rowsum
Unexecuted instantiation: igraph_matrix_bool_rowsum
Unexecuted instantiation: igraph_matrix_complex_rowsum
1598
1599
/**
1600
 * \function igraph_matrix_colsum
1601
 * \brief Columnwise sum.
1602
 *
1603
 * Calculate the sum of the elements in each column.
1604
 *
1605
 * \param m The input matrix.
1606
 * \param res Pointer to an initialized vector; the result is stored
1607
 *   here. It will be resized if necessary.
1608
 * \return Error code.
1609
 *
1610
 * Time complexity: O(mn), the number of elements in the matrix.
1611
 */
1612
1613
igraph_error_t FUNCTION(igraph_matrix, colsum)(const TYPE(igraph_matrix) *m,
1614
0
                                    TYPE(igraph_vector) *res) {
1615
0
    const igraph_int_t nrow = m->nrow, ncol = m->ncol;
1616
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, ncol));
1617
0
    for (igraph_int_t c = 0; c < ncol; c++) {
1618
0
        BASE sum = ZERO;
1619
0
        for (igraph_int_t r = 0; r < nrow; r++) {
1620
#ifdef SUM
1621
0
            SUM(sum, sum, MATRIX(*m, r, c));
1622
#else
1623
0
            sum += MATRIX(*m, r, c);
1624
#endif
1625
0
        }
1626
0
        VECTOR(*res)[c] = sum;
1627
0
    }
1628
0
    return IGRAPH_SUCCESS;
1629
0
}
Unexecuted instantiation: igraph_matrix_colsum
Unexecuted instantiation: igraph_matrix_int_colsum
Unexecuted instantiation: igraph_matrix_char_colsum
Unexecuted instantiation: igraph_matrix_bool_colsum
Unexecuted instantiation: igraph_matrix_complex_colsum
1630
1631
/**
1632
 * \function igraph_matrix_contains
1633
 * Search for an element.
1634
 *
1635
 * Search for the given element in the matrix.
1636
 * \param m The input matrix.
1637
 * \param e The element to search for.
1638
 * \return Boolean, \c true if the matrix contains \p e, \c false
1639
 * otherwise.
1640
 *
1641
 * Time complexity: O(mn), the number of elements.
1642
 */
1643
1644
igraph_bool_t FUNCTION(igraph_matrix, contains)(const TYPE(igraph_matrix) *m,
1645
0
        BASE e) {
1646
0
    return FUNCTION(igraph_vector, contains)(&m->data, e);
1647
0
}
Unexecuted instantiation: igraph_matrix_contains
Unexecuted instantiation: igraph_matrix_int_contains
Unexecuted instantiation: igraph_matrix_char_contains
Unexecuted instantiation: igraph_matrix_bool_contains
Unexecuted instantiation: igraph_matrix_complex_contains
1648
1649
/**
1650
 * \function igraph_matrix_search
1651
 * Search from a given position.
1652
 *
1653
 * Search for an element in a matrix and start the search from the
1654
 * given position. The search is performed columnwise.
1655
 * \param m The input matrix.
1656
 * \param from The position to search from, the positions are
1657
 *    enumerated columnwise.
1658
 * \param what The element to search for.
1659
 * \param pos Pointer to an <type>igraph_int_t</type>. If the element is
1660
 *    found, then this is set to the position of its first appearance.
1661
 * \param row Pointer to an <type>igraph_int_t</type>. If the element is
1662
 *    found, then this is set to its row index.
1663
 * \param col Pointer to an <type>igraph_int_t</type>. If the element is
1664
 *    found, then this is set to its column index.
1665
 * \return Boolean, \c true if the element is found, \c false
1666
 *    otherwise.
1667
 *
1668
 * Time complexity: O(mn), the number of elements.
1669
 */
1670
1671
igraph_bool_t FUNCTION(igraph_matrix, search)(const TYPE(igraph_matrix) *m,
1672
        igraph_int_t from, BASE what, igraph_int_t *pos,
1673
0
        igraph_int_t *row, igraph_int_t *col) {
1674
0
    igraph_bool_t find = FUNCTION(igraph_vector, search)(&m->data, from, what, pos);
1675
0
    if (find) {
1676
0
        *row = *pos % m->nrow;
1677
0
        *col = *pos / m->nrow;
1678
0
    }
1679
0
    return find;
1680
0
}
Unexecuted instantiation: igraph_matrix_search
Unexecuted instantiation: igraph_matrix_int_search
Unexecuted instantiation: igraph_matrix_char_search
Unexecuted instantiation: igraph_matrix_bool_search
Unexecuted instantiation: igraph_matrix_complex_search
1681
1682
/**
1683
 * \function igraph_matrix_remove_row
1684
 * Remove a row.
1685
 *
1686
 * A row is removed from the matrix.
1687
 * \param m The input matrix.
1688
 * \param row The index of the row to remove.
1689
 * \return Error code.
1690
 *
1691
 * Time complexity: O(mn), the number of elements in the matrix.
1692
 */
1693
1694
0
igraph_error_t FUNCTION(igraph_matrix, remove_row)(TYPE(igraph_matrix) *m, igraph_int_t row) {
1695
1696
0
    igraph_int_t c, r, index = row + 1, leap = 1, n = m->nrow * m->ncol;
1697
0
    if (row >= m->nrow) {
1698
0
        IGRAPH_ERROR("Cannot remove row, index out of range.", IGRAPH_EINVAL);
1699
0
    }
1700
1701
0
    for (c = 0; c < m->ncol; c++) {
1702
0
        for (r = 0; r < m->nrow - 1 && index < n; r++) {
1703
0
            VECTOR(m->data)[index - leap] = VECTOR(m->data)[index];
1704
0
            index++;
1705
0
        }
1706
0
        leap++;
1707
0
        index++;
1708
0
    }
1709
0
    m->nrow--;
1710
0
    IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, m->nrow * m->ncol));
1711
0
    return IGRAPH_SUCCESS;
1712
0
}
Unexecuted instantiation: igraph_matrix_remove_row
Unexecuted instantiation: igraph_matrix_int_remove_row
Unexecuted instantiation: igraph_matrix_char_remove_row
Unexecuted instantiation: igraph_matrix_bool_remove_row
Unexecuted instantiation: igraph_matrix_complex_remove_row
1713
1714
/**
1715
 * \function igraph_matrix_select_cols
1716
 * \brief Selects some columns of a matrix.
1717
 *
1718
 * This function selects some columns of a matrix and returns them in a
1719
 * new matrix. The result matrix should be initialized before calling
1720
 * the function.
1721
 * \param m The input matrix.
1722
 * \param res The result matrix. It should be initialized and will be
1723
 *    resized as needed.
1724
 * \param cols Vector; it contains the column indices (starting with
1725
 *    zero) to extract. Note that no range checking is performed.
1726
 * \return Error code.
1727
 *
1728
 * Time complexity: O(nm), n is the number of rows, m the number of
1729
 * columns of the result matrix.
1730
 */
1731
1732
igraph_error_t FUNCTION(igraph_matrix, select_cols)(const TYPE(igraph_matrix) *m,
1733
        TYPE(igraph_matrix) *res,
1734
0
        const igraph_vector_int_t *cols) {
1735
0
    igraph_int_t ncols = igraph_vector_int_size(cols);
1736
0
    igraph_int_t nrows = m->nrow;
1737
0
    igraph_int_t i, j;
1738
1739
0
    IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, nrows, ncols));
1740
    /* Iterate in column-major order for better performance. */
1741
0
    for (j = 0; j < ncols; j++) {
1742
0
        for (i = 0; i < nrows; i++) {
1743
0
            MATRIX(*res, i, j) = MATRIX(*m, i, VECTOR(*cols)[j]);
1744
0
        }
1745
0
    }
1746
0
    return IGRAPH_SUCCESS;
1747
0
}
Unexecuted instantiation: igraph_matrix_select_cols
Unexecuted instantiation: igraph_matrix_int_select_cols
Unexecuted instantiation: igraph_matrix_char_select_cols
Unexecuted instantiation: igraph_matrix_bool_select_cols
Unexecuted instantiation: igraph_matrix_complex_select_cols
1748
1749
#ifdef OUT_FORMAT
1750
#ifndef USING_R
1751
igraph_error_t FUNCTION(igraph_matrix, printf)(const TYPE(igraph_matrix) *m,
1752
0
                                    const char *format) {
1753
0
    igraph_int_t nr = FUNCTION(igraph_matrix, nrow)(m);
1754
0
    igraph_int_t nc = FUNCTION(igraph_matrix, ncol)(m);
1755
0
    igraph_int_t i, j;
1756
1757
0
    for (i = 0; i < nr; i++) {
1758
0
        for (j = 0; j < nc; j++) {
1759
0
            if (j != 0) {
1760
0
                putchar(' ');
1761
0
            }
1762
0
            printf(format, MATRIX(*m, i, j));
1763
0
        }
1764
0
        printf("\n");
1765
0
    }
1766
1767
0
    return IGRAPH_SUCCESS;
1768
0
}
Unexecuted instantiation: igraph_matrix_printf
Unexecuted instantiation: igraph_matrix_int_printf
Unexecuted instantiation: igraph_matrix_char_printf
Unexecuted instantiation: igraph_matrix_bool_printf
1769
#endif /* USING_R */
1770
#endif /* OUT_FORMAT */
1771
1772
#if defined(OUT_FORMAT) || defined(FPRINTFUNC)
1773
1774
#ifndef USING_R
1775
1776
0
igraph_error_t FUNCTION(igraph_matrix, print)(const TYPE(igraph_matrix) *m) {
1777
0
    return FUNCTION(igraph_matrix, fprint)(m, stdout);
1778
0
}
Unexecuted instantiation: igraph_matrix_print
Unexecuted instantiation: igraph_matrix_int_print
Unexecuted instantiation: igraph_matrix_char_print
Unexecuted instantiation: igraph_matrix_bool_print
Unexecuted instantiation: igraph_matrix_complex_print
1779
1780
#endif /* USING_R */
1781
1782
0
igraph_error_t FUNCTION(igraph_matrix, fprint)(const TYPE(igraph_matrix) *m, FILE *file) {
1783
0
    igraph_int_t nr = FUNCTION(igraph_matrix, nrow)(m);
1784
0
    igraph_int_t nc = FUNCTION(igraph_matrix, ncol)(m);
1785
0
    igraph_int_t i, j;
1786
0
    igraph_vector_int_t column_width;
1787
1788
#ifdef OUT_FORMAT
1789
    /* Insert dynamic width specifier '*' in format string. */
1790
    char format[ sizeof(OUT_FORMAT) + 1 ] = "%*";
1791
0
    strcpy(format + 2, (const char *) OUT_FORMAT + 1);
1792
#endif
1793
1794
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&column_width, nc);
1795
1796
    /* First we detect the width needed for each matrix column.
1797
     * snprintf() may be passed a NULL pointer with a buffer size of 0.
1798
     * It will then return the number of characters that would have been written,
1799
     * without writing anything. */
1800
0
    for (j = 0; j < nc; j++) {
1801
0
        for (i = 0; i < nr; i++) {
1802
0
            const int min_width = 1; /* minimum field width */
1803
0
            int width;
1804
#ifdef SNPRINTFUNC
1805
0
            width = SNPRINTFUNC(NULL, 0, MATRIX(*m, i, j));
1806
#else
1807
0
            width = snprintf(NULL, 0, OUT_FORMAT, MATRIX(*m, i, j));
1808
#endif
1809
0
            if (width < min_width) {
1810
0
                width = min_width;
1811
0
            }
1812
0
            if (width > VECTOR(column_width)[j]) {
1813
0
                VECTOR(column_width)[j] = width;
1814
0
            }
1815
0
        }
1816
0
    }
1817
1818
0
    for (i = 0; i < nr; i++) {
1819
0
        for (j = 0; j < nc; j++) {
1820
0
            if (j != 0) {
1821
0
                fputc(' ', file);
1822
0
            }
1823
#ifdef FPRINTFUNC_ALIGNED
1824
0
            FPRINTFUNC_ALIGNED(file, (int) VECTOR(column_width)[j], MATRIX(*m, i, j));
1825
#else
1826
0
            fprintf(file, format, (int) VECTOR(column_width)[j], MATRIX(*m, i, j));
1827
#endif
1828
0
        }
1829
0
        fprintf(file, "\n");
1830
0
    }
1831
1832
0
    igraph_vector_int_destroy(&column_width);
1833
0
    IGRAPH_FINALLY_CLEAN(1);
1834
1835
0
    return IGRAPH_SUCCESS;
1836
0
}
Unexecuted instantiation: igraph_matrix_fprint
Unexecuted instantiation: igraph_matrix_int_fprint
Unexecuted instantiation: igraph_matrix_char_fprint
Unexecuted instantiation: igraph_matrix_bool_fprint
Unexecuted instantiation: igraph_matrix_complex_fprint
1837
1838
#endif /* defined(OUT_FORMAT) || defined(FPRINTFUNC) */