/src/igraph/src/core/matrix.c
Line | Count | Source |
1 | | /* |
2 | | igraph library. |
3 | | Copyright (C) 2007-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_matrix.h" |
24 | | #include "igraph_types.h" |
25 | | |
26 | | #define BASE_IGRAPH_REAL |
27 | | #include "igraph_pmt.h" |
28 | | #include "matrix.pmt" |
29 | | #include "igraph_pmt_off.h" |
30 | | #undef BASE_IGRAPH_REAL |
31 | | |
32 | | #define BASE_INT |
33 | | #include "igraph_pmt.h" |
34 | | #include "matrix.pmt" |
35 | | #include "igraph_pmt_off.h" |
36 | | #undef BASE_INT |
37 | | |
38 | | #define BASE_CHAR |
39 | | #include "igraph_pmt.h" |
40 | | #include "matrix.pmt" |
41 | | #include "igraph_pmt_off.h" |
42 | | #undef BASE_CHAR |
43 | | |
44 | | #define BASE_BOOL |
45 | | #include "igraph_pmt.h" |
46 | | #include "matrix.pmt" |
47 | | #include "igraph_pmt_off.h" |
48 | | #undef BASE_BOOL |
49 | | |
50 | | #define BASE_COMPLEX |
51 | | #include "igraph_pmt.h" |
52 | | #include "matrix.pmt" |
53 | | #include "igraph_pmt_off.h" |
54 | | #undef BASE_COMPLEX |
55 | | |
56 | | /** |
57 | | * \ingroup matrix |
58 | | * \function igraph_matrix_complex_real |
59 | | * \brief Gives the real part of a complex matrix. |
60 | | * |
61 | | * \param m Pointer to a complex matrix. |
62 | | * \param real Pointer to an initialized matrix. The result will be stored here. |
63 | | * \return Error code. |
64 | | * |
65 | | * Time complexity: O(n), |
66 | | * n is the |
67 | | * number of elements in the matrix. |
68 | | */ |
69 | | |
70 | | igraph_error_t igraph_matrix_complex_real(const igraph_matrix_complex_t *m, |
71 | 0 | igraph_matrix_t *real) { |
72 | 0 | igraph_int_t nrow = igraph_matrix_complex_nrow(m); |
73 | 0 | igraph_int_t ncol = igraph_matrix_complex_ncol(m); |
74 | 0 | IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol)); |
75 | 0 | IGRAPH_CHECK(igraph_vector_complex_real(&m->data, &real->data)); |
76 | 0 | return IGRAPH_SUCCESS; |
77 | 0 | } |
78 | | |
79 | | /** |
80 | | * \ingroup matrix |
81 | | * \function igraph_matrix_complex_imag |
82 | | * \brief Gives the imaginary part of a complex matrix. |
83 | | * |
84 | | * \param m Pointer to a complex matrix. |
85 | | * \param imag Pointer to an initialized matrix. The result will be stored here. |
86 | | * \return Error code. |
87 | | * |
88 | | * Time complexity: O(n), |
89 | | * n is the |
90 | | * number of elements in the matrix. |
91 | | */ |
92 | | |
93 | | igraph_error_t igraph_matrix_complex_imag(const igraph_matrix_complex_t *m, |
94 | 0 | igraph_matrix_t *imag) { |
95 | 0 | igraph_int_t nrow = igraph_matrix_complex_nrow(m); |
96 | 0 | igraph_int_t ncol = igraph_matrix_complex_ncol(m); |
97 | 0 | IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol)); |
98 | 0 | IGRAPH_CHECK(igraph_vector_complex_imag(&m->data, &imag->data)); |
99 | 0 | return IGRAPH_SUCCESS; |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * \ingroup matrix |
104 | | * \function igraph_matrix_complex_realimag |
105 | | * \brief Gives the real and imaginary parts of a complex matrix. |
106 | | * |
107 | | * \param m Pointer to a complex matrix. |
108 | | * \param real Pointer to an initialized matrix. The real part will be stored here. |
109 | | * \param imag Pointer to an initialized matrix. The imaginary part will be stored here. |
110 | | * \return Error code. |
111 | | * |
112 | | * Time complexity: O(n), |
113 | | * n is the |
114 | | * number of elements in the matrix. |
115 | | */ |
116 | | |
117 | | igraph_error_t igraph_matrix_complex_realimag(const igraph_matrix_complex_t *m, |
118 | | igraph_matrix_t *real, |
119 | 0 | igraph_matrix_t *imag) { |
120 | 0 | igraph_int_t nrow = igraph_matrix_complex_nrow(m); |
121 | 0 | igraph_int_t ncol = igraph_matrix_complex_ncol(m); |
122 | 0 | IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol)); |
123 | 0 | IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol)); |
124 | 0 | IGRAPH_CHECK(igraph_vector_complex_realimag(&m->data, &real->data, |
125 | 0 | &imag->data)); |
126 | 0 | return IGRAPH_SUCCESS; |
127 | 0 | } |
128 | | |
129 | | /** |
130 | | * \ingroup matrix |
131 | | * \function igraph_matrix_complex_create |
132 | | * \brief Creates a complex matrix from a real and imaginary part. |
133 | | * |
134 | | * \param m Pointer to an uninitialized complex matrix. |
135 | | * \param real Pointer to the real part of the complex matrix. |
136 | | * \param imag Pointer to the imaginary part of the complex matrix. |
137 | | * \return Error code. |
138 | | * |
139 | | * Time complexity: O(n), |
140 | | * n is the |
141 | | * number of elements in the matrix. |
142 | | */ |
143 | | |
144 | | igraph_error_t igraph_matrix_complex_create(igraph_matrix_complex_t *m, |
145 | | const igraph_matrix_t *real, |
146 | 0 | const igraph_matrix_t *imag) { |
147 | 0 | igraph_int_t nrowr = igraph_matrix_nrow(real); |
148 | 0 | igraph_int_t ncolr = igraph_matrix_ncol(real); |
149 | 0 | igraph_int_t nrowi = igraph_matrix_nrow(imag); |
150 | 0 | igraph_int_t ncoli = igraph_matrix_ncol(imag); |
151 | |
|
152 | 0 | if (nrowr != nrowi || ncolr != ncoli) { |
153 | 0 | IGRAPH_ERRORF("Dimensions of real (%" IGRAPH_PRId " by %" IGRAPH_PRId ") and " |
154 | 0 | "imaginary (%" IGRAPH_PRId " by %" IGRAPH_PRId ") matrices must match.", |
155 | 0 | IGRAPH_EINVAL, nrowr, ncolr, nrowi, ncoli); |
156 | 0 | } |
157 | | |
158 | 0 | IGRAPH_CHECK(igraph_matrix_complex_init(m, nrowr, ncolr)); |
159 | | |
160 | 0 | for (igraph_int_t i = 0; i < nrowr * ncolr; i++) { |
161 | 0 | VECTOR(m->data)[i] = igraph_complex(VECTOR(real->data)[i], VECTOR(imag->data)[i]); |
162 | 0 | } |
163 | |
|
164 | 0 | return IGRAPH_SUCCESS; |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * \ingroup matrix |
169 | | * \function igraph_matrix_complex_create_polar |
170 | | * \brief Creates a complex matrix from a magnitude and an angle. |
171 | | * |
172 | | * \param m Pointer to an uninitialized complex matrix. |
173 | | * \param r Pointer to a real matrix containing magnitudes. |
174 | | * \param theta Pointer to a real matrix containing arguments (phase angles). |
175 | | * \return Error code. |
176 | | * |
177 | | * Time complexity: O(n), |
178 | | * n is the |
179 | | * number of elements in the matrix. |
180 | | */ |
181 | | |
182 | | igraph_error_t igraph_matrix_complex_create_polar(igraph_matrix_complex_t *m, |
183 | | const igraph_matrix_t *r, |
184 | 0 | const igraph_matrix_t *theta) { |
185 | 0 | igraph_int_t nrowr = igraph_matrix_nrow(r); |
186 | 0 | igraph_int_t ncolr = igraph_matrix_ncol(r); |
187 | 0 | igraph_int_t nrowt = igraph_matrix_nrow(theta); |
188 | 0 | igraph_int_t ncolt = igraph_matrix_ncol(theta); |
189 | |
|
190 | 0 | if (nrowr != nrowt || ncolr != ncolt) { |
191 | 0 | IGRAPH_ERRORF("Dimensions of magnitude (%" IGRAPH_PRId " by %" IGRAPH_PRId ") and " |
192 | 0 | "angle (%" IGRAPH_PRId " by %" IGRAPH_PRId ") matrices must match.", |
193 | 0 | IGRAPH_EINVAL, nrowr, ncolr, nrowt, ncolt); |
194 | 0 | } |
195 | | |
196 | 0 | IGRAPH_CHECK(igraph_matrix_complex_init(m, nrowr, ncolr)); |
197 | | |
198 | 0 | for (igraph_int_t i = 0; i < nrowr * ncolr; i++) { |
199 | 0 | VECTOR(m->data)[i] = igraph_complex_polar(VECTOR(r->data)[i], VECTOR(theta->data)[i]); |
200 | 0 | } |
201 | 0 | return IGRAPH_SUCCESS; |
202 | 0 | } |
203 | | |
204 | | /** |
205 | | * \function igraph_matrix_complex_all_almost_e |
206 | | * \brief Are all elements almost equal? |
207 | | * |
208 | | * Checks if the elements of two complex matrices are equal within a relative tolerance. |
209 | | * |
210 | | * \param lhs The first matrix. |
211 | | * \param rhs The second matrix. |
212 | | * \param eps Relative tolerance, see \ref igraph_complex_almost_equals() for details. |
213 | | * \return True if the two matrices are almost equal, false if there is at least |
214 | | * one differing element or if the matrices are not of the same dimensions. |
215 | | */ |
216 | | igraph_bool_t igraph_matrix_complex_all_almost_e(igraph_matrix_complex_t *lhs, |
217 | | igraph_matrix_complex_t *rhs, |
218 | 0 | igraph_real_t eps) { |
219 | 0 | return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow && |
220 | 0 | igraph_vector_complex_all_almost_e(&lhs->data, &rhs->data, eps); |
221 | 0 | } |
222 | | |
223 | | |
224 | | /** |
225 | | * \function igraph_matrix_all_almost_e |
226 | | * \brief Are all elements almost equal? |
227 | | * |
228 | | * Checks if the elements of two matrices are equal within a relative tolerance. |
229 | | * |
230 | | * \param lhs The first matrix. |
231 | | * \param rhs The second matrix. |
232 | | * \param eps Relative tolerance, see \ref igraph_almost_equals() for details. |
233 | | * \return True if the two matrices are almost equal, false if there is at least |
234 | | * one differing element or if the matrices are not of the same dimensions. |
235 | | */ |
236 | | igraph_bool_t igraph_matrix_all_almost_e(const igraph_matrix_t *lhs, |
237 | | const igraph_matrix_t *rhs, |
238 | 0 | igraph_real_t eps) { |
239 | 0 | return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow && |
240 | 0 | igraph_vector_all_almost_e(&lhs->data, &rhs->data, eps); |
241 | 0 | } |
242 | | |
243 | | |
244 | | /** |
245 | | * \function igraph_matrix_zapsmall |
246 | | * \brief Replaces small elements of a matrix by exact zeros. |
247 | | * |
248 | | * Matrix elements which are smaller in magnitude than the given absolute |
249 | | * tolerance will be replaced by exact zeros. The default tolerance |
250 | | * corresponds to two-thirds of the representable digits of \type igraph_real_t, |
251 | | * i.e. <code>DBL_EPSILON^(2/3)</code> which is approximately <code>10^-10</code>. |
252 | | * |
253 | | * \param m The matrix to process, it will be changed in-place. |
254 | | * \param tol Tolerance value. Numbers smaller than this in magnitude will |
255 | | * be replaced by zeros. Pass in zero to use the default tolerance. |
256 | | * Must not be negative. |
257 | | * \return Error code. |
258 | | * |
259 | | * \sa \ref igraph_matrix_all_almost_e() and \ref igraph_almost_equals() to |
260 | | * perform comparisons with relative tolerances. |
261 | | */ |
262 | 0 | igraph_error_t igraph_matrix_zapsmall(igraph_matrix_t *m, igraph_real_t tol) { |
263 | 0 | return igraph_vector_zapsmall(&m->data, tol); |
264 | 0 | } |
265 | | |
266 | | /** |
267 | | * \function igraph_matrix_complex_zapsmall |
268 | | * \brief Replaces small elements of a complex matrix by exact zeros. |
269 | | * |
270 | | * Similarly to \ref igraph_matrix_zapsmall(), small elements will be replaced |
271 | | * by zeros. The operation is performed separately on the real and imaginary |
272 | | * parts of the numbers. This way, complex numbers with a large real part and |
273 | | * tiny imaginary part will effectively be transformed to real numbers. |
274 | | * The default tolerance |
275 | | * corresponds to two-thirds of the representable digits of \type igraph_real_t, |
276 | | * i.e. <code>DBL_EPSILON^(2/3)</code> which is approximately <code>10^-10</code>. |
277 | | * |
278 | | * \param m The matrix to process, it will be changed in-place. |
279 | | * \param tol Tolerance value. Real and imaginary parts smaller than this in |
280 | | * magnitude will be replaced by zeros. Pass in zero to use the default |
281 | | * tolerance. Must not be negative. |
282 | | * \return Error code. |
283 | | * |
284 | | * \sa \ref igraph_matrix_complex_all_almost_e() and |
285 | | * \ref igraph_complex_almost_equals() to perform comparisons with relative |
286 | | * tolerances. |
287 | | */ |
288 | 0 | igraph_error_t igraph_matrix_complex_zapsmall(igraph_matrix_complex_t *m, igraph_real_t tol) { |
289 | 0 | return igraph_vector_complex_zapsmall(&m->data, tol); |
290 | 0 | } |