Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
EigenTest.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Teviet Creighton
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \file
22 * \ingroup MatrixUtils_h
23 * \author Creighton, T. D.
24 *
25 * \brief Computes the eigenvalues and eigenvectors of a matrix.
26 *
27 * ### Usage ###
28 *
29 * \code
30 * EigenTest [-n size | -i infile] [-o outfile] [-v] [-t] [-s] [-d debuglevel]
31 * \endcode
32 *
33 * ### Description ###
34 *
35 * This program computes the eigenvalues and eigenvectors of a symmetric
36 * real matrix using the routines in \ref Eigen_c.
37 * The following option flags are accepted:
38 * <ul>
39 * <li>[<tt>-n</tt>] Generates a random symmetric
40 * \c size\f$\times\f$\c size metric. If this option is not given,
41 * <tt>-n 3</tt> is assumed. This option (or its default) is
42 * \e overridden by the <tt>-i</tt> option, below.</li>
43 * <li>[<tt>-i</tt>] Reads a matrix from an input file \c infile
44 * using the function <tt>LALSReadVector()</tt>. If the input file is
45 * specified as \c stdin, the data is read from standard input (not a
46 * file named \c stdin).</li>
47 * <li>[<tt>-o</tt>] Writes the eigenvalues (and eigenvectors, if
48 * <tt>-v</tt> is specified below) to an output file \c outfile. If
49 * the output file is specified as \c stdout or \c stderr, the
50 * data is written to standard output or standard error (not to files
51 * named \c stdout or \c stderr). The eigenvalues are written
52 * as a single row of whitespace-separated numbers, and the eigenvectors
53 * as a square matrix where each column is the eigenvector of the
54 * corresponding eigenvalue. If this option is not specified, no output
55 * is written.</li>
56 * <li>[<tt>-v</tt>] Specifies that eigenvectors are to be computed as
57 * well as eigenvalues.</li>
58 * <li>[<tt>-t</tt>] Specifies that the computation is to be timed;
59 * timing information is written to \c stderr.</li>
60 * <li>[<tt>-s</tt>] Specifies that the calculations are to be done to
61 * single-precision (\c REAL4) rather than double-precision
62 * (\c REAL8).</li>
63 * <li>[<tt>-d</tt>] Sets the debug level to \c debuglevel. If not
64 * specified, level 0 is assumed.</li>
65 * </ul>
66 *
67 * \par Input format:
68 * If an input file or stream is specified, it
69 * should consist of \f$N\f$ consecutive lines of \f$N\f$ whitespace-separated
70 * numbers, that will be parsed using <tt>LALDReadVector()</tt>, or
71 * <tt>LALSReadVector()</tt> if the <tt>-s</tt> option was given. The data
72 * block may be preceded by blank or comment lines (lines containing no
73 * parseable numbers), but once a parseable number is found, the rest
74 * should follow in a contiguous block. If the lines contain different
75 * numbers of data columns, or if there are fewer lines than columns,
76 * then an error is returned; if there are \e more lines than
77 * columns, then the extra lines are ignored.
78 *
79 * \par Output format:
80 * If an output file or stream is specified,
81 * the input matrix is first written as \f$N\f$ consecutive lines of \f$N\f$
82 * whitespace-separated numbers. This will be followed with a blank
83 * line, then a single line of \f$N\f$ whitespace-separated numbers
84 * representing the eigenvalues. If the <tt>-v</tt> option is specified,
85 * another blank line will be appended to the output, followed by \f$N\f$
86 * lines of \f$N\f$ columns specifying the eigenvectors: the column under
87 * each eigenvalue is the corresponding eigenvector.
88 *
89 */
90
91/** \name Error Codes */
92/** @{ */
93#define EIGENTESTC_ENORM 0 /**< Normal exit */
94#define EIGENTESTC_ESUB 1 /**< Subroutine failed */
95#define EIGENTESTC_EARG 2 /**< Error parsing arguments */
96#define EIGENTESTC_EMEM 3 /**< Out of memory */
97#define EIGENTESTC_EFILE 4 /**< Could not open file */
98#define EIGENTESTC_EFMT 5 /**< Bad input file format */
99/** @} */
100
101
102/** \cond DONT_DOXYGEN */
103#define EIGENTESTC_MSGENORM "Normal exit"
104#define EIGENTESTC_MSGESUB "Subroutine failed"
105#define EIGENTESTC_MSGEARG "Error parsing arguments"
106#define EIGENTESTC_MSGEMEM "Out of memory"
107#define EIGENTESTC_MSGEFILE "Could not open file"
108#define EIGENTESTC_MSGEFMT "Bad input file format"
109
110
111#include <math.h>
112#include <time.h>
113#include <stdlib.h>
114#include <lal/LALStdio.h>
115#include <lal/LALStdlib.h>
116#include <lal/AVFactories.h>
117#include <lal/StreamInput.h>
118#include <lal/Random.h>
119#include <lal/MatrixUtils.h>
120
121/* Default parameter settings. */
122#define SIZE 3
123
124/* Usage format string. */
125#define USAGE "Usage: %s [-n size | -i infile] [-o outfile]\n" \
126"\t[-v] [-t] [-s] [-d debuglevel]\n"
127
128/* Macros for printing errors and testing subroutines. */
129#define ERROR( code, msg, statement ) \
130do \
131if ( lalDebugLevel & LALERROR ) \
132{ \
133 LALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n" \
134 " %s %s\n", (code), *argv, __FILE__, \
135 __LINE__, "$Id$", statement ? \
136 statement : "", (msg) ); \
137} \
138while (0)
139
140#define INFO( statement ) \
141do \
142if ( lalDebugLevel & LALINFO ) \
143{ \
144 LALPrintError( "Info[0]: program %s, file %s, line %d, %s\n" \
145 " %s\n", *argv, __FILE__, __LINE__, \
146 "$Id$", (statement) ); \
147} \
148while (0)
149
150#define WARNING( statement ) \
151do \
152if ( lalDebugLevel & LALWARNING ) \
153{ \
154 LALPrintError( "Warning[0]: program %s, file %s, line %d, %s\n" \
155 " %s\n", *argv, __FILE__, __LINE__, \
156 "$Id$", (statement) ); \
157} \
158while (0)
159
160#define SUB( func, statusptr ) \
161do \
162if ( (func), (statusptr)->statusCode ) \
163{ \
164 ERROR( EIGENTESTC_ESUB, EIGENTESTC_MSGESUB, \
165 "Function call \"" #func "\" failed:" ); \
166 return EIGENTESTC_ESUB; \
167} \
168while (0)
169
170int
171main( int argc, char **argv )
172{
173 static LALStatus stat; /* status structure */
174 int arg; /* command-line argument counter */
175 UINT4 n = SIZE, i, j; /* array size and indecies */
176 CHAR *infile = NULL; /* input filename */
177 CHAR *outfile = NULL; /* output filename */
178 BOOLEAN timing = 0; /* whether -t option was given */
179 BOOLEAN single = 0; /* whether -s option was given */
180 BOOLEAN vector = 0; /* whether -v option was given */
181 REAL4Vector *sValues = NULL; /* eigenvalues if -s option is given */
182 REAL8Vector *dValues = NULL; /* eigenvalues if -s option isn't given */
183 REAL4Array *sMatrix = NULL; /* matrix if -s option is given */
184 REAL8Array *dMatrix = NULL; /* matrix if -s option is not given */
185 UINT4Vector dimLength; /* dimensions used to create matrix */
186 UINT4 dims[2]; /* dimLength.data array */
187 clock_t start = 0, stop = 0; /* start and stop times for timing */
188 FILE *fp = NULL; /* input/output file pointer */
189
190
191 /*******************************************************************
192 * PARSE ARGUMENTS (arg stores the current position) *
193 *******************************************************************/
194
195 arg = 1;
196 while ( arg < argc ) {
197
198 /* Parse matrix size option. */
199 if ( !strcmp( argv[arg], "-n" ) ) {
200 if ( argc > arg + 1 ) {
201 arg++;
202 n = atoi( argv[arg++] );
203 } else {
204 ERROR( EIGENTESTC_EARG, EIGENTESTC_MSGEARG, 0 );
205 LALPrintError( USAGE, *argv );
206 return EIGENTESTC_EARG;
207 }
208 }
209
210 /* Parse input option. */
211 else if ( !strcmp( argv[arg], "-i" ) ) {
212 if ( argc > arg + 1 ) {
213 arg++;
214 infile = argv[arg++];
215 } else {
216 ERROR( EIGENTESTC_EARG, EIGENTESTC_MSGEARG, 0 );
217 LALPrintError( USAGE, *argv );
218 return EIGENTESTC_EARG;
219 }
220 }
221
222 /* Parse output option. */
223 else if ( !strcmp( argv[arg], "-o" ) ) {
224 if ( argc > arg + 1 ) {
225 arg++;
226 outfile = argv[arg++];
227 } else {
228 ERROR( EIGENTESTC_EARG, EIGENTESTC_MSGEARG, 0 );
229 LALPrintError( USAGE, *argv );
230 return EIGENTESTC_EARG;
231 }
232 }
233
234 /* Parse eigenvector, single-precision, and timing options. */
235 else if ( !strcmp( argv[arg], "-v" ) ) {
236 arg++;
237 vector = 1;
238 }
239 else if ( !strcmp( argv[arg], "-s" ) ) {
240 arg++;
241 single = 1;
242 }
243 else if ( !strcmp( argv[arg], "-t" ) ) {
244 arg++;
245 timing = 1;
246 }
247
248 /* Parse debug level option. */
249 else if ( !strcmp( argv[arg], "-d" ) ) {
250 if ( argc > arg + 1 ) {
251 arg++;
252 }else{
253 ERROR( EIGENTESTC_EARG, EIGENTESTC_MSGEARG, 0 );
254 LALPrintError( USAGE, *argv );
255 return EIGENTESTC_EARG;
256 }
257 }
258
259 /* Check for unrecognized options. */
260 else {
261 ERROR( EIGENTESTC_EARG, EIGENTESTC_MSGEARG, 0 );
262 LALPrintError( USAGE, *argv );
263 return EIGENTESTC_EARG;
264 }
265 } /* End of argument parsing loop. */
266
267
268 /*******************************************************************
269 * GET INPUT MATRIX *
270 *******************************************************************/
271
272 /* Set up array creation vector. */
273 dimLength.length = 2;
274 dimLength.data = dims;
275
276 /* Read input matrix file. */
277 if ( infile ) {
278
279 /* Open input file. */
280 if ( !strcmp( infile, "stdin" ) )
281 fp = stdin;
282 else if ( !( fp = fopen( infile, "r" ) ) ) {
283 ERROR( EIGENTESTC_EFILE, "- " EIGENTESTC_MSGEFILE, infile );
284 return EIGENTESTC_EFILE;
285 }
286
287 /* Single-precision mode: */
288 if ( single ) {
289 REAL4Vector *vec = NULL; /* parsed input line */
290
291 /* Read first non-comment line and create array. */
292 do {
293 SUB( LALSReadVector( &stat, &vec, fp, 0 ), &stat );
294 } while ( ( n = vec->length ) == 0 );
295 dimLength.data[0] = dimLength.data[1] = n;
296 SUB( LALSCreateArray( &stat, &sMatrix, &dimLength ), &stat );
297 for ( j = 0; j < n; j++ )
298 sMatrix->data[j] = vec->data[j];
299 SUB( LALSDestroyVector( &stat, &vec ), &stat );
300
301 /* Read remaining lines. */
302 for ( i = 1; i < n; i++ ) {
303 SUB( LALSReadVector( &stat, &vec, fp, 1 ), &stat );
304 if ( vec->length != n ) {
305 ERROR( EIGENTESTC_EFMT, EIGENTESTC_MSGEFMT, 0 );
306 return EIGENTESTC_EFMT;
307 }
308 for ( j = 0; j < n; j++ )
309 sMatrix->data[i*n+j] = vec->data[j];
310 SUB( LALSDestroyVector( &stat, &vec ), &stat );
311 }
312 }
313
314 /* Double-precision mode: */
315 else {
316 REAL8Vector *vec = NULL; /* parsed input line */
317
318 /* Read first non-comment line and create array. */
319 do {
320 SUB( LALDReadVector( &stat, &vec, fp, 0 ), &stat );
321 } while ( ( n = vec->length ) == 0 );
322 dimLength.data[0] = dimLength.data[1] = n;
323 SUB( LALDCreateArray( &stat, &dMatrix, &dimLength ), &stat );
324 for ( j = 0; j < n; j++ )
325 dMatrix->data[j] = vec->data[j];
326 SUB( LALDDestroyVector( &stat, &vec ), &stat );
327
328 /* Read remaining lines. */
329 for ( i = 1; i < n; i++ ) {
330 SUB( LALDReadVector( &stat, &vec, fp, 1 ), &stat );
331 if ( vec->length != n ) {
332 ERROR( EIGENTESTC_EFMT, EIGENTESTC_MSGEFMT, 0 );
333 return EIGENTESTC_EFMT;
334 }
335 for ( j = 0; j < n; j++ )
336 dMatrix->data[i*n+j] = vec->data[j];
337 SUB( LALDDestroyVector( &stat, &vec ), &stat );
338 }
339 }
340 }
341
342 /* Generate random matrix. */
343 else {
344 RandomParams *params;
345 params = XLALCreateRandomParams( 0 );
346 dimLength.data[0] = dimLength.data[1] = n;
347
348 /* Single-precision mode: */
349 if ( single ) {
350 SUB( LALSCreateArray( &stat, &sMatrix, &dimLength ), &stat );
351 for ( i = 0; i < n; i++ ) {
352 for ( j = 0; j < i; j++ ) {
353 sMatrix->data[i*n+j] = sMatrix->data[j*n+i] = 2.0*XLALUniformDeviate( params ) - 1.0;
354 }
355 sMatrix->data[i*(n+1)] = 2.0*XLALUniformDeviate( params ) - 1.0;
356 }
357 }
358
359 /* Double-precision mode: */
360 else {
361 SUB( LALDCreateArray( &stat, &dMatrix, &dimLength ), &stat );
362 for ( i = 0; i < n; i++ ) {
363 for ( j = 0; j < i; j++ ) {
364 dMatrix->data[i*n+j] = dMatrix->data[j*n+i]
365 = 2.0*(REAL8)( XLALUniformDeviate( params ) ) - 1.0;
366 }
367 dMatrix->data[i*(n+1)] = 2.0*(REAL8)( XLALUniformDeviate( params ) ) - 1.0;
368 }
369 }
370
371 XLALDestroyRandomParams( params );
372 }
373
374 /* Write input matrix to output file. */
375 if ( outfile ) {
376
377 /* Open output file. */
378 if ( !strcmp( outfile, "stdout" ) )
379 fp = stdout;
380 else if ( !strcmp( outfile, "stderr" ) )
381 fp = stderr;
382 else if ( !( fp = fopen( outfile, "r" ) ) ) {
383 ERROR( EIGENTESTC_EFILE, "- " EIGENTESTC_MSGEFILE, outfile );
384 return EIGENTESTC_EFILE;
385 }
386
387 /* Single-precision mode: */
388 if ( single ) {
389 for ( i = 0; i < n; i++ ) {
390 fprintf( fp, "%16.9e", sMatrix->data[i*n] );
391 for ( j = 1; j < n; j++ )
392 fprintf( fp, " %16.9e", sMatrix->data[i*n+j] );
393 fprintf( fp, "\n" );
394 }
395 }
396
397 /* Double-precision mode: */
398 else {
399 for ( i = 0; i < n; i++ ) {
400 fprintf( fp, "%25.17e", dMatrix->data[i*n] );
401 for ( j = 1; j < n; j++ )
402 fprintf( fp, " %25.17e", dMatrix->data[i*n+j] );
403 fprintf( fp, "\n" );
404 }
405 }
406 }
407
408
409 /*******************************************************************
410 * DIAGONALIZE MATRIX *
411 *******************************************************************/
412
413 if ( timing )
414 start = clock();
415
416 /* Single-precision mode: */
417 if ( single ) {
418 SUB( LALSCreateVector( &stat, &sValues, n ), &stat );
419 if ( vector ) {
420 SUB( LALSSymmetricEigenVectors( &stat, sValues, sMatrix ),
421 &stat );
422 }
423 }
424
425 /* Double-precision mode: */
426 else {
427 SUB( LALDCreateVector( &stat, &dValues, n ), &stat );
428 if ( vector ) {
429 SUB( LALDSymmetricEigenVectors( &stat, dValues, dMatrix ),
430 &stat );
431 }
432 }
433
434 if ( timing ) {
435 stop = clock();
436 fprintf( stderr, "Elapsed time: %.2f s\n",
437 (double)( stop - start )/CLOCKS_PER_SEC );
438 }
439
440 /* Write output. */
441 if ( outfile ) {
442
443 /* Write eigenvalues. */
444 fprintf( fp, "\n" );
445 if ( single ) {
446 fprintf( fp, "%16.9e", sValues->data[0] );
447 for ( j = 1; j < n; j++ )
448 fprintf( fp, " %16.9e", sValues->data[j] );
449 fprintf( fp, "\n" );
450 } else {
451 fprintf( fp, "%25.17e", dValues->data[0] );
452 for ( j = 1; j < n; j++ )
453 fprintf( fp, " %25.17e", dValues->data[j] );
454 fprintf( fp, "\n" );
455 }
456
457 /* Write eigenvectors. */
458 if ( vector ) {
459 fprintf( fp, "\n" );
460 if ( single ) {
461 for ( i = 0; i < n; i++ ) {
462 fprintf( fp, "%16.9e", sMatrix->data[i*n] );
463 for ( j = 1; j < n; j++ )
464 fprintf( fp, " %16.9e", sMatrix->data[i*n+j] );
465 fprintf( fp, "\n" );
466 }
467 } else {
468 for ( i = 0; i < n; i++ ) {
469 fprintf( fp, "%25.17e", dMatrix->data[i*n] );
470 for ( j = 1; j < n; j++ )
471 fprintf( fp, " %25.17e", dMatrix->data[i*n+j] );
472 fprintf( fp, "\n" );
473 }
474 }
475 }
476
477 /* Finished output. */
478 if ( fp != stdout && fp != stderr )
479 fclose( fp );
480 }
481
482 /* Clean up and exit. */
483 if ( single ) {
484 SUB( LALSDestroyVector( &stat, &sValues ), &stat );
485 SUB( LALSDestroyArray( &stat, &sMatrix ), &stat );
486 } else {
487 SUB( LALDDestroyVector( &stat, &dValues ), &stat );
488 SUB( LALDDestroyArray( &stat, &dMatrix ), &stat );
489 }
491 INFO( EIGENTESTC_MSGENORM );
492 return EIGENTESTC_ENORM;
493}
494/** \endcond */
#define EIGENTESTC_EFMT
Bad input file format.
Definition: EigenTest.c:98
#define EIGENTESTC_EARG
Error parsing arguments.
Definition: EigenTest.c:95
#define EIGENTESTC_ENORM
Normal exit.
Definition: EigenTest.c:93
#define EIGENTESTC_EFILE
Could not open file.
Definition: EigenTest.c:97
#define USAGE
Definition: GzipTest.c:27
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
#define SUB(func, statusptr)
#define ERROR(code, msg, statement)
#define INFO(statement)
#define SIZE
#define fprintf
int main(int argc, char *argv[])
Definition: cache.c:25
void LALSCreateArray(LALStatus *, REAL4Array **, UINT4Vector *)
void LALDCreateArray(LALStatus *, REAL8Array **, UINT4Vector *)
void LALSDestroyArray(LALStatus *, REAL4Array **)
void LALDDestroyArray(LALStatus *, REAL8Array **)
void LALDSymmetricEigenVectors(LALStatus *stat, REAL8Vector *values, REAL8Array *matrix)
Definition: Eigen.c:772
void LALSSymmetricEigenVectors(LALStatus *stat, REAL4Vector *values, REAL4Array *matrix)
Definition: Eigen.c:734
unsigned char BOOLEAN
Boolean logical type, see Headers LAL(Atomic)Datatypes.h for more details.
double REAL8
Double precision real floating-point number (8 bytes).
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
int LALPrintError(const char *fmt,...)
Definition: LALError.c:46
RandomParams * XLALCreateRandomParams(INT4 seed)
Definition: Random.c:102
REAL4 XLALUniformDeviate(RandomParams *params)
Definition: Random.c:146
void XLALDestroyRandomParams(RandomParams *params)
Definition: Random.c:140
void LALDReadVector(LALStatus *status, REAL8Vector **vector, FILE *stream, BOOLEAN strict)
void LALSReadVector(LALStatus *status, REAL4Vector **vector, FILE *stream, BOOLEAN strict)
void LALDCreateVector(LALStatus *, REAL8Vector **, UINT4)
void LALDDestroyVector(LALStatus *, REAL8Vector **)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
Multidimentional array of REAL4, see DATATYPE-Array types for more details.
Definition: LALDatatypes.h:220
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:222
Vector of type REAL4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:145
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:150
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:149
Multidimentional array of REAL8, see DATATYPE-Array types for more details.
Definition: LALDatatypes.h:226
REAL8 * data
Pointer to the data array.
Definition: LALDatatypes.h:228
Vector of type REAL8, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:154
REAL8 * data
Pointer to the data array.
Definition: LALDatatypes.h:159
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:158
This structure contains the parameters necessary for generating the current sequence of random number...
Definition: Random.h:86
Vector of type UINT4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:118
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:122
UINT4 * data
Pointer to the data array.
Definition: LALDatatypes.h:123
FILE * fp
Definition: tconvert.c:105