/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 | } 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 | } |
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 | } 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 | } 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 | } 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 | } |
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 | } 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 | } |
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 | } 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 | } |
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 | } 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 | } |
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 | } 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 | } 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 | } 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 | } 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) */ |