From 370e3064a39ed2db9ab7e57aa904c3ff00644c5c Mon Sep 17 00:00:00 2001 From: YaGeek Date: Sun, 3 Mar 2013 15:28:24 +0100 Subject: [PATCH] First commit - Original version --- DOC/fnindex.txt | 404 ++ DOC/tutorial.txt | 1320 +++++++ FILELIST | 187 + MACHINES/Cray/machine.h | 224 ++ MACHINES/Cray/makefile | 218 ++ MACHINES/Cray/mesch-cray.tar.Z | Bin 0 -> 7604 bytes MACHINES/Cray/mesch-cray.tar.Z.uu | 172 + MACHINES/Cray/patch.1 | 56 + MACHINES/Cray/patch.2 | 23 + MACHINES/Cray/patch.3 | 13 + MACHINES/GCC/machine.h | 191 + MACHINES/GCC/makefile | 187 + MACHINES/Linux/machine.h | 193 + MACHINES/Linux/makefile | 200 + MACHINES/MicroSoft/machine.h | 236 ++ MACHINES/MicroSoft/makefile | 238 ++ MACHINES/MicroSoft/stewart.zip | Bin 0 -> 4027 bytes MACHINES/OS2/README | 32 + MACHINES/OS2/machine.h | 191 + MACHINES/OS2/makefile | 208 ++ MACHINES/RS6000/machine.c | 238 ++ MACHINES/RS6000/machine.h | 186 + MACHINES/RS6000/makefile | 202 + MACHINES/SGI/machine.h | 224 ++ MACHINES/SGI/makefile | 215 ++ MACHINES/SPARC/machine.h | 187 + MACHINES/SPARC/makefile | 186 + MACHINES/ThinkC/README | 103 + MACHINES/ThinkC/TC-README | 184 + MACHINES/ThinkC/TC-machine-2.h | 385 ++ MACHINES/ThinkC/TC-machine.h | 382 ++ MACHINES/ThinkC/machine.h | 402 ++ MACHINES/TurboC/README | 25 + MACHINES/TurboC/filelist | 5 + MACHINES/TurboC/machine.h | 247 ++ MACHINES/TurboC/mail | 1974 ++++++++++ MACHINES/TurboC/meschach.mak | 375 ++ MACHINES/TurboC/meschtc.zip | Bin 0 -> 104828 bytes MACHINES/TurboC/meschtc.zip.uu | 2327 ++++++++++++ MACHINES/WatcomPC/machine.h | 233 ++ MACHINES/cornelison | 235 ++ MACHINES/w-mckinnon | 291 ++ README | 455 +++ arnoldi.c | 198 + autom4te.cache/output.0 | 5820 +++++++++++++++++++++++++++++ autom4te.cache/requests | 77 + autom4te.cache/traces.0 | 425 +++ bdfactor.c | 819 ++++ bkpfacto.c | 324 ++ chfactor.c | 242 ++ config.log | 1015 +++++ configure | 5820 +++++++++++++++++++++++++++++ configure.in | 109 + conjgrad.c | 349 ++ copy.c | 246 ++ copyright | 25 + dmacheps.c | 46 + err.c | 366 ++ err.h | 183 + extras.c | 500 +++ fft.c | 153 + fmacheps.c | 46 + givens.c | 159 + hessen.c | 174 + hsehldr.c | 248 ++ init.c | 346 ++ iotort.c | 141 + iter.h | 253 ++ iter0.c | 435 +++ iternsym.c | 1395 +++++++ itersym.c | 648 ++++ itertort.c | 691 ++++ ivecop.c | 334 ++ lanczos.c | 328 ++ ls.dat | 14 + lufactor.c | 314 ++ macheps | Bin 0 -> 8840 bytes machine.c | 170 + machine.h | 193 + machine.h.in | 227 ++ makefile | 202 + makefile.in | 214 ++ matlab.c | 218 ++ matlab.h | 113 + matop.c | 556 +++ matrix.h | 689 ++++ matrix2.h | 236 ++ matrixio.c | 772 ++++ maxint | Bin 0 -> 8760 bytes maxint.c | 38 + meminfo.c | 442 +++ meminfo.h | 164 + memory.c | 1043 ++++++ memstat.c | 421 +++ memtort.c | 760 ++++ mfunc.c | 434 +++ mfuntort.c | 181 + norm.c | 230 ++ oldnames.h | 150 + otherio.c | 180 + pxop.c | 393 ++ qrfactor.c | 583 +++ rk4.dat | 12 + schur.c | 692 ++++ solve.c | 308 ++ sparse.c | 1162 ++++++ sparse.h | 221 ++ sparse2.h | 95 + sparseio.c | 361 ++ spbkp.c | 1445 +++++++ spchfctr.c | 659 ++++ splufctr.c | 433 +++ sprow.c | 774 ++++ spswap.c | 326 ++ sptort.c | 485 +++ submat.c | 206 + svd.c | 433 +++ symmeig.c | 223 ++ torture.c | 1052 ++++++ tutadv.c | 192 + tutorial.c | 321 ++ update.c | 139 + vecop.c | 673 ++++ version.c | 72 + zcopy.c | 220 ++ zfunc.c | 244 ++ zgivens.c | 184 + zhessen.c | 162 + zhsehldr.c | 255 ++ zlufctr.c | 291 ++ zmachine.c | 203 + zmatio.c | 449 +++ zmatlab.c | 223 ++ zmatop.c | 615 +++ zmatrix.h | 321 ++ zmatrix2.h | 120 + zmemory.c | 745 ++++ znorm.c | 208 ++ zqrfctr.c | 548 +++ zschur.c | 386 ++ zsolve.c | 300 ++ ztorture.c | 720 ++++ zvecop.c | 568 +++ 143 files changed, 61252 insertions(+) create mode 100644 DOC/fnindex.txt create mode 100644 DOC/tutorial.txt create mode 100644 FILELIST create mode 100644 MACHINES/Cray/machine.h create mode 100644 MACHINES/Cray/makefile create mode 100644 MACHINES/Cray/mesch-cray.tar.Z create mode 100644 MACHINES/Cray/mesch-cray.tar.Z.uu create mode 100644 MACHINES/Cray/patch.1 create mode 100644 MACHINES/Cray/patch.2 create mode 100644 MACHINES/Cray/patch.3 create mode 100644 MACHINES/GCC/machine.h create mode 100644 MACHINES/GCC/makefile create mode 100644 MACHINES/Linux/machine.h create mode 100644 MACHINES/Linux/makefile create mode 100644 MACHINES/MicroSoft/machine.h create mode 100644 MACHINES/MicroSoft/makefile create mode 100644 MACHINES/MicroSoft/stewart.zip create mode 100644 MACHINES/OS2/README create mode 100644 MACHINES/OS2/machine.h create mode 100644 MACHINES/OS2/makefile create mode 100644 MACHINES/RS6000/machine.c create mode 100644 MACHINES/RS6000/machine.h create mode 100644 MACHINES/RS6000/makefile create mode 100644 MACHINES/SGI/machine.h create mode 100644 MACHINES/SGI/makefile create mode 100644 MACHINES/SPARC/machine.h create mode 100644 MACHINES/SPARC/makefile create mode 100644 MACHINES/ThinkC/README create mode 100644 MACHINES/ThinkC/TC-README create mode 100644 MACHINES/ThinkC/TC-machine-2.h create mode 100644 MACHINES/ThinkC/TC-machine.h create mode 100644 MACHINES/ThinkC/machine.h create mode 100644 MACHINES/TurboC/README create mode 100644 MACHINES/TurboC/filelist create mode 100644 MACHINES/TurboC/machine.h create mode 100644 MACHINES/TurboC/mail create mode 100644 MACHINES/TurboC/meschach.mak create mode 100644 MACHINES/TurboC/meschtc.zip create mode 100644 MACHINES/TurboC/meschtc.zip.uu create mode 100644 MACHINES/WatcomPC/machine.h create mode 100644 MACHINES/cornelison create mode 100644 MACHINES/w-mckinnon create mode 100644 README create mode 100644 arnoldi.c create mode 100644 autom4te.cache/output.0 create mode 100644 autom4te.cache/requests create mode 100644 autom4te.cache/traces.0 create mode 100644 bdfactor.c create mode 100644 bkpfacto.c create mode 100644 chfactor.c create mode 100644 config.log create mode 100755 configure create mode 100644 configure.in create mode 100644 conjgrad.c create mode 100644 copy.c create mode 100644 copyright create mode 100644 dmacheps.c create mode 100644 err.c create mode 100644 err.h create mode 100644 extras.c create mode 100644 fft.c create mode 100644 fmacheps.c create mode 100644 givens.c create mode 100644 hessen.c create mode 100644 hsehldr.c create mode 100644 init.c create mode 100644 iotort.c create mode 100644 iter.h create mode 100644 iter0.c create mode 100644 iternsym.c create mode 100644 itersym.c create mode 100644 itertort.c create mode 100644 ivecop.c create mode 100644 lanczos.c create mode 100644 ls.dat create mode 100644 lufactor.c create mode 100755 macheps create mode 100644 machine.c create mode 100644 machine.h create mode 100644 machine.h.in create mode 100644 makefile create mode 100644 makefile.in create mode 100644 matlab.c create mode 100644 matlab.h create mode 100644 matop.c create mode 100644 matrix.h create mode 100644 matrix2.h create mode 100644 matrixio.c create mode 100755 maxint create mode 100644 maxint.c create mode 100644 meminfo.c create mode 100644 meminfo.h create mode 100644 memory.c create mode 100644 memstat.c create mode 100644 memtort.c create mode 100644 mfunc.c create mode 100644 mfuntort.c create mode 100644 norm.c create mode 100644 oldnames.h create mode 100644 otherio.c create mode 100644 pxop.c create mode 100644 qrfactor.c create mode 100644 rk4.dat create mode 100644 schur.c create mode 100644 solve.c create mode 100644 sparse.c create mode 100644 sparse.h create mode 100644 sparse2.h create mode 100644 sparseio.c create mode 100644 spbkp.c create mode 100644 spchfctr.c create mode 100644 splufctr.c create mode 100644 sprow.c create mode 100644 spswap.c create mode 100644 sptort.c create mode 100644 submat.c create mode 100644 svd.c create mode 100644 symmeig.c create mode 100644 torture.c create mode 100644 tutadv.c create mode 100644 tutorial.c create mode 100644 update.c create mode 100644 vecop.c create mode 100644 version.c create mode 100644 zcopy.c create mode 100644 zfunc.c create mode 100644 zgivens.c create mode 100644 zhessen.c create mode 100644 zhsehldr.c create mode 100644 zlufctr.c create mode 100644 zmachine.c create mode 100644 zmatio.c create mode 100644 zmatlab.c create mode 100644 zmatop.c create mode 100644 zmatrix.h create mode 100644 zmatrix2.h create mode 100644 zmemory.c create mode 100644 znorm.c create mode 100644 zqrfctr.c create mode 100644 zschur.c create mode 100644 zsolve.c create mode 100644 ztorture.c create mode 100644 zvecop.c diff --git a/DOC/fnindex.txt b/DOC/fnindex.txt new file mode 100644 index 0000000..e049ad7 --- /dev/null +++ b/DOC/fnindex.txt @@ -0,0 +1,404 @@ + + FUNCTION INDEX + ============== + +In the descriptions below, matrices are represented by capital letters, +vectors by lower case letters and scalars by alpha. + + Function Description + +band2mat() Convert band matrix to dense matrix +bd_free() Deallocate (destroy) band matrix +bd_get() Allocate and initialise band matrix +bd_transp() Transpose band matrix +bd_resize() Resize band matrix +bdLDLfactor() Band LDL^T factorisation +bdLDLsolve() Solve Ax=b using band LDL^T factors +bdLUfactor() Band LU factorisation +bdLUsolve() Solve Ax=b using band LU factors +bisvd() SVD of bi-diagonal matrix +BKPfactor() Bunch-Kaufman-Parlett factorisation +BKPsolve() Bunch-Kaufman-Parlett solver +catch() Catch a raised error (macro) +catchall() Catch any raised error (macro) +catch_FPE() Catch floating point error (sets flag) +CHfactor() Dense Cholesky factorisation +CHsolve() Cholesky solver +d_save() Save real in MATLAB format +Dsolve() Solve Dx=y , D diagonal +ERRABORT() Abort on error (sets flag, macro) +ERREXIT() Exit on error (sets flag, macro) +error() Raise an error (macro, see ev_err()) +err_list_attach() Attach new list of errors +err_list_free() Discard list of errors +err_is_list_attached() Checks for an error list +ev_err() Raise an error (function) +fft() Computes Fast Fourier Transform +finput() Input a simple data item from a stream +fprompter() Print prompt to stderr +get_col() Extract a column from a matrix +get_row() Extract a row from a matrix +givens() Compute Givens parameters +hhtrcols() Compute AP^T where P is a Householder matrix +hhtrrows() Compute PA where P is a Householder matrix +hhtrvec() Compute Px where P is a Householder matrix +hhvec() Compute parameters for a Householder matrix +ifft() Computes inverse FFT +in_prod() Inner product of vectors +input() Input a simple data item from stdin (macro) +iter_arnoldi() Arnoldi iterative method +iter_arnoldi_iref() Arnoldi iterative method with refinement +iter_ATx() Set A^T in ITER structure +iter_Ax() Set A in ITER structure +iter_Bx() Set preconditioner in ITER structure +iter_cg() Conjugate gradients iterative method +iter_cgne() Conjugate gradients for normal equations +iter_cgs() CGS iterative method +iter_copy() Copy ITER data structures +iter_copy2() Shallow copy of ITER data structures +iter_dump() Dump ITER data structure to a stream +iter_free() Free (deallocate) ITER structure +iter_get() Allocate ITER structure +iter_gmres() GMRES iterative method +iter_lanczos() Lanczos iterative method +iter_lanczos2() Lanczos method with Cullum and Willoughby extensions +iter_lsqr() LSQR iterative method +iter_mgcr() MGCR iterative method +iter_resize() Resize vectors in an ITER data structure +iter_spcg() Sparse matrix CG method +iter_spcgne() Sparse matrix CG method for normal equations +iter_spcgs() Sparse matrix CGS method +iter_spgmres() Sparse matrix GMRES method +iter_splsqr() Sparse matrix LSQR method +iter_spmgcr() Sparse matrix MGCR method +iv_add() Add integer vectors +iv_copy() Copy integer vector +iv_dump() Dump integer vector to a stream +iv_finput() Input integer vector from a stream +iv_foutput() Output integer vector to a stream +IV_FREE() Free (deallocate) an integer vector (macro) +iv_free() Free (deallocate) integer vector (function) +iv_free_vars() Free a list of integer vectors +iv_get() Allocate and initialise an integer vector +iv_get_vars() Allocate list of integer vectors +iv_input() Input integer vector from stdin (macro) +iv_output() Output integer vector to stdout (macro) +iv_resize() Resize an integer vector +iv_resize_vars() Resize a list of integer vectors +iv_sub() Subtract integer vectors +LDLfactor() LDL^T factorisation +LDLsolve() LDL^T solver +LDLupdate() Update LDL^T factorisation +Lsolve() Solve Lx=y , L lower triangular +LTsolve() Solve L^Tx=y , L lower triangular +LUcondest() Estimate a condition number using LU factors +LUfactor() Compute LU factors with implicit scaled partial pivoting +LUsolve() Solve Ax=b using LU factors +LUTsolve() Solve A^Tx=b usng LU factors +m_add() Add matrices +makeQ() Form Q matrix for QR factorisation +makeR() Form R matrix for QR factorisation +mat2band() Extract band matrix from dense matrix +MCHfactor() Modified Cholesky factorisation + (actually factors A+D, D diagonal, instead of A) +m_copy() Copy dense matrix +m_dump() Dump matrix data structure to a stream +mem_attach_list() Adds a new family of types +mem_bytes() Notify change in memory usage (macro) +mem_bytes_list() Notify change in memory usage +mem_free_list() Frees a family of types +mem_info_bytes() Number of bytes used by a type +mem_info_numvar() Number of structures of a type +mem_info_file() Print memory info to a stream +mem_info_is_on() Is memory data being accumulated? +mem_info_on() Turns memory info system on/off +mem_is_list_attached() Is list of types attached? +mem_numvar() Notify change in number of structures allocated (macro) +mem_numvar_list() Notify change in number of structures allocated +mem_stat_dump() Prints information on registered workspace +mem_stat_free() Frees (deallocates) static workspace +mem_stat_mark() Sets mark for workspace +MEM_STAT_REG() Register static workspace (macro) +mem_stat_show_mark() Current workspace group +m_exp() Computes matrix exponential +m_finput() Input matrix from a stream +m_foutput() Output matrix to a stream +M_FREE() Free (deallocate) a matrix (macro) +m_free() Free (deallocate) matrix (function) +m_free_vars() Free a list of matrices +m_get() Allocate and initialise a matrix +m_get_vars() Allocate list of matrices +m_ident() Sets matrix to identity matrix +m_input() Input matrix from stdin (macro) +m_inverse() Invert matrix +m_load() Load matrix in MATLAB format +m_mlt() Multiplies matrices +mmtr_mlt() Computes AB^T +m_norm1() Computes ||A||_1 of a matrix +m_norm_frob() Computes the Frobenius norm of a matrix +m_norm_inf() Computes ||A||_inf of a matrix +m_ones() Set matrix to all 1's +m_output() Output matrix to stdout (macro) +m_poly() Computes a matrix polynomial +m_pow() Computes integer power of a matrix +mrand() Generates pseudo-random real number +m_rand() Randomise entries of a matrix +mrandlist() Generates array of pseudo-random numbers +m_resize() Resize matrix +m_resize_vars() Resize a list of matrices +m_save() Save matrix in MATLAB format +m_sub() Subtract matrices +m_transp() Transpose matrix +mtrm_mlt() Computes A^TB +mv_mlt() Computes Ax +mv_mltadd() Computes y <- Ax+y +m_zero() Zero a matrix +ON_ERROR() Error handler (macro) +prompter() Print prompt message to stdout +px_cols() Permute the columns of a matrix +px_copy() Copy permutation +px_dump() Dump permutation data structure to a stream +px_finput() Input permutation from a stream +px_foutput() Output permutation to a stream +PX_FREE() Free (deallocate) a permutation (macro) +px_free() Free (deallocate) permutation (function) +px_free_vars() Free a list of permutations +px_get() Allocate and initialise a permutation +px_get_vars() Allocate a list of permutations +px_ident() Sets permutation to identity +px_input() Input permutation from stdin (macro) +px_inv() Invert permutation +pxinv_vec() Computes P^Tx where P is a permutation matrix +pxinv_zvec() Computes P^Tx where P is a permutation matrix (complex) +px_mlt() Multiply permutations +px_output() Output permutation to stdout (macro) +px_resize() Resize a permutation +px_resize_vars() Resize a list of permutations +px_rows() Permute the rows of a matrix +px_sign() Returns the sign of the permutation +px_transp() Transpose a pair of entries +px_vec() Computes Px where P is a permutation matrix +px_zvec() Computes Px where P is a permutation matrix (complex) +QRCPfactor() QR factorisation with column pivoting +QRfactor() QR factorisation +QRsolve() Solve Ax=b using QR factorisation +QRTsolve() Solve A^Tx=b using QR factorisation +QRupdate() Update explicit QR factors +rot_cols() Apply Givens rotation to the columns of a matrix +rot_rows() Apply Givens rotation to the rows of a matrix +rot_vec() Apply Givens rotation to a vector +rot_zvec() Apply complex Givens rotation to a vector +schur() Compute real Schur form +schur_evals() Compute eigenvalues from the real Schur form +schur_vecs() Compute eigenvectors from the real Schur form +set_col() Set the column of a matrix to a given vector +set_err_flag() Control behaviour of ev_err() +set_row() Set the row of a matrix to a given vector +sm_mlt() Scalar-matrix multiplication +smrand() Set seed for mrand() +spBKPfactor() Sparse symmetric indefinite factorsiation +spBKPsolve() Sparse symmetric indefinite solver +spCHfactor() Sparse Cholesky factorisation +spCHsolve() Sparse Cholesky solver +spCHsymb() Symbolic sparse Cholesky factorisation + (no floating point operations) +sp_col_access() Sets up column access paths for a sparse matrix +sp_compact() Eliminates zero entries in a sparse matrix +sp_copy() Copies a sparse matrix +sp_copy2() Copies a sparse matrix into another +sp_diag_access() Sets up diagonal access paths for a sparse matrix +sp_dump() Dump sparse matrix data structure to a stream +sp_finput() Input sparse matrix from a stream +sp_foutput() Output a sparse matrix to a stream +sp_free() Free (deallocate) a sparse matrix +sp_get() Allocate and initialise a sparse matrix +sp_get_val() Get the (i,j) entry of a sparse matrix +spICHfactor() Sparse incomplete Cholesky factorisation +sp_input() Input a sparse matrix form stdin +spLUfactor() Sparse LU factorisation using partial pivoting +spLUsolve() Solves Ax=b using sparse LU factors +spLUTsolve() Solves A^Tx=b using sparse LU factors +sp_mv_mlt() Computes Ax for sparse A +sp_output() Outputs a sparse matrix to a stream (macro) +sp_resize() Resize a sparse matrix +sprow_add() Adds a pair of sparse rows +sprow_foutput() Output sparse row to a stream +sprow_get() Allocate and initialise a sparse row +sprow_get_idx() Get location of an entry in a sparse row +sprow_merge() Merge two sparse rows +sprow_mltadd() Sparse row vector multiply-and-add +sprow_set_val() Set an entry in a sparse row +sprow_smlt() Multiplies a sparse row by a scalar +sprow_sub() Subtracts a sparse row from another +sprow_xpd() Expand a sparse row +sp_set_val() Set the (i,j) entry of a sparse matrix +sp_vm_mlt() Compute x^TA for sparse A +sp_zero() Zero (but do not remove) all entries of a sparse matrix +svd() Compute the SVD of a matrix +sv_mlt() Scalar-vector multiply +symmeig() Compute eigenvalues/vectors of a symmetric matrix +tracecatch() Catch and re-raise errors (macro) +trieig() Compute eigenvalues/vectors of a symmetric tridiagonal matrix +Usolve() Solve Ux=b where U is upper triangular +UTsolve() Solve U^Tx=b where U is upper triangular +v_add() Add vectors +v_conv() Convolution product of vectors +v_copy() Copy vector +v_dump() Dump vector data structure to a stream +v_finput() Input vector from a stream +v_foutput() Output vector to a stream +V_FREE() Free (deallocate) a vector (macro) +v_free() Free (deallocate) vector (function) +v_free_vars() Free a list of vectors +v_get() Allocate and initialise a vector +v_get_vars() Allocate list of vectors +v_input() Input vector from stdin (macro) +v_lincomb() Compute sum of a_i x_i for an array of vectors +v_linlist() Compute sum of a_i x_i for a list of vectors +v_map() Apply function componentwise to a vector +v_max() Computes max vector entry and index +v_min() Computes min vector entry and index +v_mltadd() Computes y <- alpha*x+y for vectors x , y +vm_mlt() Computes x^TA +vm_mltadd() Computes y^T <- y^T+x^TA +v_norm1() Computes ||x||_1 for a vector +v_norm2() Computes ||x||_2 (the Euclidean norm) of a vector +v_norm_inf() Computes ||x||_inf for a vector +v_ones() Set vector to all 1's +v_output() Output vector to stdout (macro) +v_pconv() Periodic convolution of two vectors +v_rand() Randomise entries of a vector +v_resize() Resize a vector +v_resize_vars() Resize a list of vectors +v_save() Save a vector in MATLAB format +v_slash() Computes componentwise ratio of vectors +v_sort() Sorts vector components +v_star() Componentwise vector product +v_sub() Subtract two vectors +v_sum() Sum of components of a vector +v_zero() Zero a vector +zabs() Complex absolute value (modulus) +zadd() Add complex numbers +zconj() Conjugate complex number +zdiv() Divide complex numbers +zexp() Complex exponential +z_finput() Read complex number from file or stream +z_foutput() Prints complex number to file or stream +zgivens() Compute complex Givens' rotation +zhhtrcols() Apply Householder transformation: PA (complex) +zhhtrrows() Apply Householder transformation: AP (complex) +zhhtrvec() Apply Householder transformation: Px (complex) +zhhvec() Compute Householder transformation +zin_prod() Complex inner product +z_input() Read complex number from stdin +zinv() Computes 1/z (complex) +zLAsolve() Solve L^*x=b , L complex lower triangular +zlog() Complex logarithm +zLsolve() Solve Lx=b , L complex lower triangular +zLUAsolve() Solve A^*x=b using complex LU factorisation + (A^* - adjoint of A, A is complex) +zLUcondest() Complex LU condition estimate +zLUfactor() Complex LU factorisation +zLUsolve() Solve Ax=b using complex LU factorisation +zm_add() Add complex matrices +zm_adjoint() Computes adjoint of complex matrix +zmake() Construct complex number from real and imaginary parts +zmakeQ() Construct Q matrix for complex QR +zmakeR() Construct R matrix for complex QR +zmam_mlt() Computes A^*B (complex) +zm_dump() Dump complex matrix to stream +zm_finput() Input complex matrix from stream +ZM_FREE() Free (deallocate) complex matrix (macro) +zm_free() Free (deallocate) complex matrix (function) +zm_free_vars() Free a list of complex matrices +zm_get() Allocate complex matrix +zm_get_vars() Allocate a list of complex matrices +zm_input() Input complex matrix from stdin +zm_inverse() Compute inverse of complex matrix +zm_load() Load complex matrix in MATLAB format +zmlt() Multiply complex numbers +zmma_mlt() Computes AB^* (complex) +zm_mlt() Multiply complex matrices +zm_norm1() Complex matrix 1-norm +zm_norm_frob() Complex matrix Frobenius norm +zm_norm_inf() Complex matrix infinity-norm +zm_rand() Randomise complex matrix +zm_resize() Resize complex matrix +zm_resize_vars() Resize a list of complex matrices +zm_save() Save complex matrix in MATLAB format +zm_sub() Subtract complex matrices +zmv_mlt() Complex matrix-vector multiply +zmv_mltadd() Complex matrix-vector multiply and add +zm_zero() Zero complex matrix +zneg() Computes -z (complex) +z_output() Print complex number to stdout +zQRCPfactor() Complex QR factorisation with column pivoting +zQRCPsolve() Solve Ax = b using complex QR factorisation +zQRfactor() Complex QR factorisation +zQRAsolve() Solve A^*x = b using complex QR factorisation +zQRsolve() Solve Ax = b using complex QR factorisation +zrot_cols() Complex Givens' rotation of columns +zrot_rows() Complex Givens' rotation of rows +z_save() Save complex number in MATLAB format +zschur() Complex Schur factorisation +zset_col() Set column of complex matrix +zset_row() Set row of complex matrix +zsm_mlt() Complex scalar-matrix product +zsqrt() Square root z (complex) +zsub() Subtract complex numbers +zUAsolve() Solve U^*x=b , U complex upper triangular +zUsolve() Solve Ux=b , U complex upper triangular +zv_add() Add complex vectors +zv_copy() Copy complex vector +zv_dump() Dump complex vector to a stream +zv_finput() Input complex vector from a stream +ZV_FREE() Free (deallocate) complex vector (macro) +zv_free() Free (deallocate) complex vector (function) +zv_free_vars() Free a list of complex vectors +zv_get() Allocate complex vector +zv_get_vars() Allocate a list of complex vectors +zv_input() Input complex vector from a stdin +zv_lincomb() Compute sum of a_i x_i for an array of vectors +zv_linlist() Compute sum of a_i x_i for a list of vectors +zv_map() Apply function componentwise to a complex vector +zv_mlt() Complex scalar-vector product +zv_mltadd() Complex scalar-vector multiply and add +zvm_mlt() Computes A^*x (complex) +zvm_mltadd() Computes A^*x+y (complex) +zv_norm1() Complex vector 1-norm vnorm1() +zv_norm2() Complex vector 2-norm (Euclidean norm) +zv_norm_inf() Complex vector infinity- (or supremum) norm +zv_rand() Randomise complex vector +zv_resize() Resize complex vector +zv_resize_vars() Resize a list of complex vectors +zv_save() Save complex vector in MATLAB format +zv_slash() Componentwise ratio of complex vectors +zv_star() Componentwise product of complex vectors +zv_sub() Subtract complex vectors +zv_sum() Sum of components of a complex vector +zv_zero() Zero complex vector + + + + Low level routines + + + Function Description + +__add__() Add arrays +__ip__() Inner product of arrays +MEM_COPY() Copy memory (macro) +MEM_ZERO() Zero memory (macro) +__mltadd__() Forms x+ alpha*y for arrays +__smlt__() Scalar-vector multiplication for arrays +__sub__() Subtract an array from another +__zadd__() Add complex arrays +__zconj__() Conjugate complex array +__zero__() Zero an array +__zip__() Complex inner product of arrays +__zmlt__() Complex array scalar product +__zmltadd__() Complex array saxpy +__zsub__() Subtract complex arrays +__zzero__() Zero a complex array + + diff --git a/DOC/tutorial.txt b/DOC/tutorial.txt new file mode 100644 index 0000000..de1c93c --- /dev/null +++ b/DOC/tutorial.txt @@ -0,0 +1,1320 @@ + + + MESCHACH VERSION 1.2A + --------------------- + + + TUTORIAL + ======== + + + In this manual the basic data structures are introduced, and some of the +more basic operations are illustrated. Then some examples of how to use +the data structures and procedures to solve some simple problems are given. +The first example program is a simple 4th order Runge-Kutta solver for +ordinary differential equations. The second is a general least squares +equation solver for over-determined equations. The third example +illustrates how to solve a problem involving sparse matrices. These +examples illustrate the use of matrices, matrix factorisations and solving +systems of linear equations. The examples described in this manual are +implemented in tutorial.c. + + While the description of each aspect of the system is brief and far from +comprehensive, the aim is to show the different aspects of how to set up +programs and routines and how these work in practice, which includes I/O +and error-handling issues. + + + +1. THE DATA STRUCTURES AND SOME BASIC OPERATIONS + + The three main data structures are those describing vectors, matrices +and permutations. These have been used to create data structures for +simplex tableaus for linear programming, and used with data structures for +sparse matrices etc. To use the system reliably, you should always use +pointers to these data structures and use library routines to do all the +necessary initialisation. + + In fact, for the operations that involve memory management (creation, +destruction and resizing), it is essential that you use the routines +provided. + + For example, to create a matrix A of size 34 , a vector x of dimension +10, and a permutation p of size 10, use the following code: + + + #include "matrix.h" + .............. + main() + { + MAT *A; + VEC *x; + PERM *p; + .......... + A = m_get(3,4); + x = v_get(10); + p = px_get(10); + .......... + } + + + This initialises these data structures to have the given size. The +matrix A and the vector x are initially all zero, while p is initially the +identity permutation. + + They can be disposed of by calling M_FREE(A), V_FREE(x) and PX_FREE(p) +respectively if you need to re-use the memory for something else. The +elements of each data structure can be accessed directly using the members +(or fields) of the corresponding structures. For example the (i,j) +component of A is accessed by A->me[i][j], x_i by x->ve[i] and p_i by +p->pe[i]. + + Their sizes are also directly accessible: A->m and A->n are the number +of rows and columns of A respectively, x->dim is the dimension of x , and +size of p is p->size. + + Note that the indexes are zero relative just as they are in ordinary C, +so that the index i in x->ve[i] can range from 0 to x->dim -1 . Thus the +total number of entries of a vector is exactly x->dim. + + While this alone is sufficient to allow a programmer to do any desired +operation with vectors and matrices it is neither convenient for the +programmer, nor efficient use of the CPU. A whole library has been +implemented to reduce the burden on the programmer in implementing +algorithms with vectors and matrices. For instance, to copy a vector from +x to y it is sufficient to write y = v_copy(x,VNULL). The VNULL is the +NULL vector, and usually tells the routine called to create a vector for +output. + + Thus, the v_copy function will create a vector which has the same size +as x and all the components are equal to those of x. If y has already +been created then you can write y = v_copy(x,y); in general, writing +``v_copy(x,y);'' is not enough! If y is NULL, then it is created (to have +the correct size, i.e. the same size as x), and if it is the wrong size, +then it is resized to have the correct size (i.e. same size as x). Note +that for all the following functions, the output value is returned, even if +you have a non-NULL value as the output argument. This is the standard +across the entire library. + + Addition, subtraction and scalar multiples of vectors can be computed by +calls to library routines: v_add(x,y,out), v_sub(x,y,out), sv_mlt(s,x,out) +where x and y are input vectors (with data type VEC *), out is the output +vector (same data type) and s is a double precision number (data type +double). There is also a special combination routine, which computes +out=v_1+s,v_2 in a single routine: v_mltadd(v1,v2,s,out). This is not only +extremely useful, it is also more efficient than using the scalar-vector +multiply and vector addition routines separately. + + Inner products can be computed directly: in_prod(x,y) returns the inner +product of x and y. Note that extended precision evaluation is not +guaranteed. The standard installation options uses double precision +operations throughout the library. + + Equivalent operations can be performed on matrices: m_add(A,B,C) which +returns C=A+B , and sm_mlt(s,A,C) which returns C=sA . The data types of +A, B and C are all MAT *, while that of s is type double as before. The +matrix NULL is called MNULL. + + Multiplying matrices and vectors can be done by a single function call: +mv_mlt(A,x,out) returns out=A*x while vm_mlt(A,x,out) returns out=A^T*x , or +equivalently, out^T=x^T*A . Note that there is no distinction between row +and column vectors unlike certain interactive environments such as MATLAB +or MATCALC. + + Permutations are also an essential part of the package. Vectors can be +permuted by using px_vec(p,x,p_x), rows and columns of matrices can be +permuted by using px_rows(p,A,p_A), px_cols(p,A,A_p), and permutations can +be multiplied using px_mlt(p1,p2,p1_p2) and inverted using px_inv(p,p_inv). +The NULL permutation is called PXNULL. + + There are also utility routines to initialise or re-initialise these +data structures: v_zero(x), m_zero(A), m_ident(A) (which sets A=I of the +correct size), v_rand(x), m_rand(A) which sets the entries of x and A +respectively to be randomly and uniformly selected between zero and one, +and px_ident(p) which sets p to be an identity permutation. + + Input and output are accomplished by library routines v_input(x), +m_input(A), and px_input(p). If a null object is passed to any of these +input routines, all data will be obtained from the input file, which is +stdin. If input is taken from a keyboard then the user will be prompted +for all the data items needed; if input is taken from a file, then the +input will have to be of the same format as that produced by the output +routines, which are: v_output(x), m_output(A) and px_output(p). This +output is both human and machine readable! + + If you wish to send the data to a file other than the standard output +device stdout, or receive input from a file or device other than the +standard input device stdin, take the appropriate routine above, use the +``foutpout'' suffix instead of just ``output'', and add a file pointer as +the first argument. For example, to send a matrix A to a file called +``fred'', use the following: + + + #include "matrix.h" + ............. + main() + { + FILE *fp; + MAT *A; + ............. + fp = fopen("fred","w"); + m_foutput(fp,A); + ............. + } + + + These input routines allow for the presence of comments in the data. A +comment in the input starts with a ``hash'' character ``#'', and continues +to the end of the line. For example, the following is valid input for a +3-dimensional vector: + + # The initial vector must not be zero + # x = + Vector: dim: 3 + -7 0 3 + + + For general input/output which conforms to this format, allowing +comments in the input files, use the input() and finput() macros. These +are used to print out a prompt message if stdin is a terminal (or ``tty'' +in Unix jargon), and to skip over any comments if input is from a +non-interactive device. An example of the usage of these macros is: + + input("Input number of steps: ","%d",&steps); + fp = stdin; + finput(fp,"Input number of steps: ","%d",&steps); + fp = fopen("fred","r"); + finput(fp,"Input number of steps: ","%d",&steps); + +The "%d" is one of the format specifiers which are used in fscanf(); the +last argument is the pointer to the variable (unless the variable is a +string) just as for scanf() and fscanf(). The first two macro calls read +input from stdin, the last from the file fred. If, in the first two calls, +stdin is a keyboard (a ``tty'' in Unix jargon) then the prompt string + "Input number of steps: " +is printed out on the terminal. + + + The second part of the library contains routines for various +factorisation methods. To use it put + + #include "matrix2.h" + +at the beginning of your program. It contains factorisation and solution +routines for LU, Cholesky and QR-factorisation methods, as well as update +routines for Cholesky and QR factorisations. Supporting these are a number +of Householder transformation and Givens' rotation routines. Also there is +a routine for generating the Q matrix for a QR-factorisation, if it is +needed explicitly, as it often is. +There are routines for band factorisation and solution for LU and LDL^T +factorisations. + +For using complex numbers, vectors and matrices include + + #include "zmatrix.h" + +for using the basic routines, and + + #include "zmatrix2.h" + +for the complex matrix factorisation routines. The zmatrix2.h file +includes matrix.h and zmatrix.h so you don't need these files included +together. + +For using the sparse matrix routines in the library you need to put + + #include "sparse.h" + +or, if you use any sparse factorisation routines, + + #include "sparse2.h" + +at the beginning of your file. The routines contained in the library +include routines for creating, destroying, initialising and updating sparse +matrices, and also routines for sparse matrix-dense vector multiplication, +sparse LU factorisation and sparse Cholesky factorisation. + +For using the iterative routines you need to use + + #include "iter.h" + +This includes the sparse.h and matrix.h file. +There are also routines for applying iterative methods such as +pre-conditioned conjugate gradient methods to sparse matrices. + + And if you use the standard maths library (sin(), cos(), tan(), exp(), +log(), sqrt(), acos() etc.) don't forget to include the standard +mathematics header: + + #include + +This file is not automatically included by any of the Meschach +header files. + + + +2. HOW TO MANAGE MEMORY + + Unlike many other numerical libraries, Meschach allows you to allocate, +deallocate and resize the vectors, matrices and permutations that you are +using. To gain maximum benefit from this it is sometimes necessary to +think a little about where memory is allocated and deallocated. There are +two reasons for this. + + Memory allocation, deallocation and resizing takes a significant amount +of time compared with (say) vector operations, so it should not be done too +frequently. Allocating memory but not deallocating it means that it cannot +be used by any other data structure. Data structures that are no longer +needed should be explicitly deallocated, or kept as static variables for +later use. Unlike other interpreted systems (such as Lisp) there is no +implicit ``garbage collection'' of no-longer-used memory. + + There are three main strategies that are recommended for deciding how to +allocate, deallocate and resize objects. These are ``no deallocation'' +which is really only useful for demonstration programs, ``allocate and +deallocate'' which minimises overall memory requirements at the expense of +speed, and ``resize on demand'' which is useful for routines that are +called repeatedly. A new technique for static workspace arrays is to +``register workspace variables''. + + +2.1 NO DEALLOCATION + + This is the strategy of allocating but never deallocating data +structures. This is only useful for demonstration programs run with small +to medium size data structures. For example, there could be a line + + QR = m_copy(A,MNULL); /* allocate memory for QR */ + +to allocate the memory, but without the call M_FREE(QR); in it. This can +be acceptable if QR = m_copy(A,MNULL) is only executed once, and so the +allocated memory never needs to be explicitly deallocated. + + This would not be acceptable if QR = m_copy(A,MNULL) occurred inside a +for loop. If this were so, then memory would be ``lost'' as far as the +program is concerned until there was insufficient space for allocating the +next matrix for QR. The next subsection shows how to avoid this. + + +2.2 ALLOCATE AND DEALLOCATE + + This is the most straightforward way of ensuring that memory is not +lost. With the example of allocating QR it would work like this: + + for ( ... ; ... ; ... ) + { + QR = m_copy(A,MNULL); /* allocate memory for QR */ + /* could have been allocated by m_get() */ + /* use QR */ + ...... + ...... + /* no longer need QR for this cycle */ + M_FREE(QR); /* deallocate QR so memory can be reused */ + } + + The allocate and deallocate statements could also have come at the +beginning and end of a function or procedure, so that when the function +returns, all the memory that the function has allocated has been +deallocated. + + This is most suitable for functions or sections of code that are called +repeatedly but involve fairly extensive calculations (at least a +matrix-matrix multiply, or solving a system of equations). + + +2.3 RESIZE ON DEMAND + + This technique reduces the time involved in memory allocation for code +that is repeatedly called or used, especially where the same size matrix or +vector is needed. For example, the vectors v1, v2, etc. in the +Runge-Kutta routine rk4() are allocated according to this strategy: + + rk4(...,x,...) + { + static VEC *v1=VNULL, *v2=VNULL, *v3=VNULL, *v4=VNULL, *temp=VNULL; + ....... + v1 = v_resize(v1,x->dim); + v2 = v_resize(v2,x->dim); + v3 = v_resize(v3,x->dim); + v4 = v_resize(v4,x->dim); + temp = v_resize(temp,x->dim); + ....... + } + + The intention is that the rk4() routine is called repeatedly with the +same size x vector. It then doesn't make as much sense to allocate v1, v2 +etc. whenever the function is called. Instead, v_resize() only performs +memory allocation if the memory already allocated to v1, v2 etc. is smaller +than x->dim. + + The vectors v1, v2 etc. are declared to be static to ensure that their +values are not lost between function calls. Variables that are declared +static are set to NULL or zero by default. So the declaration of v1, v2, +etc., could be + + static VEC *v1, *v2, *v3, *v4, *temp; + + This strategy of resizing static workspace variables is not so useful if +the object being allocated is extremely large. The previous ``allocate and +deallocate'' strategy is much more efficient for memory in those +circumstances. However, the following section shows how to get the best of +both worlds. + + +2.4 REGISTRATION OF WORKSPACE + + From version 1.2 onwards, workspace variables can be registered so that +the memory they reference can be freed up on demand. To do this, the +function containing the static workspace variables has to include calls to +MEM_STAT_REG(var,type) where var is a pointer to a Meschach data type (such +as VEC or MAT). This call should be placed after the call to the +appropriate resize function. The type parameter should be a TYPE_... macro +where the ``...'' is the name of a Meschach type such as VEC or MAT. For +example, + + rk4(...,x,...) + { + static VEC *v1, *v2, *v3, *v4, *temp; + ....... + v1 = v_resize(v1,x->dim); + MEM_STAT_REG(v1,TYPE_VEC); + v2 = v_resize(v2,x->dim); + MEM_STAT_REG(v2,TYPE_VEC); + ...... + } + +Normally, these registered workspace variables remain allocated. However, +to implement the ``deallocate on exit'' approach, use the following code: + + ...... + mem_stat_mark(1); + rk4(...,x,...) + mem_stat_free(1); + ...... + + To keep the workspace vectors allocated for the duration of a loop, but +then deallocated, use + + ...... + mem_stat_mark(1); + for (i = 0; i < N; i++ ) + rk4(...,x,...); + mem_stat_free(1); + ...... + +The number used in the mem_stat_mark() and mem_stat_free() calls is the +workspace group number. The call mem_stat_mark(1) designates 1 as the +current workspace group number; the call mem_stat_free(1) deallocates (and +sets to NULL) all static workspace variables registered as belonging to +workspace group 1. + + + +3. SIMPLE VECTOR OPERATIONS: AN RK4 ROUTINE + + The main purpose of this example is to show how to deal with vectors and +to compute linear combinations. + + The problem here is to implement the standard 4th order Runge-Kutta +method for the ODE + + x'=f(t,x), x(t_0)=x_0 + +for x(t_i), i=1,2,3, where t_i=t_0+i*h and h is the step size. + + The formulae for the 4th order Runge-Kutta method are: + + x_i+1 = x_i+ h/6*(v_1+2*v_2+2*v_3+v_4), +where + v_1 = f(t_i,x_i) + v_2 = f(t_i+h, x_i+h*v_1) + v_3 = f(t_i+h, x_i+h*v_2) + v_4 = f(t_i+h, x_i+h*v_3) + +where the v_i are vectors. + + The procedure for implementing this method (rk4()) will be passed (a +pointer to) the function f. The implementation of f could, in this system, +create a vector to hold the return value each time it is called. However, +such a scheme is memory intensive and the calls to the memory allocation +functions could easily dominate the time performed doing numerical +computations. So, the implementation of f will also be passed an already +allocated vector to be filled in with the appropriate values. + + The procedure rk4() will also be passed the current time t, the step +size h, and the current value for x. The time after the step will be +returned by rk4(). + +The code that does this follows. + + + #include "matrix.h" + + /* rk4 - 4th order Runge-Kutta method */ + double rk4(f,t,x,h) + double t, h; + VEC *(*f)(), *x; + { + static VEC *v1=VNULL, *v2=VNULL, *v3=VNULL, *v4=VNULL; + static VEC *temp=VNULL; + + /* do not work with NULL initial vector */ + if ( x == VNULL ) + error(E_NULL,"rk4"); + + /* ensure that v1, ..., v4, temp are of the correct size */ + v1 = v_resize(v1,x->dim); + v2 = v_resize(v2,x->dim); + v3 = v_resize(v3,x->dim); + v4 = v_resize(v4,x->dim); + temp = v_resize(temp,x->dim); + + /* register workspace variables */ + MEM_STAT_REG(v1,TYPE_VEC); + MEM_STAT_REG(v2,TYPE_VEC); + MEM_STAT_REG(v3,TYPE_VEC); + MEM_STAT_REG(v4,TYPE_VEC); + MEM_STAT_REG(temp,TYPE_VEC); + /* end of memory allocation */ + + (*f)(t,x,v1); /* most compilers allow: f(t,x,v1); */ + v_mltadd(x,v1,0.5*h,temp); /* temp = x+.5*h*v1 */ + (*f)(t+0.5*h,temp,v2); + v_mltadd(x,v2,0.5*h,temp); /* temp = x+.5*h*v2 */ + (*f)(t+0.5*h,temp,v3); + v_mltadd(x,v3,h,temp); /* temp = x+h*v3 */ + (*f)(t+h,temp,v4); + + /* now add: v1+2*v2+2*v3+v4 */ + v_copy(v1,temp); /* temp = v1 */ + v_mltadd(temp,v2,2.0,temp); /* temp = v1+2*v2 */ + v_mltadd(temp,v3,2.0,temp); /* temp = v1+2*v2+2*v3 */ + v_add(temp,v4,temp); /* temp = v1+2*v2+2*v3+v4 */ + + /* adjust x */ + v_mltadd(x,temp,h/6.0,x); /* x = x+(h/6)*temp */ + + return t+h; /* return the new time */ + } + + + Note that the last parameter of f() is where the output is placed. +Often this can be NULL in which case the appropriate data structure is +allocated and initialised. Note also that this routine can be used for +problems of arbitrary size, and the dimension of the problem is determined +directly from the data given. The vectors v_1,...,v_4 are created to have +the correct size in the lines + + .... + v1 = v_resize(v1,x->dim); + v2 = v_resize(v2,x->dim); + .... + + Here v_resize(v,dim) resizes the VEC structure v to hold a vector of +length dim. If v is initially NULL, then this creates a new vector of +dimension dim, just as v_get(dim) would do. For the above piece of code to +work correctly, v1, v2 etc., must be initialised to be NULL vectors. This +is done by the declaration + + static VEC *v1=VNULL, *v2=VNULL, *v3=VNULL, *v4=VNULL; + +or + + static VEC *v1, *v2, *v3, *v4; + +The operations of vector addition and scalar addition are really the only +vector operations that need to be performed in rk4. Vector addition is +done by v_add(v1,v2,out), where out=v1+v2, and scalar multiplication by +sv_mlt(scale,v,out), where out=scale*v. + +These can be combined into a single operation v_mltadd(v1,v2,scale,out), +where out=v1+scale*v2. As many operations in numerical mathematics involve +accumulating scalar multiples, this is an extremely useful operation, as we +can see above. For example: + + v_mltadd(x,v1,0.5*h,temp); /* temp = x+0.5*h*v1 */ + + We also need a number of ``utility'' operations. For example v_copy(in, +out) copies the vector in to out. There is also v_zero(v) to zero a vector +v. + + Here is an implementation of the function f for simple harmonic motion: + + /* f - right-hand side of ODE solver */ + VEC *f(t,x,out) + VEC *x, *out; + double t; + { + if ( x == VNULL || out == VNULL ) + error(E_NULL,"f"); + if ( x->dim != 2 || out->dim != 2 ) + error(E_SIZES,"f"); + + out->ve[0] = x->ve[1]; + out->ve[1] = - x->ve[0]; + + return out; + } + + As can be seen, most of this code is error checking code, which, of +course, makes the routine safer but a little slower. For a procedure like +f() it is probably not necessary, although then the main program would have +to perform checking to ensure that the vectors involved have the correct +size etc. The ith component of a vector x is x->ve[i], and indexing is +zero-relative (i.e., the ``first'' component is component 0). The ODE +described above is for simple harmonic motion: + + x_0'=x_1 , x_1'=-x_0 , or equivalently, x_0''+ x_0 = 0 . + + Here is the main program: + + + #include + #include "matrix.h" + + main() + { + VEC *x; + VEC *f(); + double h, t, t_fin; + double rk4(); + + input("Input initial time: ", "%lf", &t); + input("Input final time: ", "%lf", &t_fin); + x = v_get(2); /* this is the size needed by f() */ + prompter("Input initial state:\n"); x = v_input(VNULL); + input("Input step size: ", "%lf", &h); + + printf("# At time %g, the state is\n",t); + v_output(x); + while ( t < t_fin ) + { + t = rk4(f,t,x,min(h,t_fin-t)); /* new t is returned */ + printf("# At time %g, the state is\n",t); + v_output(x); + t += h; + } + } + + The initial values are entered as a vector by v_input(). If v_input() +is passed a vector, then this vector will be used to store the input, and +this vector has the size that x had on entry to v_input(). The original +values of x are also used as a prompt on input from a tty. If a NULL is +passed to v_input() then v_input() will return a vector of whatever size +the user inputs. So, to ensure that only a two-dimensional vector is used +for the initial conditions (which is what f() is expecting) we use + + x = v_get(2); x = v_input(x); + + To compile the program under Unix, if it is in a file tutorial.c: + + cc -o tutorial tutorial.c meschach.a + +or, if you have an ANSI compiler, + + cc -DANSI_C -o tutorial tutorial.c meschach.a + + Here is a sample session with the above program: + + tutorial + + Input initial time: 0 + Input final time: 1 + Input initial state: + Vector: dim: 2 + entry 0: -1 + entry 1: b + entry 0: old -1 new: 1 + entry 1: old 0 new: 0 + Input step size: 0.1 + At time 0, the state is + Vector: dim: 2 + 1 0 + At time 0.1, the state is + Vector: dim: 2 + 0.995004167 -0.0998333333 + ................. + At time 1, the state is + Vector: dim: 2 + 0.540302967 -0.841470478 + + By way of comparison, the state at t=1 for the true solution is + x_0(1)=0.5403023058 , x_1(1)=-0.8414709848 . +The ``b'' that is typed in entering the x vector allows the user to alter +previously entered components. In this case once this is done, the user is +prompted with the old values when entering the new values. The user can +also type in ``f'' for skipping over the vector's components, which are +then unchanged. If an incorrectly sized initial value vector x is given, +the error handler comes into action: + + Input initial time: 0 + Input final time: 1 + Input initial state: + Vector: dim: 3 + entry 0: 3 + entry 1: 2 + entry 2: -1 + Input step size: 0.1 + At time 0, the state is + Vector: dim: 3 + 3 2 -1 + + "tutorial.c", line 79: sizes of objects don't match in function f() + Sorry, aborting program + + The error handler prints out the error message giving the source code +file and line number as well as the function name where the error was +raised. The relevant section of f() in file tutorial.c is: + + if ( x->dim != 2 || out->dim != 2 ) + error(E_SIZES,"f"); /* line 79 */ + + + The standard routines in this system perform error checking of this +type, and also checking for undefined results such as division by zero in +the routines for solving systems of linear equations. There are also error +messages for incorrectly formatted input and end-of-file conditions. + + To round off the discussion of this program, note that we have seen +interactive input of vectors. If the input file or stream is not a tty +(e.g., a file, a pipeline or a device) then it expects the input to have +the same form as the output for each of the data structures. Each of the +input routines (v_input(), m_input(), px_input()) skips over ``comments'' +in the input data, as do the macros input() and finput(). Anything from a +`#' to the end of the line (or EOF) is considered to be a comment. For +example, the initial value problem could be set up in a file ivp.dat as: + + # Initial time + 0 + # Final time + 1 + # Solution is x(t) = (cos(t),-sin(t)) + # x(0) = + Vector: dim: 2 + 1 0 + # Step size + 0.1 + + The output of the above program with the above input (from a file) gives +essentially the same output as shown above, except that no prompts are sent +to the screen. + + + +4. USING ROUTINES FOR LISTS OF ARGUMENTS + + Some of the most common routines have variants that take a variable +number of arguments. These are the routines .._get_vars(), .._resize_vars() +and .._free_vars(). These correspond to the the basic routines .._get(), +.._resize() and .._free() respectively. Also there is the +mem_stat_reg_vars() routine which registers a list of static workspace +variables. This corresponds to mem_stat_reg_list() for a single variable. + + Here is an example of how to use these functions. This example also +uses the routine v_linlist() to compute a linear combination of vectors. +Note that the code is much more compact, but don't forget that these +``..._vars()'' routines usually need the address-of operator ``&'' and NULL +termination of the arguments to work correctly. + + + #include "matrix.h" + + /* rk4 - 4th order Runge-Kutta method */ + double rk4(f,t,x,h) + double t, h; + VEC *(*f)(), *x; + { + static VEC *v1, *v2, *v3, *v4, *temp; + + /* do not work with NULL initial vector */ + if ( x == VNULL ) + error(E_NULL,"rk4"); + + /* ensure that v1, ..., v4, temp are of the correct size */ + v_resize_vars(x->dim, &v1, &v2, &v3, &v4, &temp, NULL); + + /* register workspace variables */ + mem_stat_reg_vars(0, TYPE_VEC, &v1, &v2, &v3, &v4, &temp, NULL); + /* end of memory allocation */ + + (*f)(t,x,v1); v_mltadd(x,v1,0.5*h,temp); + (*f)(t+0.5*h,temp,v2); v_mltadd(x,v2,0.5*h,temp); + (*f)(t+0.5*h,temp,v3); v_mltadd(x,v3,h,temp); + (*f)(t+h,temp,v4); + + /* now add: temp = v1+2*v2+2*v3+v4 */ + v_linlist(temp, v1, 1.0, v2, 2.0, v3, 2.0, v4, 1.0, VNULL); + /* adjust x */ + v_mltadd(x,temp,h/6.0,x); /* x = x+(h/6)*temp */ + + return t+h; /* return the new time */ + } + + + +5. A LEAST SQUARES PROBLEM + + Here we need to use matrices and matrix factorisations (in particular, a +QR factorisation) in order to find the best linear least squares solution +to some data. Thus in order to solve the (approximate) equations + A*x = b, +where A is an m x n matrix (m > n) we really need to solve the optimisation +problem + min_x ||Ax-b||^2. + + If we write A=QR where Q is an orthogonal m x m matrix and R is an upper +triangular m x n matrix then (we use 2-norm) + + ||A*x-b||^2 = ||R*x-Q^T*b||^2 = || R_1*x - Q_1^T*b||^2 + ||Q_2^T*b||^2 + +where R_1 is an n x n upper triangular matrix. If A has full rank then R_1 +will be an invertible matrix, and the best least squares solution of A*x=b +is x= R_1^{-1}*Q_1^T*b . + + These calculations can be be done quite easily as there is a QRfactor() +function available with the system. QRfactor() is declared to have the +prototype + + MAT *QRfactor(MAT *A, VEC *diag); + + The matrix A is overwritten with the factorisation of A ``in compact +form''; that is, while the upper triangular part of A is indeed the R +matrix described above, the Q matrix is stored as a collection of +Householder vectors in the strictly lower triangular part of A and in the +diag vector. The QRsolve() function knows and uses this compact form and +solves Q*R*x=b with the call QRsolve(A,diag,b,x), which also returns x. + + Here is the code to obtain the matrix A, perform the QR factorisation, +obtain the data vector b, solve for x, and determine what the norm of the +errors ( ||Ax-b||_2 ) is. + + + #include "matrix2.h" + + main() + { + MAT *A, *QR; + VEC *b, *x, *diag; + + /* read in A matrix */ + printf("Input A matrix:"); + + A = m_input(MNULL); /* A has whatever size is input */ + + if ( A->m < A->n ) + { + printf("Need m >= n to obtain least squares fit"); + exit(0); + } + printf("# A ="); m_output(A); + diag = v_get(A->m); + + /* QR is to be the QR factorisation of A */ + QR = m_copy(A,MNULL); + QRfactor(QR,diag); + + /* read in b vector */ + printf("Input b vector:"); + b = v_get(A->m); + b = v_input(b); + printf("# b ="); v_output(b); + + /* solve for x */ + x = QRsolve(QR,diag,b,VNULL); + printf("Vector of best fit parameters is"); + v_output(x); + + /* ... and work out norm of errors... */ + printf("||A*x-b|| = %g\n", + v_norm2(v_sub(mv_mlt(A,x,VNULL),b,VNULL))); + } + + Note that as well as the usual memory allocation functions like m_get(), +the I/O functions like m_input() and m_output(), and the +factorise-and-solve functions QRfactor() and QRsolve(), there are also +functions for matrix-vector multiplication: + mv_mlt(MAT *A, VEC *x, VEC *out) +and also vector-matrix multiplication (with the vector on the left): + vm_mlt(MAT *A, VEC *x, VEC *out), +with out=x^T A. There are also functions to perform matrix arithmetic - +matrix addition m_add(), matrix-scalar multiplication sm_mlt(), +matrix-matrix multiplication m_mlt(). + + Several different sorts of matrix factorisation are supported: LU +factorisation (also known as Gaussian elimination) with partial pivoting, +by LUfactor() and LUsolve(). Other factorisation methods include Cholesky +factorisation CHfactor() and CHsolve(), and QR factorisation with column +pivoting QRCPfactor(). + + Pivoting involve permutations which have their own PERM data structure. +Permutations can be created by px_get(), read and written by px_input() and +px_output(), multiplied by px_mlt(), inverted by px_inv() and applied to +vectors by px_vec(). + +The above program can be put into a file leastsq.c and compiled under Unix +using + + cc -o leastsq leastsq.c meschach.a -lm + +A sample session using leastsq follows: + + + Input A matrix: + Matrix: rows cols:5 3 + row 0: + entry (0,0): 3 + entry (0,1): -1 + entry (0,2): 2 + Continue: + row 1: + entry (1,0): 2 + entry (1,1): -1 + entry (1,2): 1 + Continue: n + row 1: + entry (1,0): old 2 new: 2 + entry (1,1): old -1 new: -1 + entry (1,2): old 1 new: 1.2 + Continue: + row 2: + entry (2,0): old 0 new: 2.5 + .... + .... (Data entry) + .... + # A = + Matrix: 5 by 3 + row 0: 3 -1 2 + row 1: 2 -1 1.2 + row 2: 2.5 1 -1.5 + row 3: 3 1 1 + row 4: -1 1 -2.2 + Input b vector: + entry 0: old 0 new: 5 + entry 1: old 0 new: 3 + entry 2: old 0 new: 2 + entry 3: old 0 new: 4 + entry 4: old 0 new: 6 + # b = + Vector: dim: 5 + 5 3 2 4 6 + Vector of best fit parameters is + Vector: dim: 3 + 1.47241555 -0.402817858 -1.14411815 + ||A*x-b|| = 6.78938 + + + The Q matrix can be obtained explicitly by the routine makeQ(). The Q +matrix can then be used to obtain an orthogonal basis for the range of A . +An orthogonal basis for the null space of A can be obtained by finding the +QR-factorisation of A^T . + + + +6. A SPARSE MATRIX EXAMPLE + + To illustrate the sparse matrix routines, consider the problem of +solving Poisson's equation on a square using finite differences, and +incomplete Cholesky factorisation. The actual equations to solve are + + u_{i,j+1} + u_{i,j-1} + u_{i+1,j} + u_{i-1,j} - 4*u_{i,j} = + h^2*f(x_i,y_j), for i,j=1,...,N + +where u_{0,j} = u_{i,0} = u_{N+1,j} = u_{i,N+1} = 0 for i,j=1,...,N and h +is the common distance between grid points. + + The first task is to set up the matrix describing this system of linear +equations. The next is to set up the right-hand side. The third is to +form the incomplete Cholesky factorisation of this matrix, and finally to +use the sparse matrix conjugate gradient routine with the incomplete +Cholesky factorisation as preconditioner. + + Setting up the matrix and right-hand side can be done by the following +code: + + + #define N 100 + #define index(i,j) (N*((i)-1)+(j)-1) + ...... + A = sp_get(N*N,N*N,5); + b = v_get(N*N); + h = 1.0/(N+1); /* for a unit square */ + ...... + + for ( i = 1; i <= N; i++ ) + for ( j = 1; j <= N; j++ ) + { + if ( i < N ) + sp_set_val(A,index(i,j),index(i+1,j),-1.0); + if ( i > 1 ) + sp_set_val(A,index(i,j),index(i-1,j),-1.0); + if ( j < N ) + sp_set_val(A,index(i,j),index(i,j+1),-1.0); + if ( j > 1 ) + sp_set_val(A,index(i,j),index(i,j-1),-1.0); + sp_set_val(A,index(i,j),index(i,j),4.0); + b->ve[index(i,j)] = -h*h*f(h*i,h*j); + } + + Once the matrix and right-hand side are set up, the next task is to +compute the sparse incomplete Cholesky factorisation of A. This must be +done in a different matrix, so A must be copied. + + LLT = sp_copy(A); + spICHfactor(LLT); + +Now when that is done, the remainder is easy: + + out = v_get(A->m); + ...... + iter_spcg(A,LLT,b,1e-6,out,1000,&num_steps); + printf("Number of iterations = %d\n",num_steps); + ...... + +and the output can be used in whatever way desired. + + For graphical output of the results, the solution vector can be copied +into a square matrix, which is then saved in MATLAB format using m_save(), +and graphical output can be produced by MATLAB. + + + +7. HOW DO I ....? + + For the convenience of the user, here a number of common tasks that +people need to perform frequently, and how to perform the computations +using Meschach. + + +7.1 .... SOLVE A SYSTEM OF LINEAR EQUATIONS ? + + If you wish to solve Ax=b for x given A and b (without destroying A), +then the following code will do this: + + VEC *x, *b; + MAT *A, *LU; + PERM *pivot; + ...... + LU = m_get(A->m,A->n); + LU = m_copy(A,LU); + pivot = px_get(A->m); + LUfactor(LU,pivot); + /* set values of b here */ + x = LUsolve(LU,pivot,b,VNULL); + + +7.2 .... SOLVE A LEAST-SQUARES PROBLEM ? + + To minimise ||Ax-b||_2^2 = sum_i ((Ax)_i-b_i)^2, the most reliable +method is based on the QR-factorisation. The following code performs this +calculation assuming that A is m x n with m > n : + + MAT *A, *QR; + VEC *diag, *b, *x; + ...... + QR = m_get(A->m,A->n); + QR = m_copy(A,QR); + diag = v_get(A->n); + QRfactor(QR,diag); + /* set values of b here */ + x = QRsolve(QR,diag,b,x); + + +7.3 .... FIND ALL THE EIGENVALUES (AND EIGENVECTORS) OF A GENERAL MATRIX ? + + The best method is based on the Schur decomposition. For symmetric +matrices, the eigenvalues and eigenvectors can be computed by a single call +to symmeig(). For non-symmetric matrices, the situation is more complex +and the problem of finding eigenvalues and eigenvectors can become quite +ill-conditioned. Provided the problem is not too ill-conditioned, the +following code should give accurate results: + + + /* A is the matrix whose eigenvalues and eigenvectors are sought */ + MAT *A, *T, *Q, *X_re, *X_im; + VEC *evals_re, *evals_im; + ...... + Q = m_get(A->m,A->n); + T = m_copy(A,MNULL); + + /* compute Schur form: A = Q*T*Q^T */ + schur(T,Q); + + /* extract eigenvalues */ + evals_re = v_get(A->m); + evals_im = v_get(A->m); + schur_evals(T,evals_re,evals_im); + + /* Q not needed for eiegenvalues */ + X_re = m_get(A->m,A->n); + X_im = m_get(A->m,A->n); + schur_vecs(T,Q,X_re,X_im); + /* k'th eigenvector is k'th column of (X_re + i*X_im) */ + + + +7.4 .... SOLVE A LARGE, SPARSE, POSITIVE DEFINITE SYSTEM OF EQUATIONS ? + + An example of a large, sparse, positive definite matrix is the matrix +obtained from a finite-difference approximation of the Laplacian operator. +If an explicit representation of such a matrix is available, then the +following code is suggested as a reasonable way of computing solutions: + + + /* A*x == b is the system to be solved */ + SPMAT *A, *LLT; + VEC *x, *b; + int num_steps; + ...... + /* set up A and b */ + ...... + x = m_get(A->m); + LLT = sp_copy(A); + + /* preconditioning using the incomplete Cholesky factorisation */ + spICHfactor(LLT); + + /* now use pre-conditioned conjugate gradients */ + x = iter_spcg(A,LLT,b,1e-7,x,1000,&num_steps); + /* solution computed to give a relative residual of 10^-7 */ + + + If explicitly storing such a matrix takes up too much memory, then if +you can write a routine to perform the calculation of A*x for any given x , +the following code may be more suitable (if slower): + + + VEC *mult_routine(user_def,x,out) + void *user_def; + VEC *x, *out; + { + /* compute out = A*x */ + ...... + return out; + } + + + main() + { + ITER *ip; + VEC *x, *b; + ...... + b = v_get(BIG_DIM); /* right-hand side */ + x = v_get(BIG_DIM); /* solution */ + + /* set up b */ + ...... + ip = iter_get(b->dim, x->dim); + ip->b = v_copy(b,ip->b); + ip->info = NULL; /* if you don't want information + about solution process */ + v_zero(ip->x); /* initial guess is zero */ + iter_Ax(ip,mult_routine,user_def); + iter_cg(ip); + printf("# Solution is:\n"); v_output(ip->x); + ...... + ITER_FREE(ip); /* destroy ip */ + } + + The user_def argument is for a pointer to a user-defined structure +(possibly NULL, if you don't need this) so that you can write a common +function for handling a large number of different circumstances. + + + +8. MORE ADVANCED TOPICS + + Read this if you are interested in using Meschach library as a base for +applications. As an example we show how to implement a new type for 3 +dimensional matrices and incorporate this new type into the Meschach +system. Usually this part of Meschach is transparent to a user. But a more +advanced user can take advantage of these routines. We do not describe +the routines in detail here, but we want to give a rather broad picture of +what can be done. By the system we mainly mean the system of delivering +information on the number of bytes of allocated memory and routines for +deallocating static variables by mem_stat_... routines. + + First we introduce a concept of a list of types. By a list of types we +mean a set of different types with corresponding routines for creating +these types, destroying and resizing them. Each type list has a number. +The list 0 is a list of standard Meschach types such as MAT or VEC. Other +lists can be defined by a user or a application (based on Meschach). The +user can attach his/her own list to the system by the routine +mem_attach_list(). Sometimes it is worth checking if a list number is +already used by another application. It can be done by +mem_is_list_attached(ls_num), which returns TRUE if the number ls_num +is used. And such a list can be removed from the system by +mem_free_list(ls_num) if necessary. + + We describe arguments required by mem_attach_list(). The prototype of +this function is as follow + + int mem_attach_list(int ls_num, int ntypes, char *type_names[], + int (*free_funcs[])(), MEM_ARRAY sum[]); + +where the structure MEM_ARRAY has two members: "bytes" of type long and +"numvar" of type int. The frst argument is the list number. Note that you +cannot overwrite another list. To do this remove first the old list (by +mem_free_list()) or choose another number. The next argument is the number +of types which are on the list. This number cannot be changed during +running a program. The third argument is an array containing the names of +types (these are character strings). The fourth one is an array of +functions deallocating variables of the corresponding type. And the last +argument is the local array where information about the number of bytes of +allocated/deallocated memory (member bytes) and the number of allocated +variables (member numvar) are gathered. The functions which send +information to this array are mem_bytes_list() and mem_numvar_list(). + + +Example: The routines described here are in the file tutadv.c. +Firstly we define some macros and a type for 3 dimensional matrices. + +#include "matrix.h" +#define M3D_LIST 3 /* list number */ +#define TYPE_MAT3D 0 /* the number of a type */ +/* type for 3 dimensional matrices */ +typedef struct { + int l,m,n; /* actual dimensions */ + int max_l, max_m, max_n; /* maximal dimensions */ + Real ***me; /* pointer to matrix elements */ + /* we do not consider segmented memory */ + Real *base, **me2d; /* me and me2d are additional pointers + to base */ +} MAT3D; + + +Now we need two routines: one for allocating memory for 3 dimensional +matrices and the other for deallocating it. It can be useful to have a +routine for resizing 3 dimensional matrices but we do not use it here. +Note the use of mem_bytes_list() and mem_numvar_list() to notify the change +in the number of structures and bytes in use. + +/* function for creating a variable of MAT3D type */ + +MAT3D *m3d_get(l,m,n) +int l,m,n; +{ + MAT3D *mat; + .... + /* alocate memory for structure */ + if ((mat = NEW(MAT3D)) == (MAT3D *)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) { + /* record how many bytes are allocated to structure */ + mem_bytes_list(TYPE_MAT3D,0,sizeof(MAT3D),M3D_LIST); + /* record a new allocated variable */ + mem_numvar_list(TYPE_MAT3D,1,M3D_LIST); + } + .... + /* allocate memory for 3D array */ + if ((mat->base = NEW_A(l*m*n,Real)) == (Real *)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_MAT3D,0,l*m*n*sizeof(Real),M3D_LIST); + .... + return mat; +} + +/* deallocate a variable of type MAT3D */ + +int m3d_free(mat) +MAT3D *mat; +{ + /* do not try to deallocate the NULL pointer */ + if (mat == (MAT3D *)NULL) + return -1; + .... + /* first deallocate base */ + if (mat->base != (Real *)NULL) { + if (mem_info_is_on()) + /* record how many bytes is deallocated */ + mem_bytes_list(TYPE_MAT3D,mat->max_l*mat->max_m*mat->max_n*sizeof(Real), + 0,M3D_LIST); + free((char *)mat->base); + } + .... + /* deallocate MAT3D structure */ + if (mem_info_is_on()) { + mem_bytes_list(TYPE_MAT3D,sizeof(MAT3D),0,M3D_LIST); + mem_numvar_list(TYPE_MAT3D,-1,M3D_LIST); + } + free((char *)mat); + + .... + free((char *)mat); + + return 0; +} + + +We can now create the arrays necessary for mem_attach_list(). Note that +m3d_sum can be static if it is in the same file as main(), where +mem_attach_list is called. Otherwise it must be global. + + +char *m3d_names[] = { + "MAT3D" +}; + +#define M3D_NUM (sizeof(m3d_names)/sizeof(*m3d_names)) + +int (*m3d_free_funcs[M3D_NUM])() = { + m3d_free +} + +static MEM_ARRAY m3d_sum[M3D_NUM]; + + +The last thing is to attach the list to the system. + +void main() +{ + MAT3D *M; + .... + + mem_info_on(TRUE); /* switch memory info on */ + /* attach the new list */ + mem_attach_list(M3D_LIST,M3D_NUM,m3d_names,m3d_free_funcs,m3d_sum); + .... + M = m3d_get(3,4,5); + .... + /* making use of M->me[i][j][k], where i,j,k are non-negative and + i < 3, j < 4, k < 5 */ + .... + mem_info_file(stdout,M3D_LIST); /* info on the number of allocated + bytes of memory for types + on the list M3D_LIST */ + .... + m3d_free(M); /* if M is not necessary */ + .... +} + + +We can now use the function mem_info_file() for getting information about +the number of bytes of allocated memory and number of allocated variables +of type MAT3D; mem_stat_reg_list() for registering variables of this type +and mem_stat_mark() and mem_stat_free_list() for deallocating static +variables of this type. + + + +In the similar way you can create you own list of errors and attach it to +the system. See the functions: + + int err_list_attach(int list_num, int list_len, char **err_ptr, + int warn); /* for attaching a list of errors */ + + int err_is_list_attached(int list_num); /* checking if a list + is attached */ + + extern int err_list_free(int list_num); /* freeing a list of errors */ + +where list_num is the number of the error list, list_len is the number of +errors on the list, err_ptr is the character string explaining the error +and warn can be TRUE if this is only a warning (the program continues to +run) or it can be FALSE if it is an error (the program stops). + +The examples are the standard errors (error list 0) and warnings +(error list 1) which are in the file err.c + + + David Stewart and Zbigniew Leyk, 1993 diff --git a/FILELIST b/FILELIST new file mode 100644 index 0000000..fb3baa5 --- /dev/null +++ b/FILELIST @@ -0,0 +1,187 @@ +-rw-r--r-- 1 5066 Nov 21 2002 arnoldi.c +-rw-r--r-- 1 18361 Dec 6 2002 bdfactor.c +-rw-r--r-- 1 8682 Dec 2 2002 bkpfacto.c +-rw-r--r-- 1 5524 Dec 2 2002 chfactor.c +-rwxr-xr-x 1 60386 Nov 25 2002 configure +-rw-r--r-- 1 3711 Nov 26 2002 configure.in +-rw-r--r-- 1 8278 May 10 1995 conjgrad.c +-rw-r--r-- 1 6338 Dec 2 2002 copy.c +-rw-r--r-- 1 1124 Jan 12 1994 copyright +-rw-r--r-- 1 1402 Jan 12 1994 dmacheps.c +-rw-r--r-- 1 10319 Dec 2 2002 err.c +-rw-r--r-- 2 5718 Oct 6 2003 err.h +-rw-r--r-- 1 10931 Jun 8 1995 extras.c +-rw-r--r-- 1 4082 Dec 2 2002 fft.c +-rw-r--r-- 1 0 Sep 21 09:15 FILELIST +-rw-r--r-- 1 1400 Jan 12 1994 fmacheps.c +-rw-r--r-- 1 4167 Dec 2 2002 givens.c +-rw-r--r-- 1 4494 Dec 2 2002 hessen.c +-rw-r--r-- 1 6489 Dec 2 2002 hsehldr.c +-rw-r--r-- 1 6499 Nov 27 2002 init.c +-rw-r--r-- 1 3396 Jan 13 1994 iotort.c +-rw-r--r-- 1 9894 Oct 7 2003 iter0.c +-rw-r--r-- 1 7143 Dec 10 2002 iter.h +-rw-r--r-- 1 33308 Dec 10 2002 iternsym.c +-rw-r--r-- 1 15322 Dec 10 2002 itersym.c +-rw-r--r-- 1 16178 Dec 12 1994 itertort.c +-rw-r--r-- 1 7537 Nov 27 2002 ivecop.c +-rw-r--r-- 1 7849 Nov 21 2002 lanczos.c +-rw-r--r-- 1 397 Jan 12 1994 ls.dat +-rw-r--r-- 1 7434 Dec 2 2002 lufactor.c +-rw-r--r-- 1 4184 Nov 27 2002 machine.c +-rw-r--r-- 1 3820 Oct 6 2003 machine.h +-rw-r--r-- 1 4485 Nov 25 2002 machine.h.in +-rw-r--r-- 1 5640 Nov 4 2003 makefile +-rw-r--r-- 1 5898 Jun 22 1994 makefile.in +-rw-r--r-- 1 5563 Dec 2 2002 matlab.c +-rw-r--r-- 2 3030 Oct 6 2003 matlab.h +-rw-r--r-- 1 13336 Nov 27 2002 matop.c +-rw-r--r-- 1 8919 Oct 7 2003 matrix2.h +-rw-r--r-- 1 21822 Oct 28 2003 matrix.h +-rw-r--r-- 1 19519 Oct 7 2003 matrixio.c +-rw-r--r-- 1 1257 Jan 12 1994 maxint.c +-rw-r--r-- 1 10285 Dec 2 2002 meminfo.c +-rw-r--r-- 2 4433 Nov 27 2002 meminfo.h +-rw-r--r-- 1 20695 Nov 27 2002 memory.c +-rw-r--r-- 1 9822 Oct 7 2003 memstat.c +-rw-r--r-- 1 17441 Oct 29 2003 memtort.c +-rw-r--r-- 1 9887 Dec 3 2002 mfunc.c +-rw-r--r-- 1 4533 Jan 13 1994 mfuntort.c +-rw-r--r-- 1 4698 Dec 3 2002 norm.c +-rw-r--r-- 2 3853 Jan 12 1994 oldnames.h +-rw-r--r-- 1 4520 Nov 27 2002 otherio.c +-rw-r--r-- 1 8200 Dec 2 2002 pxop.c +-rw-r--r-- 1 14475 Dec 2 2002 qrfactor.c +-rw-r--r-- 1 18006 Apr 5 1994 README +-rw-r--r-- 1 141 Jan 12 1994 rk4.dat +-rw-r--r-- 1 18931 Dec 6 2002 schur.c +-rw-r--r-- 1 7288 Dec 2 2002 solve.c +-rw-r--r-- 1 3263 Oct 7 2003 sparse2.h +-rw-r--r-- 1 26329 Dec 3 2002 sparse.c +-rw-r--r-- 1 6730 Oct 7 2003 sparse.h +-rw-r--r-- 1 9214 Nov 2 2003 sparseio.c +-rw-r--r-- 1 36832 Oct 7 2003 spbkp.c +-rw-r--r-- 1 16329 Dec 3 2002 spchfctr.c +-rw-r--r-- 1 11245 Oct 7 2003 splufctr.c +-rw-r--r-- 1 18991 Oct 7 2003 sprow.c +-rw-r--r-- 1 7929 Dec 9 2002 spswap.c +-rw-r--r-- 1 11295 Jun 9 1995 sptort.c +-rw-r--r-- 1 5259 Dec 2 2002 submat.c +-rw-r--r-- 1 10508 Dec 2 2002 svd.c +-rw-r--r-- 1 6229 Dec 2 2002 symmeig.c +-rw-r--r-- 1 28117 Nov 26 2002 torture.c +-rw-r--r-- 1 4508 May 19 1994 tutadv.c +-rw-r--r-- 1 7794 Nov 27 2002 tutorial.c +-rw-r--r-- 1 3599 Dec 2 2002 update.c +-rw-r--r-- 1 15005 Dec 2 2002 vecop.c +-rw-r--r-- 1 2599 Aug 20 1996 version.c +-rw-r--r-- 1 5842 Oct 7 2003 zcopy.c +-rw-r--r-- 1 4556 Nov 15 2002 zfunc.c +-rw-r--r-- 1 4907 Nov 15 2002 zgivens.c +-rw-r--r-- 1 4159 Nov 26 2002 zhessen.c +-rw-r--r-- 1 6651 Nov 27 2002 zhsehldr.c +-rw-r--r-- 1 7259 Nov 26 2002 zlufctr.c +-rw-r--r-- 1 4909 Oct 7 2003 zmachine.c +-rw-r--r-- 1 11566 Dec 10 2002 zmatio.c +-rw-r--r-- 1 6155 Jun 7 1995 zmatlab.c +-rw-r--r-- 1 15369 May 10 1995 zmatop.c +-rw-r--r-- 2 4273 Nov 26 2002 zmatrix2.h +-rw-r--r-- 1 10779 Oct 7 2003 zmatrix.h +-rw-r--r-- 1 15742 Dec 11 2002 zmemory.c +-rw-r--r-- 1 4624 Nov 15 2002 znorm.c +-rw-r--r-- 1 14186 Nov 26 2002 zqrfctr.c +-rw-r--r-- 1 11267 Nov 21 2002 zschur.c +-rw-r--r-- 1 7608 Nov 15 2002 zsolve.c +-rw-r--r-- 1 20120 Nov 27 2002 ztorture.c +-rw-r--r-- 1 12512 Oct 7 2003 zvecop.c + +DOC: +total 72 +-rw------- 1 17186 Jan 13 1994 fnindex.txt +-rw------- 1 45980 Jan 13 1994 tutorial.txt + +MACHINES: +total 40 +-rw------- 1 7979 Dec 4 1998 cornelison +drwx------ 2 8192 Jan 3 1998 Cray +drwx------ 2 96 Jan 3 1998 GCC +drwx------ 2 96 Jan 3 1998 Linux +drwx------ 2 96 Mar 1 2001 MicroSoft +drwx------ 2 96 Jan 3 1998 OS2 +drwx------ 2 96 Jan 3 1998 RS6000 +drwx------ 2 96 Jan 3 1998 SGI +drwx------ 2 96 Jan 3 1998 SPARC +drwx------ 2 8192 Jan 3 1998 ThinkC +drwx------ 2 8192 Jan 3 1998 TurboC +drwx------ 2 96 Jan 3 1998 WatcomPC +-rw------- 1 7287 Aug 28 1995 w-mckinnon + +MACHINES/Cray: +total 64 +-rw------- 1 4645 Oct 27 1994 machine.h +-rw------- 1 6053 Oct 27 1994 makefile +-rw------- 1 7565 Sep 11 1997 mesch-cray.tar.Z +-rw------- 1 10459 Sep 11 1997 mesch-cray.tar.Z.uu +-rw------- 1 1951 Oct 27 1994 patch.1 +-rw------- 1 687 Oct 27 1994 patch.2 +-rw------- 1 298 Oct 27 1994 patch.3 + +MACHINES/GCC: +total 16 +-rw------- 1 3775 Jan 13 1994 machine.h +-rw------- 1 5192 Mar 27 1995 makefile + +MACHINES/Linux: +total 16 +-rw------- 1 3820 Mar 2 1994 machine.h +-rw------- 1 5604 Mar 27 1995 makefile + +MACHINES/MicroSoft: +total 24 +-rw------- 1 4812 Feb 28 2001 machine.h +-rw------- 1 6930 Feb 28 2001 makefile +-rw------- 1 4007 Mar 1 2001 stewart.zip + +MACHINES/OS2: +total 24 +-rw------- 1 3775 Oct 4 1995 machine.h +-rw------- 1 5556 Oct 4 1995 makefile +-rw------- 1 924 Oct 4 1995 README + +MACHINES/RS6000: +total 24 +-rw------- 1 6129 Jan 24 1994 machine.c +-rw------- 1 3502 Jan 13 1994 machine.h +-rw------- 1 5663 Mar 27 1995 makefile + +MACHINES/SGI: +total 16 +-rw------- 1 4635 Oct 27 1994 machine.h +-rw------- 1 5938 Oct 27 1994 makefile + +MACHINES/SPARC: +total 16 +-rw------- 1 3524 Jan 13 1994 machine.h +-rw------- 1 5195 Mar 27 1995 makefile + +MACHINES/ThinkC: +total 64 +-rw------- 1 9551 Jun 8 1995 machine.h +-rw------- 1 3777 Sep 8 1995 README +-rw------- 1 10293 Jun 13 1995 TC-machine-2.h +-rw------- 1 10226 Jun 9 1995 TC-machine.h +-rw------- 1 7145 Jun 9 1995 TC-README + +MACHINES/TurboC: +total 400 +-rw------- 1 44 Sep 11 1997 filelist +-rw------- 1 5305 Aug 21 1996 machine.h +-rw------- 1 122628 Jan 19 1996 mail +-rw------- 1 8142 Oct 14 1995 meschach.mak +-rw------- 1 104575 Sep 11 1997 meschtc.zip +-rw------- 1 144112 Sep 11 1997 meschtc.zip.uu +-rw------- 1 749 Oct 14 1995 README + +MACHINES/WatcomPC: +total 8 +-rw------- 1 4788 May 7 1996 machine.h diff --git a/MACHINES/Cray/machine.h b/MACHINES/Cray/machine.h new file mode 100644 index 0000000..7fcec8b --- /dev/null +++ b/MACHINES/Cray/machine.h @@ -0,0 +1,224 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#include +#define const + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +#define HAVE_MEMORY_H 1 +#define HAVE_COMPLEX_H 1 +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/* #undef U_INT_DEF */ +#define VARARGS 1 +#define HAVE_PROTOTYPES 1 +/* #undef HAVE_PROTOTYPES_IN_STRUCT */ + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +#define REAL_FLT 1 +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 7.10543e-15 +#define D_MACHEPS 7.10543e-15 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 9223372036854775807 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +/* #undef HUGE */ +#define HUGE HUGE_VAL +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/Cray/makefile b/MACHINES/Cray/makefile new file mode 100644 index 0000000..fa1f72c --- /dev/null +++ b/MACHINES/Cray/makefile @@ -0,0 +1,218 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: makefile.in,v 1.4 1994/03/14 01:24:06 des Exp $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = : + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12b +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +# the dependencies **between** the parts are for dmake +all: part1 part2 part3 zpart1 zpart2 ar_create +part2: part1 +part3: part2 +basic: part1 part2 +sparse: part1 part2 part3 +zpart2: zpart1 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1) + $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2) + $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3) + $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1) + $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2) + $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST) + $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +realclean: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + /bin/rm -f torture sptort ztorture memtort itertort mfuntort iotort + /bin/rm -f makefile machine.h config.status maxint macheps + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) +ar_create: + rm meschach.a + ar ruv meschach.a $(LIST1) $(LIST2) $(LIST3) \ + $(ZLIST1) $(ZLIST2) $(OLDLIST) diff --git a/MACHINES/Cray/mesch-cray.tar.Z b/MACHINES/Cray/mesch-cray.tar.Z new file mode 100644 index 0000000000000000000000000000000000000000..1e405869415c979754a55bf1a67100770c818e64 GIT binary patch literal 7604 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 Wiqw%xQcJ2yJ*g-)rK;4GYK{P*LvcL- literal 0 HcmV?d00001 diff --git a/MACHINES/Cray/mesch-cray.tar.Z.uu b/MACHINES/Cray/mesch-cray.tar.Z.uu new file mode 100644 index 0000000..9faf6ce --- /dev/null +++ b/MACHINES/Cray/mesch-cray.tar.Z.uu @@ -0,0 +1,172 @@ +begin 600 mesch-cray.tar.Z +M'YV0;<*,09/&31D7: H7,BPH<.'$"-*G$BQ(HP8,R @@(PP9-F+,,6C N&&C8\6?0(,*'?JPSAPZ8>20/%KF +M3E(Z1!V:$5B'#9T\41NFE-'28PP;([.*'4NVK%FS+U2 "#BPX$$T+D" .%+& +MH)PP=,J0 1&F#ITW >FD&1. L\(,0@'O/&C9DT9^K(.2A7Q0L%:4$$<8.8 +M+4&#(.; *3,FS>,QH>G4,6,&Q)DW9>: 0%-F,@C+F-4&(;.73!FD:=C(-C@F +M]IRDB,V\D0,BSQO)(-[<<0.BX-'";/"F:3R[=ID0MR_G!B%ER)3J9'2 ()$D +M_5J!G]^Z*,C"#H@8+F3%00)%L:LBG'G%%E@'!'&G2@ 8((C#D&F61EB !""RU4UYIS=?!EFQMOT &" +M406= 4*)CT4VF0()A%C7C7-TZ)E;+M@1!G4:@B#DB$JZ$5QV*MI1VQS;4?=& +M:T<:A)"$XSE18X>BD99&8>^-(<<;48;=>6U%Z1M+-<9?&Z!<- 9<34Q10M$/#$% +MH((FT$003##QQ!!$%#$$$W7Z-D9VD^UEVGN&O3$&"BEH2@=J:(1A9:"EBE'& +MD++2JE>ON"DP0D&SUN$;"#P<108;:8B!D _.^O88:"4>!<*$F8U0AQO>@G!J +MJJNV^JJ$(WB;J1-/4/$%H88BJBBC,71;QK<=(A&$%45\<6@33TB1Q1=(W.R +MO*"!_(400SP!118@#2&P%# D,0410C !P]$07Y$P +M$5/=)ILF>&LV&[XW%7W_/>[)=D]L.^*ZFUP7 +M&:8Y*WNZM>L-O.).,.XXY*S_[+ORN"=N=O,I/Q^Y\.@6/\+PMV96^NFIHVZ4 +MY&J5@4<8;:#>H5%AG%&&>@33J<+O*-CQA?QTL(!"Y@M*0QM2D((=B,X,R"L< +M]7(WA>@E ']N8%\96)"4,\PA!0F((*1D9$%GE4$X98@>"" H00K*P8(8U& 9 +M>.7![K4F,\D[7/5TAYMG(7!P,;P= Z_GO,=183R_^P*OJB,;S1F+2'JICAN8 +M$H:];&F$RAMB05(CASJ,@0XGD,V2]G*5T7@KBVQ#6AD>J#PAJM"$*,R@!#DX +M!P^"4(1!1,$9*WA!-4**A=]S(0A@J$ 9[G!QV?,A^CRWG,2$ 4NH*22MY,<< +M*\D!2XV130W;EC.+80P+5,O4%* -T(Y;#Q-8L,;W@"AM0B5J4 X^I+V7F +MD7AF()=:;O6D/3&E#;,Y)*Y$.88OU7!T.+R;R%;%, >.DU6N8D("8N>&:/DF +M 3P(2*ZZB09N/;-XXUG28@ #A^#4)C1H> X;]A(L*SG)0MUIXC]QDYE;T:A_ +M.PJ6&^17'1M]LYV6FY9<-BJ7:M&!>&_8UH3&,P3:C&$-A&2.Z_*TEC*TH5(& +MW6)+VU DBU[&ANE*V10YY"BVK3VM&42)E]6"#[/CN55!.R2&HAXU,4I=$U_0!0(:\<4JM8F@8*PD +MFSS\!@1KH-%T6(#$@[HTM.&<&,YTE@7&UO)@5RUO9FBT1,V28:@[(F5RG"H8 +M[DQ2C%2U:LZPJE:N>E6Q"2BN? $[D*3<)@59W2I;"\P<%2#XK/[+'((5"ZC+ +M4A:?. UOT.CZ!/.F"[T<'@][@_I>SB9UJ4UM9WVIN1'M"8+VC5[Z* +M(;EO('"P&HS@NWJ'K1)NZU[?6N'?7ABS#6U--?-PS6S*AC'M QT>O'E3<-+N +M;I6\6,;*R5IWGA;*[IMR/8\L31 DH35P6--?NABZI'1(6&$(3AC$ #H0(%6R +MS:U1IUG6'C*"J($1.4#,3(PA"586H%0$$@I*!"%7EA".D[0GMQAB\ +M9V#9MDG!94SX KFW-QY:INO?J$I;U ;IT!I]1D<86I 8_7QL-G6HVM?V-H:R +M-,R# USA3&!U:Q >\(&+D.0@YYB1;9T9+$VTSAH'MZD]GG"3BULN4O L&SR' +M:Q&"@ G3SCF:=OL&O)P\GU)OD22_W#UFN%HS#?#+?YOC,!X=R +MJ(7\YD+?N=5#>'.@3S3LB+8VZ(Z.JG7CV]U-?SK2V0UW6X^G2QTJ QRP)$HM +M;4A*-EK3V+;4FMJLJ<&7R4R%(AYQQL@!ZS;B3J7$E80B6)X\.K +MZ4P7MZEDWS+3)V#@I#=][IWNQEM!G?4_=_H1Z(XQ$9YJ]J;_^>V5K_N5&UF$ +M1C 8\6D/@ANX ",UH,$,RM""&-1 A$00/_;/8W[TJY_][K?L\09W_>(WT(:J +MUW;01WVP)WS]1WNV)W_^UWR])X"_)W5R87WCEWWA=X"FQX !""O01V_3]W;5 +M=W,6>![Q%X)D1G4@8'#\IX#DITLJT((N^((P"(.,E2[;=WK,9X 36'LUN'Q. +M4()6IBXJ>($V=%XY*('S9RI!^'_>YT(*$(-.Z(3B88#BIS%G$SDY( ,%(A,R +M " V@ /I=P,S@0,[,8/_@H2G0H6)(G+J$@0:$S=.0 2QUX9OPBB -78(9E5G +M>#U4 %<69H)-PEXML%*>YU)1I89(4 5<\P5O\W5M!QT(NXF(NZN(N\V(N^^(O &(P.$1!KX#&@(XS(&!$7D1$; 0,H 1(B@1(9 +MP172B!,S8 ,LT1$O$1,S(1(@01(Y 0/9Z(S)6(X4811(H109P11.(0=00193 +M,095<15EL15=@1-@88[ZN(^W. )S41>U@1=)U!=_$1B#@1W)L57O48R2-A_4 +MH1CQ92(^ZTAC1- (6.03R95MG +M@ 8V@@)#T"M$("QIL!=3D!?M:"-(I05B !E2TA0_5P9Y@%(QP!_\AI+^R![N +M08S&>!#T81_X00/[T1__$2 Y 0(7H0,R0 ,'8@,2UR /LAX5J0!S( =C0#S, +MT7HNH !6P$E4T#!J.2%#0">M-P9C,"%J/N2(=-B$NT$UO$)D)0 (P&9,K@AJ@ +M.9E,4)FCLAXHD)>]0@(\,"%3T#*QU'HOT)-N\ )S@ 8*<"A9PTE+<)F0,@<# +M$0,R( 8*0 5PVA0?; +MH9_!) =YH)]64E0 BA>DI)]P@ <)RE1< "1S8&V!H9\% 2+ZZ7"U\9],A7<' +M2@?9H2U,E08%VJ @>259HI\/VE@8B6A=S +MH)]U ?OE1?Z22-RT 9.:AQUD:1Y\%)E !E).A"2D:1V0 ;ZR1HQZJ! T@9F +MX%0[2@9(^@8S&IXS<)FBD11%DJ27=@>$*JAI"J2A 0=">D53JCJKX:@H"J%P +MP*-P0*ASX!27&J*H" ,4BHI[(J:<&EVA*J-:()_TV7IZP*%,I0?VV:H&J:BK +MZE*6HI]Z,**;FE2!0:)Z *:B2J5 DE1WVD[Z29TTBITW*JFMJJ1,>A"PBA,%!I;"@?+(2D6>2O$QB'>A4U-Y$0#!0=/X21,A1W+M1>!^D@A +M] 1,0 3R69^-H09GU'KY*2*4PJ(A);28XB5& +MRY]I(&83@@01VWJ@R;,^6P2] B*U\26!$:U)VY\R\"71,5 JE*4BLK"#*B(I +M2K9ET+4BHJMXT9]?LJIMN[1J.R%[(P544 7_IISYBB*$FJ-SFE1^R[<;ZE)^ +M^ZFU4;ATF@!K,:R(6QTUDJ\B6R\M$S.720:>H7=9BAJG>!>9ZSF7NW>;^1[^ +MV2>ANY!-Z9# JK@(1P2'$I$]@B*N>R*3@;H<"A=39%PLZ9*IZR0D:5N%$;JJ +M@11D8 >A*P=K0 ,NT*7SFJ7*RY22IIK@F3(Z:Y%$8!IFX!U]$KL^HAV1Y*Z5 +MYANC(3CME :ATX+&0@=W<"QNT(+>96E/H46VT226BY$AA!WJX;[N2)\$ZX[Z +ML;]T\*=ZX+_T&S3,>U;,DH<+/RB<\RIC,B4;+,/ +M>\VO#,F23,N5C)[O6<_V;,\3DHZ>V2*U61 O$*8KTAJ@R9MX$P1+D (NL)P) +M,!"5LA?8*)5@0!H!I9HD^P4FVRM\$!I)U (=DD4OP 7W^0*;^0)G< )@D+J@ +M*;E$DYI1>\UR$=$#P52@6;=W^V\8K=%[P=$@X-$@_08B/08D;=+CLM!HT-#E +M5P,UH+TH\LJGL@2[C"U'\[7-8;C=9J[=-L +M+=0IVG]GHSNA,@26U5TA$G&-<1@;"05T@G=SD *0%/.-@JN=_=H4G2H6+=LW;=;(;=N!G=MMC=+9[-(V2]>^#0+"/=,)4]-] +M?=PZS=-K#=3O7=C$=]@BN"I ,B%W:ABYF12>W<^W"="C[=U_4]#@O>!RL /- +M;=0/;=_D'=;F/=:TO=[^+=@ 3MB\3=\L'=_!W>%ZG=]\G=Y_S=[*7>+,3=1& +M/1/1;9+3S=0&?=U1[)V^^)('N,C[MXF/GQ*0^!N1R<^(.&]:=HN8.$38N$-#MH0SB7JC ;X8>'1 +M#!]=*^>J/! S<.8[EKIWC@;(*^?BW.=Z;F!][JERGN'/O>%5'MLI,]O\G=Q, +M'N G/KDI_N1[..1@;>7Z#>.UO>7+/=2JO1.] M79#>1+0^4L +MGK)9WNE+3N)-/N9]'N<[]LI![NI$OLA8'.LB/NM\GNEW +M#.Q*WMZ?7NS)G.<6;NJ@N>N8GM>MS.G!#NTTOKO9OLQM[.R03NOO+>U2_.?( +M?NVM'NXIW+//N.U_K66^^:#+@>ZWNYS3>G+GM?$O=])7N[##NYP#>5A +MOH9?[@2Z P+H3L>&GNL*H.J>Z>"A'=#0Z\X)(!PKP@92X.YV\N%'+N\$_^EW +MS>(!S^WS'NE=?O"7WN]UK?!( .:)G;I\$ 9W@%(G\ )>0 (D\ (@L =IECE] +ML ,\OP4M0 9= /1";UM]8@8H( (E(!M3OU$E@!%[4?5:3_5SP 5N( +L 5>D/1+'_1#WR=]< *I +M.^:@&;U[.%(*,"N>Y085S^:BW1HJH)^.]V9S@ EG\03DL!L\/F*#R063_J/'Z2G +MSQ>37_F7G_FP[_J0J[R/3\4)D/N-;[#N"+NBX;> N[>V02G0;[7NF*^+>R[5 +M_[CNB/N,C_'.JY&UJ[UG#J/G$Q"C:R.?ZVD*@!V!.QGJ\?YD @?0KP?R/U/5 +MCXK0;Z?:C_W$W_T*0/[I /GGHI)9+7-D/ "8N0:?( +M@%AA A3/+U_I@ SHC@J@/'ME"5 U+<"YT0"+@!%(32V J7! &[$")Y6*,H 5 +ML#&-BLM&N#0@_H-<@PL&@D#15)HH$PE430XP!=Y =S0$_U:*HH!B[ (*,P%H +M_Z2?LYISE&P'*D ?F.*"8*NZ?TVP^ )[A1 D@T00#AK!.M4%D^ ,5 #_CPZ,0>[WMRB@%!2!:Q (FD 4 +M&*+XX.8K@T>P#MHP)%K?J5N(N'%ZRFO7N<);TZE.9[)29 +ML73V"1>9*W-D\,P,3C-?A\VT&12+6WC@CQ4P@O4KX$(,X$?F:!EIA)LPC4+" +M2"@))J$:981K)!.T$4R0"33!)C@C:T039(!/0(@@$1TEA:6 DYY"68A'\P@K +MD 5[)(V^0E@ B3 Q)E8$%Z0I'@]"2 5(D8H 6,S(+Y"@L !.H X324:H !8 +M1(L(6O>))26 *Y!$GL 5(1!>223H@)>0(*(B?R"*3\@)-2'V19QR NH"4GM +M!2D N9 ]D "4 /MXPL8FM;P!8Z#E=@!JRA[?0'#\P7<0!W@*B#@"XBS+[!; +MXH5!D,0'HQ8'"%[.#CGA.OV$N/I["&#]0@ F\%^0I4120Q1Y0 +M4TAC9HP-Z8@.$)#'U'JFAET;B_"F+": -[ &OH#_2HV!,0'4%-C(&,\ "AB, +M9* Y3D; &!Q?S&5\CFYQ@FC&W%ACRH!H)(VFT0R@Q@30!X"54;P/,L KU@2O +M9!1; ' 4CN!Q+>;%[ @7 0ASM(MX$3HV1^08'/5C7SR,&HT.,,?_Z!C#S^G1 +M%]/Q/5I'\G(;-V/_\(Q6HCM^Q[2X%E$CL%J-@I$NXD?:^!MLXW9\"@D20[;& +MO*@A[R)OQ$H@X#<&1K-('(WC4^"/I6(YTD4"Z1\-8X),CI:104)([8@;GX*$ +MA'KQ\306$/((K+)B#-J*:B$GJ$>D=AM1BI)%=TD:>232)&=FDFNP?H1%( +MODGQ."3+XX,ZC^X'!GS%&G #5H11?))G<5+.Q\]8'^6BG<22B5)+4D=!D24! +MI(P\E&+R,1Y(,[DE3%5GH$SV2J_I+2$E8WQ,2J!*F QK&5EE"O7 +M<5NRR4CI)DMCA326K'%.OD8[B2?UI(/LD[TQ10+*X2@H7R2A?)6Q$5$2QO_H +M+_^E?M&1VA)7)Y*5D$>0R[HF$I-8>0664')5OD4J2R,6('U'EQC2, +M]%)>VLL!&2O#S[[LEV<26Q)+'SDPA\R$))F4,D[V1X8I+.' T.23(& '^,IC +MJ3!G9FS$CW+!3TI,9ADH7:0[6I08LSD^1WG9,1DE=OR,+&!;$DQ>62F!E4PL +M1P11C7G$M_F+%&(S>D8.L1I1(XB($[C"0]Q&&+$F? 1P- -HPD$D1W0S&8E$ +M=00#V)%)A$=4P2JHQ+' $E-"/DJ%^M%(# +MNT9#L2BB3,ZYF9(B9#@^M@4$.$4;(0-P %8:930@!P3%') ZPZ58I(D8809\ +M196 +E4 <-PHK1%TN $\X/"P4M6" RW !S#/UJ,_^ <*4)Y_ L-]&DK4(;13 +M])R>=:)^'!@G4 52A?8<%^ !>4)/'Q $P*?W9)]>\S*13_.I&CG*^S0W[G-] +MFIOXV7KF)Q/ <.E3+KQ/(9 _HZ<0X)\@P'^>3_49/8G69;)^;?&C? &BM4 % +MZ/H\"J0$@8&(!XJ*(FATQ*"E44V B I:'=9GA1*0FO$R>2H8@.$P)8 8GO2I +M97Z:Y%D7F.>8@P'/\WM>INKY&ZYG#9U%VQ.$E% =VGI0@/AT, H4.-9/!LH^ +MP:<"M:#1,P@@T"0:0()'R)L0<6_R37%4^2PB-\J( +M ()PUH"=\!$GZ2Y:G"2Q*3S.L8 2)6<]\@J:%!^]1%-*2W<13?QD;@L-X,0Z +MT"&:@($! ;:S=(Y2K605^X/J;!&X=&DA!-=Y!F!G&I"=3[%VWLZIV,!H0#"] +MBN R7([+&4 #6, ,X)UB\3QR4Q9 V+HIXQ Z/#39 800 7RP&B0.-\"1$"5 +MC<3"U$>)NB++08LPEU\V&$*'A(A G0,%M89ZB@<40$!M&P0U3_ 3*:-$Y4)F +M2*@T0Y[:E\L@%]A,NJ@M5L1&!+U$6DL[JD?]J" UI(K4D4I22ZI)/:DH-:6J +%U)5JC@#: + +end diff --git a/MACHINES/Cray/patch.1 b/MACHINES/Cray/patch.1 new file mode 100644 index 0000000..1370b00 --- /dev/null +++ b/MACHINES/Cray/patch.1 @@ -0,0 +1,56 @@ +*** err.h Thu Jan 13 16:38:12 1994 +--- err.h.orig Wed Oct 26 17:56:36 1994 +*************** +*** 129,135 **** + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ +--- 129,136 ---- + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! _err_num=setjmp(restart); \ +! if ( _err_num == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ +*************** +*** 149,155 **** + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ +--- 150,157 ---- + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! _err_num=setjmp(restart); \ +! if ( _err_num == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ +*************** +*** 166,172 **** + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_JUMP); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ +--- 168,175 ---- + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_JUMP); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ +! _err_num=setjmp(restart) ;\ +! if ( _err_num == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ diff --git a/MACHINES/Cray/patch.2 b/MACHINES/Cray/patch.2 new file mode 100644 index 0000000..71967ef --- /dev/null +++ b/MACHINES/Cray/patch.2 @@ -0,0 +1,23 @@ +*** iter0.c Mon Jun 20 15:22:36 1994 +--- iter0.c.orig Fri Oct 28 01:49:19 1994 +*************** +*** 103,111 **** + if (lenx > 0) ip->x = v_get(lenx); + else ip->x = (VEC *)NULL; + +! ip->Ax = ip->A_par = NULL; +! ip->ATx = ip->AT_par = NULL; +! ip->Bx = ip->B_par = NULL; + ip->info = iter_std_info; + ip->stop_crit = iter_std_stop_crit; + ip->init_res = 0.0; +--- 103,111 ---- + if (lenx > 0) ip->x = v_get(lenx); + else ip->x = (VEC *)NULL; + +! ip->Ax = NULL; ip->A_par = NULL; +! ip->ATx = NULL; ip->AT_par = NULL; +! ip->Bx = NULL; ip->B_par = NULL; + ip->info = iter_std_info; + ip->stop_crit = iter_std_stop_crit; + ip->init_res = 0.0; diff --git a/MACHINES/Cray/patch.3 b/MACHINES/Cray/patch.3 new file mode 100644 index 0000000..69b5a32 --- /dev/null +++ b/MACHINES/Cray/patch.3 @@ -0,0 +1,13 @@ +*** zmatrix.h Tue Mar 8 15:50:26 1994 +--- zmatrix.h.orig Fri Oct 28 01:52:48 1994 +*************** +*** 34,39 **** +--- 34,41 ---- + + /* Type definitions for complex vectors and matrices */ + ++ #undef complex ++ #define complex Complex + + /* complex definition */ + typedef struct { diff --git a/MACHINES/GCC/machine.h b/MACHINES/GCC/machine.h new file mode 100644 index 0000000..4164889 --- /dev/null +++ b/MACHINES/GCC/machine.h @@ -0,0 +1,191 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + + +#define ANSI_C 1 +#define NOT_SEGMENTED 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/* #undef U_INT_DEF */ + + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +/* #undef HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +#define REAL_DBL 1 + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/GCC/makefile b/MACHINES/GCC/makefile new file mode 100644 index 0000000..532a4b8 --- /dev/null +++ b/MACHINES/GCC/makefile @@ -0,0 +1,187 @@ +# +# +# Makefile for Meschach for GNU cc +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: $ +# + +srcdir = . +VPATH = . + +CC = gcc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O6 + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12a +TAR = tar +SHAR = stree -u +ZIP = zip -r -l + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + + +HLIST = err.h iter.h machine.h matlab.h matrix.h matrix2.h \ + meminfo.h oldnames.h sparse.h sparse2.h \ + zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +HBASE = err.h meminfo.h machine.h matrix.h + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1); $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2); $(RANLIB) + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3); $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1); $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2); $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST); $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/MACHINES/Linux/machine.h b/MACHINES/Linux/machine.h new file mode 100644 index 0000000..13ea93f --- /dev/null +++ b/MACHINES/Linux/machine.h @@ -0,0 +1,193 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +/* #undef const */ + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +/* #undef WORDS_BIGENDIAN */ +#define U_INT_DEF 1 +#define VARARGS 1 + + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#define HAVE_PROTOTYPES 1 +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/Linux/makefile b/MACHINES/Linux/makefile new file mode 100644 index 0000000..168ad6b --- /dev/null +++ b/MACHINES/Linux/makefile @@ -0,0 +1,200 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12a +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1); $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2); $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3); $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1); $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2); $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST); $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/MACHINES/MicroSoft/machine.h b/MACHINES/MicroSoft/machine.h new file mode 100644 index 0000000..e9775c9 --- /dev/null +++ b/MACHINES/MicroSoft/machine.h @@ -0,0 +1,236 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.3 1995/03/27 15:36:21 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#ifndef _MACHINE_H +#define _MACHINE_H 1 + +/* #undef const */ + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +#define HAVE_MEMORY_H 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +/* #undef HAVE_BCOPY */ +/* #undef HAVE_BZERO */ +#define CHAR0ISDBL0 1 +#undef WORDS_BIGENDIAN +/* #undef U_INT_DEF */ +#define VARARGS 1 +#define HAVE_PROTOTYPES 1 +/* #undef HAVE_PROTOTYPES_IN_STRUCT */ + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS +#define D_MACHEPS + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT +#ifdef M_MAX_INT +#ifndef MAX_RAND +#ifdef RAND_MAX +#define MAX_RAND RAND_MAX +#else +#define MAX_RAND ((double)(M_MAX_INT)) +#endif /* MAX_RAND */ +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL +#endif +#endif +#ifdef HUGE_VAL + /* HUGE_VAL later defined in math.h */ + #undef HUGE_VAL +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + +#endif diff --git a/MACHINES/MicroSoft/makefile b/MACHINES/MicroSoft/makefile new file mode 100644 index 0000000..283c3f6 --- /dev/null +++ b/MACHINES/MicroSoft/makefile @@ -0,0 +1,238 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: makefile.in,v 1.4 1994/03/14 01:24:06 des Exp $ +# + +srcdir = . +VPATH = . + +CC = gcc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O2 -ffast-math -fexpensive-optimizations + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12b +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +# the dependencies **between** the parts are for dmake +all: part1 part2 part3 zpart1 zpart2 +part2: part1 +part3: part2 +basic: part1 part2 +sparse: part1 part2 part3 +zpart2: zpart1 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru libmeschach.a $(LIST1) + $(RANLIB) libmeschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru libmeschach.a $(LIST2) + $(RANLIB) libmeschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru libmeschach.a $(LIST3) + $(RANLIB) libmeschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru libmeschach.a $(ZLIST1) + $(RANLIB) libmeschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru libmeschach.a $(ZLIST2) + $(RANLIB) libmeschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru libmeschach.a $(OLDLIST) + $(RANLIB) libmeschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a *.dll *.def + +realclean: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a *.dll *.def + /bin/rm -f torture.exe sptort.exe ztorture.exe memtort.exe \ + itertort.exe mfuntort.exe iotort.exe + /bin/rm -f maxint.exe macheps.exe +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + libmeschach.a $(LIBS) +sptort:sptort.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + libmeschach.a $(LIBS) +memtort: memtort.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + libmeschach.a $(LIBS) +ztorture:ztorture.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + libmeschach.a $(LIBS) +itertort: itertort.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + libmeschach.a $(LIBS) + +iotort: iotort.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + libmeschach.a $(LIBS) +mfuntort: mfuntort.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + libmeschach.a $(LIBS) +tstmove: tstmove.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + libmeschach.a $(LIBS) +tstpxvec: tstpxvec.o libmeschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + libmeschach.a $(LIBS) + +OBJ=$(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) +DLLTOOL= dlltool +DLLWRAP= dllwrap + +DLL_NAME = meschach.dll +DLL_EXP_DEF = libmeschach_dll.def +DLL_EXP_LIB = libmeschach_dll.a + + +DLL_LDFLAGS = -L . +DLL_LDLIBS = -lm +DLL_CFLAGS = --verbose --export-all-symbols +DLLWRAP_FLAGS = --output-def $(DLL_EXP_DEF) \ + --implib $(DLL_EXP_LIB) \ + --driver-name $(CC) #--no-delete + +$(DLL_NAME) $(DLL_EXP_DEF) $(DLL_EXP_LIB): $(OBJ) + $(DLLWRAP) $(DLL_CFLAGS) $(DLLWRAP_FLAGS) -o $(DLL_NAME) \ + $(OBJ) $(DLL_LDFLAGS) $(DLL_LDLIBS) + + + +dll: $(DLL_NAME) \ No newline at end of file diff --git a/MACHINES/MicroSoft/stewart.zip b/MACHINES/MicroSoft/stewart.zip new file mode 100644 index 0000000000000000000000000000000000000000..57ab10d3a8db2d10eabaea3dba547909a906cb04 GIT binary patch literal 4027 zcmZ`+Ra6uVw;d3qWw}?TkPwiLLAnJ5=^j#Aq??hD z-~X;#5BENuSZhC=v(8z2Z*`?dIA8!a03VR5V$Ahqv(14W9{?bG2Kd_n09-7bY-}Bz zZAPh`ycXY{p~^O7yj{?79#He{A=5!N9rPNyP26{(vxD1=&y)!yZwD*NA*I?EeYkJ^ z8Nnzj(4xI!86IeRBeL@1#dML~NnWusMuMp44r<7vC)2Sg@|~=2v&+UGgOf>sQgzGJ2Ea;9TQHQKHXo6gtfC=J84yh?9PpG3aoA z-F&x)$FEwRcD{<|Y^8;9piPJ-ZlNU(I;J>uc-DT3&S;4m$YC7Wp;odHwxSz!j2jJ`ulscoR*j5WfE8x0r&)Vk*LM+uGgZ-P|p1 z8=0VYMMAdm)mRpIdV~%8j=E%c z!!+|W1$VdiF&;b4pABuOaFY0Yp7k(!TcE~8W}vOtB_1eKMXPCS6EcT{Sf^K`x72s>=9TT3o4>%%DV>XzM6A-W=l5@$i&5RXQ)Z zJH{Fz4vxGB#j3E0mKa12W4%v}`!JE28lU>lHLSPrSy&fk?$Ki6Tr zS(dEOM}L7Na@)Ij;p!(*%uPjH8d$Ka)E7Xe1%ijhBBrZrZFzDxVd6TKsO_s^*?5APiH=NE;4s9nw(9O6(P==Wo{xZ%qn@w7xFnRSU=-CQ~GL$<>!bl#KyXWsV${IiF!(5!% zyQ_*4Ily@k2>`S-?fN%cE_+n+;f}O~MTV1@9Wm70e_JSh4G8OL>TDR6zRZaL@e*rx<&yZ0zj% z&ZGvWkaQw%u{d<{r{*YA{&B=Dsv&axTnt~@YkCxM#N}=Fr7+JV;jrd5FLv7De4g}jHGkSZHD>LqVmKOUO=UShmS=Wy=`GV!V2`my0IC9m#{{&0p zPWF7C=3q}=g8`vgT3Q_i#4w{C)^(=##ij5c`jGYLwR$)m953dZc~Xzp!X0{TRDPm8 z;7^XC@Mn~wSL&WlZ*};lx!``$h3bJCzZsukj%DD~t<5W;j26cYk80u`XB{`>o~RDG zyhR;(^RZlbJ@0}zF;ND{mmda1)Psj(Uluv=<8D$#`BL%z!CuwB$x%>8*%wLYX0VLpDb$55h8XZQQ^e35g zLNX?GXkrrycOHUZiI4?XpS#C-BhFQF#nCLewmB(BYdsF7q?Q43UCzq6IOm&gnwvzX zHjYLF^%AH{ruWd6A9K+-8T+^W-)0j*gey-IXCQ%$%{=p|Q6Rz}Gw~ooJSQ%eRwo~! zKnY~!OVx6O{im|c0*m_3-g?BjJBmlcx8g}sJw%qVvHaXo_i>UsP9Nrc`Y#`Qj`Y#~ zqT#e1ThZ+4e9!1qhkHt+F*mldkrV%OSzCH2crIq;47cy`hVhfiWix4JVq8y_#E@`^ zDTokNBR zo9cB4ylnww@@0yFm|smT%8lvMhhD4M^QQCFti2X;c!??g+T2xvpI~j%0V_?^W%t^# z-TY@^6ES|_wgC$yls6V`P#bHhX!wTa>T>u|{yd&+Aa_B~tP$R9#ow!{2^t6FiCJ0p z)nT7YiIgdBPkJBWZKr2>Zl?aTYUTE zVJSGaWorh_Ia;J~Jk#(ZCKSPV8XdZ|I1Nj$qpWp2W)6bM%G{4uc3dsKnyFaCMxA3u zN5-ti)tFAhb@~<-_JC`N9_cqJ5o>Or-Ud_S!fD+sIwM}4KpU1n0T)!qjeeF+tQ+wH z7qW3DnL&h%h@5`x^e~%ROU~&^3w$O79BkKZ&|N>G)>Qk1)487=_cUC#Pbj8w;?tVq zg;)yPI?NA5sNoOlx<2g!5xVp(jk^c<;$|?&z{R_oB|{!KjN#3lH=8&2Y&65&?+m^k z8xA>B*o1}*?XX*&u%vK{b0HldA{M{YM>c-JIJgLS1v6ZtS%7BzUtsZUl5oKHX7gXs}9#!mIaA;gB>$ zPWtcYxSFJ2+>RmkK`ZP2XDXaE7oQPF{uqdR*G6&ycZP;-YJ7>B-3!)cWS&&kQF-gH zM21cZN|gM=H)OoZ<;v~YR-w${3Xtz@z}U^T|5Q$(*u9kB%)XzzxqZOJO;OgomzxTk z8WLvbDdrM*1EC%tK)I0|(TC1bb6u36hOGQbtd!58pX<;8Kq5?sQrBgFJJ4i;UP!RDZ*!@cKMF2 zEs~>&s8kVof54mNytFI%L1RPwBe3b2t_Tfx#umJH5#BmN8`p{b4hr@dP(%k&yL{_j zj30fyDX*@sJo%#X<-zMrlth5MPmImiyMF?qt~Au*qLbd_g9uc=Gjce8%P&d0;C!YT#aqJIlbA`tD|kF-tLYQRd8t!1 zTIg9A2+X=P7=EzHK9vBCTPIM&PUu;ZN0r|fo<>K0VqkvZM@_oE<{(>p_B-V@s~2NS z;PXGhW7bpzf`v1FdOVowUd?!tco?(#ixs-NJOPJhD_?oGMA?ieI1O{(<&>uDj2kJ- z9gBmE>CkfG(#lv4X(r~33SI5;?rchZODL_wY!R-rry6`t7;wS+8ec><#@99c?-&u)&EOiQMWY^V zdx4+@-gVCqh@gSs{N9(YP#>;O`JFjsHWMKO{j(o8g#(M+7!RXThn9Zw65t4aBL6r7xN)7?CRj9QmT0i2V=7X`1c9Xo{WTvuVg=(R{p ziL#6L!5LGPZz+(|T(oOp&niE3$0-iGk1Xy^M=}=}{{2Qu85dWeyHkyR{W!+sohipPLIE&;cYS$yR97;XAM?*xd=^ zeb7)Mi3LhWD;nKyWZ~H>T$(~57R?V8Ki?3%M^<#yZt8XxS8{*@d?+wT?Z>$}-F3{6%s8^q&jj+!+us@Q& zoA>cbO_K?z${D3IIa`i$U|4^`8FjO*^r#9-LTQb1Jm3+}#d1-~=McUx_N)(^5R(?%2+U7-#?yW*soQ8SVA2S>rz0K zgs(%tK+}0ja`l}n +To: david.stewart@anu.edu.au +Subject: meschach documentation + +Dear David, + +[snip] + +By the way: I have installed the library with EMX 0.9a + gcc under +OS/2. I have included the makefile, may it is useful for others. + +[Note: I have also put the "standard" gcc machine.h here as well. + -- David Stewart, 4th Oct, 1995] + +Best regards + +//wenzel + +-- + ___ +wenzel matiaske | / /_/-Berlin + | + | mail: Technical University Berlin + | Dept. of Economics & Management, WW6 + | Uhlandstr. 4-5, D-10623 Berlin + | phone: +49 30 314-22574 + | email: W.Matiaske@ww.TU-Berlin.de + diff --git a/MACHINES/OS2/machine.h b/MACHINES/OS2/machine.h new file mode 100644 index 0000000..4164889 --- /dev/null +++ b/MACHINES/OS2/machine.h @@ -0,0 +1,191 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + + +#define ANSI_C 1 +#define NOT_SEGMENTED 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/* #undef U_INT_DEF */ + + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +/* #undef HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +#define REAL_DBL 1 + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/OS2/makefile b/MACHINES/OS2/makefile new file mode 100644 index 0000000..27f73d4 --- /dev/null +++ b/MACHINES/OS2/makefile @@ -0,0 +1,208 @@ +# +# +# Makefile for Meschach for GNU cc/emx (OS/2) +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# modified by mati1831@perform.ww.tu-berlin.de +# +# $Id: $ +# + +srcdir = +VPATH = + +CC = gcc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +# we don't have ranlib +RANLIB = ar -s + +CFLAGS = -O6 + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +# we do not need the shell +##SHELL = sh +# if we have rm, otherwise use del. +RM= rm -f +MES_PAK = mesch12a +TAR = tar +SHAR = shar -u +ZIP = gzip -r -l + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + + +HLIST = err.h iter.h machine.h matlab.h matrix.h matrix2.h \ + meminfo.h oldnames.h sparse.h sparse2.h \ + zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +HBASE = err.h meminfo.h machine.h matrix.h + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1) + $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2) + $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3) + $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1) + $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2) + $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST) + $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + + +clean: + $(RM) *.o core asx5213a.mat iotort.dat + +cleanup: + $(RM) *.o core asx5213a.mat iotort.dat *.a + torture sptort ztorture memtort itertort mfuntort iotort + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) + emxbind torture +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) + emxbind sptort +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) + emxbind memtort +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) + emxbind ztorture +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + emxbind itertort +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) + emxbind iotort +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) + emxbind mfuntort +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) + emxbind tstmove +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + emxbind tstpxvec + + + diff --git a/MACHINES/RS6000/machine.c b/MACHINES/RS6000/machine.c new file mode 100644 index 0000000..2332e16 --- /dev/null +++ b/MACHINES/RS6000/machine.c @@ -0,0 +1,238 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + This file contains basic routines which are used by the functions + in matrix.a etc. + These are the routines that should be modified in order to take + full advantage of specialised architectures (pipelining, vector + processors etc). + */ +static char *rcsid = "$Header: /usr/local/home/des/meschach/meschach/RCS/machine.c,v 1.3 1991/08/29 06:42:11 des Exp $"; + +#include "machine.h" + +/* __ip__ -- inner product */ +double __ip__(dp1,dp2,len) +register double *dp1, *dp2; +int len; +{ + register int len4; + register int i; + register double sum0, sum1, sum2, sum3; + + sum0 = sum1 = sum2 = sum3 = 0.0; + + len4 = len / 4; + len = len % 4; + + for ( i = 0; i < len4; i++ ) + { + sum0 += dp1[4*i]*dp2[4*i]; + sum1 += dp1[4*i+1]*dp2[4*i+1]; + sum2 += dp1[4*i+2]*dp2[4*i+2]; + sum3 += dp1[4*i+3]*dp2[4*i+3]; + } + sum0 += sum1 + sum2 + sum3; + dp1 += 4*len4; dp2 += 4*len4; + + for ( i = 0; i < len; i++ ) + sum0 += (*dp1++)*(*dp2++); + + return sum0; +} + +/* __mltadd__ -- scalar multiply and add c.f. v_mltadd() */ +void __mltadd__(dp1,dp2,s,len) +register double *dp1, *dp2, s; +register int len; +{ + register int i, len4; + + len4 = len / 4; + len = len % 4; + for ( i = 0; i < len4; i++ ) + { + dp1[4*i] += s*dp2[4*i]; + dp1[4*i+1] += s*dp2[4*i+1]; + dp1[4*i+2] += s*dp2[4*i+2]; + dp1[4*i+3] += s*dp2[4*i+3]; + } + dp1 += 4*len4; dp2 += 4*len4; + + for ( i = 0; i < len; i++ ) + (*dp1++) += s*(*dp2++); +} + +/* __smlt__ scalar multiply array c.f. sv_mlt() */ +void __smlt__(dp,s,out,len) +register double *dp, s, *out; +register int len; +{ + register int i; + for ( i = 0; i < len; i++ ) + (*out++) = s*(*dp++); +} + +/* __add__ -- add arrays c.f. v_add() */ +void __add__(dp1,dp2,out,len) +register double *dp1, *dp2, *out; +register int len; +{ + register int i; + for ( i = 0; i < len; i++ ) + (*out++) = (*dp1++) + (*dp2++); +} + +/* __sub__ -- subtract arrays c.f. v_sub() */ +void __sub__(dp1,dp2,out,len) +register double *dp1, *dp2, *out; +register int len; +{ + register int i; + for ( i = 0; i < len; i++ ) + (*out++) = (*dp1++) - (*dp2++); +} + +/* __zero__ -- zeros an array of double precision numbers */ +void __zero__(dp,len) +register double *dp; +register int len; +{ + /* if a double precision zero is equivalent to a string of nulls */ + MEM_ZERO((char *)dp,len*sizeof(double)); + /* else, need to zero the array entry by entry */ + /************************************************* + while ( len-- ) + *dp++ = 0.0; + *************************************************/ +} + +/*********************************************************************** + ****** Faster versions ******** + ***********************************************************************/ + +/* __ip4__ -- compute 4 inner products in one go */ +void __ip4__(v0,v1,v2,v3,w,out,len) +double *v0, *v1, *v2, *v3, *w; +double out[4]; +int len; +{ + register int i, len2; + register double sum00, sum10, sum20, sum30, w_val0; + register double sum01, sum11, sum21, sum31, w_val1; + + len2 = len / 2; + len = len % 2; + sum00 = sum10 = sum20 = sum30 = 0.0; + sum01 = sum11 = sum21 = sum31 = 0.0; + for ( i = 0; i < len2; i++ ) + { + w_val0 = w[2*i]; + w_val1 = w[2*i+1]; + sum00 += v0[2*i] *w_val0; + sum01 += v0[2*i+1]*w_val1; + sum10 += v1[2*i] *w_val0; + sum11 += v1[2*i+1]*w_val1; + sum20 += v2[2*i] *w_val0; + sum21 += v2[2*i+1]*w_val1; + sum30 += v3[2*i] *w_val0; + sum31 += v3[2*i+1]*w_val1; + } + w += 2*len2; + v0 += 2*len2; + v1 += 2*len2; + v2 += 2*len2; + v3 += 2*len2; + for ( i = 0; i < len; i++ ) + { + w_val0 = w[i]; + sum00 += v0[i]*w_val0; + sum10 += v1[i]*w_val0; + sum20 += v2[i]*w_val0; + sum30 += v3[i]*w_val0; + } + out[0] = sum00 + sum01; + out[1] = sum10 + sum11; + out[2] = sum20 + sum21; + out[3] = sum30 + sum31; +} + +/* __lc4__ -- linear combinations: w <- w+a[0]*v0+ ... + a[3]*v3 */ +void __lc4__(v0,v1,v2,v3,w,a,len) +double *v0, *v1, *v2, *v3, *w; +double a[4]; +int len; +{ + register int i, len2; + register double a0, a1, a2, a3, tmp0, tmp1; + + len2 = len / 2; + len = len % 2; + + a0 = a[0]; a1 = a[1]; + a2 = a[2]; a3 = a[3]; + for ( i = 0; i < len2; i++ ) + { + tmp0 = w[2*i] + a0*v0[2*i]; + tmp1 = w[2*i+1] + a0*v0[2*i+1]; + tmp0 += a1*v1[2*i]; + tmp1 += a1*v1[2*i+1]; + tmp0 += a2*v2[2*i]; + tmp1 += a2*v2[2*i+1]; + tmp0 += a3*v3[2*i]; + tmp1 += a3*v3[2*i+1]; + w[2*i] = tmp0; + w[2*i+1] = tmp1; + } + w += 2*len2; + v0 += 2*len2; + v1 += 2*len2; + v2 += 2*len2; + v3 += 2*len2; + for ( i = 0; i < len; i++ ) + w[i] += a0*v0[i] + a1*v1[i] + a2*v2[i] + a3*v3[i]; +} + +/* __ma4__ -- multiply and add with 4 vectors: vi <- vi + ai*w */ +void __ma4__(v0,v1,v2,v3,w,a,len) +double *v0, *v1, *v2, *v3, *w; +double a[4]; +int len; +{ + register int i; + register double a0, a1, a2, a3, w0, w1, w2, w3; + + a0 = a[0]; a1 = a[1]; + a2 = a[2]; a3 = a[3]; + for ( i = 0; i < len; i++ ) + { + w0 = w[i]; + v0[i] += a0*w0; + v1[i] += a1*w0; + v2[i] += a2*w0; + v3[i] += a3*w0; + } +} diff --git a/MACHINES/RS6000/machine.h b/MACHINES/RS6000/machine.h new file mode 100644 index 0000000..0ebed75 --- /dev/null +++ b/MACHINES/RS6000/machine.h @@ -0,0 +1,186 @@ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#define ANSI_C 1 + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +#define U_INT_DEF 1 + + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#define HAVE_PROTOTYPES 1 +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/RS6000/makefile b/MACHINES/RS6000/makefile new file mode 100644 index 0000000..14be57b --- /dev/null +++ b/MACHINES/RS6000/makefile @@ -0,0 +1,202 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12a +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1); $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2); $(RANLIB) meschach.a +schur.o: schur.c $(HBASE) matrix2.h + cc -c $(DEFS) schur.c + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3); $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1); $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2); $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST); $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/MACHINES/SGI/machine.h b/MACHINES/SGI/machine.h new file mode 100644 index 0000000..6150a7b --- /dev/null +++ b/MACHINES/SGI/machine.h @@ -0,0 +1,224 @@ +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +/* #undef const */ + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +#define HAVE_MEMORY_H 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/*#undef U_INT_DEF */ +#define U_INT_DEF +#define VARARGS 1 +#define HAVE_PROTOTYPES 1 +/* #undef HAVE_PROTOTYPES_IN_STRUCT */ + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +#define REAL_FLT 1 +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#undef HUGE +#define HUGE HUGE_VAL +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/SGI/makefile b/MACHINES/SGI/makefile new file mode 100644 index 0000000..98f5ab9 --- /dev/null +++ b/MACHINES/SGI/makefile @@ -0,0 +1,215 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: makefile.in,v 1.4 1994/03/14 01:24:06 des Exp $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12b +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +# the dependencies **between** the parts are for dmake +all: part1 part2 part3 zpart1 zpart2 +part2: part1 +part3: part2 +basic: part1 part2 +sparse: part1 part2 part3 +zpart2: zpart1 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1) + $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2) + $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3) + $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1) + $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2) + $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST) + $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +realclean: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + /bin/rm -f torture sptort ztorture memtort itertort mfuntort iotort + /bin/rm -f makefile machine.h config.status maxint macheps + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/MACHINES/SPARC/machine.h b/MACHINES/SPARC/machine.h new file mode 100644 index 0000000..03b849b --- /dev/null +++ b/MACHINES/SPARC/machine.h @@ -0,0 +1,187 @@ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#define const + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +/* #undef STDC_HEADERS */ +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/* #undef U_INT_DEF */ +#define VARARGS 1 + + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +/* #undef HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +#define REAL_DBL 1 + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/MACHINES/SPARC/makefile b/MACHINES/SPARC/makefile new file mode 100644 index 0000000..a72c306 --- /dev/null +++ b/MACHINES/SPARC/makefile @@ -0,0 +1,186 @@ +# # +# Makefile for Meschach for SUN SPARC cc +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12a +TAR = tar +SHAR = stree -u +ZIP = zip -r -l + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + + +HLIST = err.h iter.h machine.h matlab.h matrix.h matrix2.h \ + meminfo.h oldnames.h sparse.h sparse2.h \ + zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +HBASE = err.h meminfo.h machine.h matrix.h + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1); $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2); $(RANLIB) + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3); $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1); $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2); $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST); $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/MACHINES/ThinkC/README b/MACHINES/ThinkC/README new file mode 100644 index 0000000..a273ac4 --- /dev/null +++ b/MACHINES/ThinkC/README @@ -0,0 +1,103 @@ +README file for compiling Meschach with Think C +=============================================== + +Received 8th June, 1995 from Brent Boyer (boyer@jumpjibe.stanford.edu). + + +I have modified this file to make the Meschach routines work on a +Macintosh with THINK C 7.0.4. I realize that THINK C is now on +version 8.x and that Metrowerk's CodeWarrior is a competetive +development environment, but 7.0.4 is what I have available. My +system is a Quadra 650 running MacOS 7.5.1. The compile options +described below should work for any 68K Mac with a floating point +unit; they probably have to be modified for Power Macs. + +Below I describe the steps I took to build a library project for all +the Meschach routines. + + +Step 1) +_________ + + First create an appropriate version of THINK's ANSI library. +What I did was copy their project "ANSI" to one I called +"ANSI(020, 881, 4b ints)". I then selected these compiler ("THINK +C...") options before bringing the project up to date: + + -- first, under "Language Settings" + 1) choose "Factory Settings" + 2) also change "Infer prototypes" to "Require prototypes" + (as a former Pascal programmer, I curse the + person who introduced infered prototypes!) + (Note: you _cannot_ choose "ANSI Settings"; if + you do, then the compilation of the ANSI + project will fail! Talk to the people at + Symantec about this one ...) + + -- next, under "Compiler Settings" + 1) turn "Generate 68020 instructions" ON + 2) turn "Generate 68881 instructions" ON + 3) turn "4-byte ints" ON + (so int == long int <==> 32 bits) + 4) make sure that "8-byte doubles" turned OFF + (so double == long double) + 5) turn "Native floating-point format" ON + + (The other options probably do not matter either way) + + (Note: 2) and 5) ==> type double will be the 96 bit + MC68881 floating point extended precision type; + these options give the best speed and good accuracy too) + + -- optionally, under "Code Optimization" + 1) turn "Use Global Optimizer" ON + + +Step 2) +_________ + + Create a project ("Meschach") containing all the Meschach +routines that can serve as a library. After opening a new project +("ANSI Project" type) to which you added all the source code files, +select these compiler ("THINK C...") options before bringing the +project up to date: + -- first, under "Language Settings" + 1) choose "ANSI Settings" + (tragically, will have to leave "Infer prototypes" on) + + -- next, under "Compiler Settings", make the same choices as + when compiled "ANSI(020, 881, 4b ints)" + 1) turn "Generate 68020 instructions" ON + 2) turn "Generate 68881 instructions" ON + 3) turn "4-byte ints" ON (so int == long int <==> 32 bits) + 4) make sure that "8-byte doubles" turned OFF + (so double == long double) + 5) turn "Native floating-point format" ON + + (Note: the THINK C compiler, quite correctly, insists + that pointer types agree exactly. + This means that the function "px_sign" in the file + "pxop.c" will not compile unless the line + numtransp = myqsort(px2->pe, px2->size); + is replaced with + numtransp = myqsort( (int *) px2->pe, px2->size ); + since the field "pe" is a pointer to type u_int, not + an int, which the function "myqsort" expects. + I made this change.) + [D.Stewart: This change will be made to the next + distribution of Meschach.] + +You should then be able to simply add this project to any of your own +projects so that it functions as a library. The original "machine.h" +file may be found in the folder "origStuff" along with the *.shar +files. + + + -- Brent Boyer + 6/7/95 + +[Note: The file MACHINES/ThinkC/totalMacSetup.hqx has been moved to the +top directory, and is not automatically part of the main distribution. +The reason for this is the amount of space it takes up. + + -- David Stewart, 8th Sept., 1995.] diff --git a/MACHINES/ThinkC/TC-README b/MACHINES/ThinkC/TC-README new file mode 100644 index 0000000..42e784f --- /dev/null +++ b/MACHINES/ThinkC/TC-README @@ -0,0 +1,184 @@ +From boyer@jumpjibe.stanford.edu Fri Jun 9 03:54:33 1995 +Received: from jumpjibe.stanford.edu (jumpjibe.Stanford.EDU [36.4.0.23]) by gluttony.isc.tamu.edu (8.6.11/8.6.11) with ESMTP id DAA18702 for ; Fri, 9 Jun 1995 03:54:31 -0500 +Received: (from boyer@localhost) by jumpjibe.stanford.edu (8.6.10/8.6.10) id BAA13677 for des@isc.tamu.edu; Fri, 9 Jun 1995 01:54:48 -0700 +Message-Id: <199506090854.BAA13677@jumpjibe.stanford.edu> +From: boyer@jumpjibe.stanford.edu (Brent Boyer) +Date: Fri, 9 Jun 1995 01:54:48 PDT +In-Reply-To: David Stewart + "Re: Meschach setup question" (Jun 8, 19:07) +X-Mailer: Mail User's Shell (7.2.0 10/31/90) +To: David Stewart +Subject: second additional message +Content-Length: 6352 +X-Lines: 168 +Status: RO + +dave, + + below is the text for a file I call "Mac/TC README" which +explains everything I did to get it running. + + -brent + + + + + +/* + + + + +Introduction -- Brent Boyer 6/7/95 +_____________________ + + +I have found a procedure which gets the Meschach routines to work on a Macintosh with THINK C 7.0.4. +My system is a Quadra 650 running MacOS 7.5.1. The compile options described below should work for +any 68K Mac with a floating point unit; they probably have to be modified for Power Macs +(in particular, check the floating point type mapping and precision). + + (Note: THINK C is now on version 8.x, perhaps they have fixed some of the terrible features of + the 7.x release; Metrowerk's CodeWarrior is supposed to be a better development environment + and it allegedly can easily translate THINK C projects) + + + + +Procedure +_____________________ + + +Note: all projects described here should have the folowing options made under "Set Project Type..." +(which is found under the "Project" menu): + 1) "Application" type + 2) "Far CODE" and "Far DATA" checked + 3) Partition should be raised from 384 to 4000 (required to get all the *tort*.c projects to run) + 4) Under "SIZE Flags", you can set "32-Bit Compatible" but leave the rest unchecked + + +Step #1 +_________ + + Create an appropriate version of THINK's ANSI library. + + -- first, you will have to modify two of Symantecs "Standard Library" files to let the + function "isascii" become available (this function is required in "err.c") + + 1) in THINK's file "ctype.h" add this code in the appropriate places: + a) int isascii(int); + b) #define isascii(c) ((unsigned)(c)<=0177) + + 2) in THINK's file "ctype.c" add this code: + a) int + (isascii)(int c) + { + return (isascii(c)); + } + + What I next did was copy their project "ANSI" to one I called "ANSI (for Meschach)". I then selected + these compiler ("THINK C...") options before bringing the project up to date: + + -- first, under "Language Settings" + 1) choose "Factory Settings" + 2) also change "Infer prototypes" to "Require prototypes" + (as a former Pascal programmer, I curse the person who introduced infered prototypes!) + + (Note: you _cannot_ choose "ANSI Settings"; if you do, then the compilation of the ANSI project + will fail! Talk to the people at Symantec about this one ...) + + -- then, under "Compiler Settings" + 1) turn "Generate 68020 instructions" ON + 2) turn "Generate 68881 instructions" ON + 3) turn "4-byte ints" ON (so int == long int <==> 32 bits) + 4) make sure that "8-byte doubles" turned OFF (so double == long double) + 5) turn "Native floating-point format" ON + + (The other options probably do not matter either way) + + (Note: 2) and 5) ==> type double will be the 96 bit MC68881 floating point extended precision type; + these options give the best speed and good accuracy too) + + (Also: this 96 bit floating point type will cause the test in "memtort.c" to wrongly report that + 756 blocks were allocated when only 516 should have been) + + -- optionally, under "Code Optimization" + 1) turn "Use Global Optimizer" ON + + +Step #2 +_________ + + Next create an appropriate version of THINK's UNIX library. What I did was copy their project + "unix" to one I called "unix (for Meschach)". Build this project with the same "Language Settings" + and "Compiler Settings" options described in Step #1. + + +Step #3 +_________ + + Correct some errors in the "Meschach" source code files: + + 1) the function "Mmmtr" in the file "extras.c" has an error in the line + Mmv(n,p,alpha,&(A[i][Aj0]),B,Bj0,&(C[i][Cj0])); + the correct line should read + Mmv(n,p,alpha,B,Bj0,&(A[i][Aj0]),1.0,&(C[i][Cj0])); + 2) the function "px_sign" in the file "pxop.c" will not compile unless the line + numtransp = myqsort(px2->pe, px2->size); + is replaced with + numtransp = myqsort( (int *) px2->pe, px2->size ); + 3) the function "chk_col_access" in the file "sptort.c" conflicts with the same named function + in the file "spbkp.c". This causes a link error. To solve this problem, I suggest renaming it as + chk_col_access -> chk_col_accessSPT + + (Dave Stewart tells me that these errors are corrected (along with other stuff?) in a + to-be-released version of "Meschach".) + + +Step #4 +_________ + + Ideally, you would next create a single large library containing all the Meschach routines. Unfortunately, + you cannot do this because THINK C requires libraries to either be, or be built from, single segment projects, + and individual segments can only have 32K of compiled code size, which is way too small for all the + Meschach routines. + + Instead, what I had to do was create 7 smaller, single segment projects. I added code to the segments + strictly in alphabetical order, with no regard to partitioning (i.e. putting similar routines together). + + To make each such project, I first opened a new project ("ANSI Project" type) and then added alot of + source code files. I then selected these compiler ("THINK C...") options before bringing the project + up to date: + + -- first, under "Language Settings" + 1) choose "ANSI Settings" (tragically, will have to leave "Infer prototypes" on) + + -- next, under "Compiler Settings", make the same choices as when compiled "ANSI (for Meschach)" + 1) turn "Generate 68020 instructions" ON + 2) turn "Generate 68881 instructions" ON + 3) turn "4-byte ints" ON (so int == long int <==> 32 bits) + 4) make sure that "8-byte doubles" turned OFF (so double == long double) + 5) turn "Native floating-point format" ON + + If the resulting single segment was over 32K, I removed files from the bottom of the list until the segment + had < 32K left. The file "main.c" which was automatically generated was also removed. + + + Note: I never added the *tort*.c files or any of the other files with a main routine (e.g. "maxint.c") + in them to these projects. The *tort*.c files were made into separate projects. In order to + echo the screen output to a file when running the torture tests, you need to add these lines + to each *tort*.c file: + a) #include (put near top) + b) cecho2file("filename", 0, stdout); (put inside main) + + + + +You should then be able to simply add all these projects to any of your own projects -- this will give you the +whole library. + + + + +*/ + diff --git a/MACHINES/ThinkC/TC-machine-2.h b/MACHINES/ThinkC/TC-machine-2.h new file mode 100644 index 0000000..4057f2e --- /dev/null +++ b/MACHINES/ThinkC/TC-machine-2.h @@ -0,0 +1,385 @@ +From boyer@jumpjibe.stanford.edu Fri Jun 9 14:17:09 1995 +Received: from jumpjibe.stanford.edu (jumpjibe.Stanford.EDU [36.4.0.23]) by gluttony.isc.tamu.edu (8.6.11/8.6.11) with ESMTP id OAA24615 for ; Fri, 9 Jun 1995 14:17:07 -0500 +Received: (from boyer@localhost) by jumpjibe.stanford.edu (8.6.10/8.6.10) id MAA15164 for des@isc.tamu.edu; Fri, 9 Jun 1995 12:17:24 -0700 +Message-Id: <199506091917.MAA15164@jumpjibe.stanford.edu> +From: boyer@jumpjibe.stanford.edu (Brent Boyer) +Date: Fri, 9 Jun 1995 12:17:24 PDT +In-Reply-To: David Stewart + "Re: Meschach setup question" (Jun 8, 19:07) +X-Mailer: Mail User's Shell (7.2.0 10/31/90) +To: David Stewart +Subject: Re: Meschach setup question +Content-Length: 9498 +X-Lines: 369 +Status: RO + +david, + + did this file get thru to you last nite? (someone else told +me that i sent it them instead; maybe i accidentally cced it to them). + + -brent + +below is the new machine.h file for Macs: + + + + + +/* ================================================================================ */ + + +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + + +/* ================================================================================ */ + + +/* #undef const */ /* leave this commented out -- THINK C has no keyword named "const" */ + +/* #undef MALLOCDECL */ /* leave this commented out -- THINK C doesn't supply */ + +#define NOT_SEGMENTED 1 /* this must #defined -- Mac's don't have segmented memory */ + +#undef HAVE_MEMORY_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_COMPLEX_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_MALLOC_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#define STDC_HEADERS 1 /* this must be #defined -- it will cause precisely two effects below: + 1) the macros MEM_COPY(...) & MEM_ZERO(...) will be correctly + defined using memmove(...) & memset(...) + 2) the macro ANSI_C will be #defined */ + +#undef HAVE_BCOPY /* make sure this is #undefined -- bcopy is for a BSD system? */ + +#undef HAVE_BZERO /* make sure this is #undefined -- bzero is for a BSD system? */ + +/* #undef CHAR0ISDBL0 1 */ /* for safety, this should be commented out (Dave Stewart's advice) */ + +#define WORDS_BIGENDIAN 1 /* 68K Macs use big endian microprocessors */ + +#undef U_INT_DEF /* make sure this is #undefined (Dave Stewart's advice) */ + +#define VARARGS 1 /* this must be #defined (Dave Stewart's advice) */ + + +/* ================================================================================ */ + + +/* for prototypes */ + +#define HAVE_PROTOTYPES 1 /* this must be #defined (Dave Stewart's advice) */ + +#define HAVE_PROTOTYPES_IN_STRUCT 1 /* this must be #defined (Dave Stewart's advice) */ + + /* for inclusion into C++ files */ +#ifdef __cplusplus /* (Note: THINK C must #define this somewhere, since it is used in "ctype.h") */ +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + + /* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT + /* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + + + +/* ================================================================================ */ + + +/* for basic or larger versions */ + +#define COMPLEX 1 /* this must be #defined (I want all the complex routines) */ +#define SPARSE 1 /* this must be #defined (I want all the sparse routines) */ + + +/* ================================================================================ */ + + +/* for loop unrolling */ + +/* #undef VUNROLL */ +/* #undef MUNROLL */ + + +/* ================================================================================ */ + + +/* for segmented memory */ + +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + + +/* ================================================================================ */ + + +/* if the system has malloc.h */ + +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + + +/* ================================================================================ */ + + +/* any compiler should have this header */ +/* if not, change it */ + +#include + + +/* ================================================================================ */ + + +/* Check for ANSI C memmove and memset */ + +#ifdef STDC_HEADERS + + /* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + + +/* ================================================================================ */ + + +/* standard headers */ + +#ifdef ANSI_C +#include +#include +#include +#include +#include /* #include so that the macro HUGE_VAL will be available to us */ +#endif + + +/* ================================================================================ */ + + +/* if have bcopy & bzero and no alternatives yet known, use them */ + +#ifdef HAVE_BCOPY +#ifndef MEM_COPY + /* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO + /* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + + +/* ================================================================================ */ + + +/* if the system has complex.h */ + +#ifdef HAVE_COMPLEX_H +#include +#endif + + +/* ================================================================================ */ + + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ + +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + + +/* ================================================================================ */ + + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ /* leave these both commented out, so that the dafault of double is used */ + +/* choose double precision by default */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 /* this is what we want: all reals to be of type double */ +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* Note: under THINK C, the type "double" gets mapped to the type "long double" as long as you DO NOT turn on + the "8-byte doubles" option. + + Recall: this project was compiled with the "8-byte doubles" option turned OFF (so double == long double) + + Also Recall: this project was compiled with the "Generate 68881 instructions" and "Native floating-point format" + options turned ON; this means that double will be a 96 bit MC68881 floating point extended + precision type; these options give the best speed. + + (See the THINK C 6.0 User's Guide, pp. 313-317) + + --Brent Boyer 6/7/95 */ + + +/* ================================================================================ */ + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ + +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + + +/* Note: the extended precision floating point type we are using actually has DBL_EPSILON = 1.08420E-19 + (THINK C 6.0 User's Guide, p. 317); out of caution, I will let the above value for D_MACHEPS + stay the same. + + --Brent Boyer 6/7/95 */ + + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + + +/* ================================================================================ */ + + +#define M_MAX_INT 2147483647 /* this value only works if ints are 32 bits */ + + +/* Recall: this project was compiled with the "4-byte ints" option turned ON (so int == long int <==> 32 bits); + if you do not turn this option on, then ints will be 16 bits so that you will need to do + #define M_MAX_INT 32767 instead + + --Brent Boyer 6/7/95 */ + + +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + + +/* ================================================================================ */ + + +/* for non-ANSI systems */ + + /* we #included above precisely so that HUGE_VAL will be #defined here */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL /* actually, since HUGE is used in several Meschach routines, you need this + line to be executed even on ANSI systems */ +#endif +#endif + + +/* ================================================================================ */ + + +#ifdef ANSI_C +extern int isatty(int); +#endif + + diff --git a/MACHINES/ThinkC/TC-machine.h b/MACHINES/ThinkC/TC-machine.h new file mode 100644 index 0000000..3fbcbad --- /dev/null +++ b/MACHINES/ThinkC/TC-machine.h @@ -0,0 +1,382 @@ +From boyer@jumpjibe.stanford.edu Fri Jun 9 03:51:40 1995 +Received: from jumpjibe.stanford.edu (jumpjibe.Stanford.EDU [36.4.0.23]) by gluttony.isc.tamu.edu (8.6.11/8.6.11) with ESMTP id DAA18674 for ; Fri, 9 Jun 1995 03:51:38 -0500 +Received: (from boyer@localhost) by jumpjibe.stanford.edu (8.6.10/8.6.10) id BAA13657; Fri, 9 Jun 1995 01:51:54 -0700 +Message-Id: <199506090851.BAA13657@jumpjibe.stanford.edu> +From: boyer@jumpjibe.stanford.edu (Brent Boyer) +Date: Fri, 9 Jun 1995 01:51:54 PDT +In-Reply-To: David Stewart + "Re: Meschach setup question" (Jun 8, 19:07) +X-Mailer: Mail User's Shell (7.2.0 10/31/90) +To: David Stewart +Subject: Re: Meschach setup question +Cc: new@jumpjibe.stanford.edu, machine.h@jumpjibe.stanford.edu, + file@jumpjibe.stanford.edu +Content-Length: 9353 +X-Lines: 364 +Status: RO + +Dave, + + below is the new machine.h file. + + -brent + + + +/* ================================================================================ */ + + +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + + +/* ================================================================================ */ + + +/* #undef const */ /* leave this commented out -- THINK C has no keyword named "const" */ + +/* #undef MALLOCDECL */ /* leave this commented out -- THINK C doesn't supply */ + +#define NOT_SEGMENTED 1 /* this must #defined -- Mac's don't have segmented memory */ + +#undef HAVE_MEMORY_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_COMPLEX_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_MALLOC_H /* make sure this is #undefined -- THINK C doesn't supply */ + +#define STDC_HEADERS 1 /* this must be #defined -- it will cause precisely two effects below: + 1) the macros MEM_COPY(...) & MEM_ZERO(...) will be correctly + defined using memmove(...) & memset(...) + 2) the macro ANSI_C will be #defined */ + +#undef HAVE_BCOPY /* make sure this is #undefined -- bcopy is for a BSD system? */ + +#undef HAVE_BZERO /* make sure this is #undefined -- bzero is for a BSD system? */ + +/* #undef CHAR0ISDBL0 1 */ /* for safety, this should be commented out (Dave Stewart's advice) */ + +#define WORDS_BIGENDIAN 1 /* 68K Macs use big endian microprocessors */ + +#undef U_INT_DEF /* make sure this is #undefined (Dave Stewart's advice) */ + +#define VARARGS 1 /* this must be #defined (Dave Stewart's advice) */ + + +/* ================================================================================ */ + + +/* for prototypes */ + +#define HAVE_PROTOTYPES 1 /* this must be #defined (Dave Stewart's advice) */ + +#define HAVE_PROTOTYPES_IN_STRUCT 1 /* this must be #defined (Dave Stewart's advice) */ + + /* for inclusion into C++ files */ +#ifdef __cplusplus /* (Note: THINK C must #define this somewhere, since it is used in "ctype.h") */ +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + + /* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT + /* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + + + +/* ================================================================================ */ + + +/* for basic or larger versions */ + +#define COMPLEX 1 /* this must be #defined (I want all the complex routines) */ +#define SPARSE 1 /* this must be #defined (I want all the sparse routines) */ + + +/* ================================================================================ */ + + +/* for loop unrolling */ + +/* #undef VUNROLL */ +/* #undef MUNROLL */ + + +/* ================================================================================ */ + + +/* for segmented memory */ + +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + + +/* ================================================================================ */ + + +/* if the system has malloc.h */ + +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + + +/* ================================================================================ */ + + +/* any compiler should have this header */ +/* if not, change it */ + +#include + + +/* ================================================================================ */ + + +/* Check for ANSI C memmove and memset */ + +#ifdef STDC_HEADERS + + /* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + + +/* ================================================================================ */ + + +/* standard headers */ + +#ifdef ANSI_C +#include +#include +#include +#include +#include /* #include so that the macro HUGE_VAL will be available to us */ +#endif + + +/* ================================================================================ */ + + +/* if have bcopy & bzero and no alternatives yet known, use them */ + +#ifdef HAVE_BCOPY +#ifndef MEM_COPY + /* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO + /* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + + +/* ================================================================================ */ + + +/* if the system has complex.h */ + +#ifdef HAVE_COMPLEX_H +#include +#endif + + +/* ================================================================================ */ + + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ + +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + + +/* ================================================================================ */ + + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ /* leave these both commented out, so that the dafault of double is used */ + +/* choose double precision by default */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 /* this is what we want: all reals to be of type double */ +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* Note: under THINK C, the type "double" gets mapped to the type "long double" as long as you DO NOT turn on + the "8-byte doubles" option. + + Recall: this project was compiled with the "8-byte doubles" option turned OFF (so double == long double) + + Also Recall: this project was compiled with the "Generate 68881 instructions" and "Native floating-point format" + options turned ON; this means that double will be a 96 bit MC68881 floating point extended + precision type; these options give the best speed. + + (See the THINK C 6.0 User's Guide, pp. 313-317) + + --Brent Boyer 6/7/95 */ + + +/* ================================================================================ */ + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ + +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + + +/* Note: the extended precision floating point type we are using actually has DBL_EPSILON = 1.08420E-19 + (THINK C 6.0 User's Guide, p. 317); out of caution, I will let the above value for D_MACHEPS + stay the same. + + --Brent Boyer 6/7/95 */ + + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + + +/* ================================================================================ */ + + +#define M_MAX_INT 2147483647 /* this value only works if ints are 32 bits */ + + +/* Recall: this project was compiled with the "4-byte ints" option turned ON (so int == long int <==> 32 bits); + if you do not turn this option on, then ints will be 16 bits so that you will need to do + #define M_MAX_INT 32767 instead + + --Brent Boyer 6/7/95 */ + + +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + + +/* ================================================================================ */ + + +/* for non-ANSI systems */ + + /* we #included above precisely so that HUGE_VAL will be #defined here */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL /* actually, since HUGE is used in several Meschach routines, you need this + line to be executed even on ANSI systems */ +#endif +#endif + + +/* ================================================================================ */ + + +#ifdef ANSI_C +extern int isatty(int); +#endif + + diff --git a/MACHINES/ThinkC/machine.h b/MACHINES/ThinkC/machine.h new file mode 100644 index 0000000..60879d9 --- /dev/null +++ b/MACHINES/ThinkC/machine.h @@ -0,0 +1,402 @@ +/* + This file was written by Brent Boyer (boyer@jumpjibe.stanford.edu), + June 7th, 1995 for compiling Meschach under Think C 7.0.4. + His development systems was a Quadra 650 running MacOS 7.5.1 using + a 68x00 CPU with a 68881 FPU. Power Macs will probably require + modification. + + For details on how to build the library, see the associated README file. +*/ + + +/* Begin stuff from the original Meschach file: */ + + +/* ======================================================================== */ + + +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + + +/* ======================================================================== */ + + +/* #undef const */ + /* leave this commented out -- THINK C has no keyword named "const" */ + +/* #undef MALLOCDECL */ + /* leave this commented out -- THINK C doesn't supply */ + +#define NOT_SEGMENTED 1 + /* this must #defined -- Mac's don't have segmented memory */ + +#undef HAVE_MEMORY_H + /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_COMPLEX_H + /* make sure this is #undefined -- THINK C doesn't supply */ + +#undef HAVE_MALLOC_H + /* make sure this is #undefined -- THINK C doesn't supply */ + +#define STDC_HEADERS 1 + /* this must be #defined -- it will cause precisely two effects below: + 1) the macros MEM_COPY(...) & MEM_ZERO(...) will be correctly + defined using memmove(...) & memset(...) + 2) the macro ANSI_C will be #defined */ + +#undef HAVE_BCOPY + /* make sure this is #undefined -- bcopy is for a BSD system? */ + +#undef HAVE_BZERO + /* make sure this is #undefined -- bzero is for a BSD system? */ + +/* #undef CHAR0ISDBL0 1 */ + /* for safety, this should be commented out (Dave Stewart's advice) */ + +/* #define WORDS_BIGENDIAN 1 */ + /* what's this for? it doesn't appear to ever be used; + I will comment it out */ + +#undef U_INT_DEF + /* make sure this is #undefined (Dave Stewart's advice) */ + +/* #define VARARGS 1 */ + /* Don't need routines with variable number of arguments */ + + +/* ======================================================================= */ + + +/* for prototypes */ + +#define HAVE_PROTOTYPES 1 + /* this must be #defined (Dave Stewart's advice) */ + +#define HAVE_PROTOTYPES_IN_STRUCT 1 + /* this must be #defined (Dave Stewart's advice) */ + + /* for inclusion into C++ files */ +#ifdef __cplusplus +/* (Note: I do not believe that THINK C ever #defines this) */ +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + + /* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT + /* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + + + +/* ======================================================================== */ + + +/* for basic or larger versions */ + +#define COMPLEX 1 + /* this must be #defined (I want all the complex routines) */ +#define SPARSE 1 + /* this must be #defined (I want all the sparse routines) */ + + +/* ======================================================================== */ + + +/* for loop unrolling */ + +/* #undef VUNROLL */ +/* #undef MUNROLL */ + + +/* ======================================================================== */ + + +/* for segmented memory */ + +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + + +/* ======================================================================== */ + + +/* if the system has malloc.h */ + +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + + +/* ======================================================================== */ + + +/* any compiler should have this header */ +/* if not, change it */ + +#include + + +/* ======================================================================== */ + + +/* Check for ANSI C memmove and memset */ + +#ifdef STDC_HEADERS + + /* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + + +/* ======================================================================== */ + + +/* standard headers */ + +#ifdef ANSI_C +#include +#include +#include +#include +#include +/* #include so that the macro HUGE_VAL will be available to us */ +#endif + + +/* ======================================================================== */ + + +/* if have bcopy & bzero and no alternatives yet known, use them */ + +#ifdef HAVE_BCOPY +#ifndef MEM_COPY + /* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO + /* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + + +/* ======================================================================== */ + + +/* if the system has complex.h */ + +#ifdef HAVE_COMPLEX_H +#include +#endif + + +/* ======================================================================== */ + + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ + +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + + +/* ======================================================================== */ + + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ +/* leave these both commented out, so that the dafault of double is used */ + +/* choose double precision by default */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 + /* this is what we want: all reals to be of type double */ +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* Note: under THINK C, the type "double" gets mapped to the type + "long double" as long as you DO NOT turn on the "8-byte doubles" + option. + + Recall: this project was compiled with the "8-byte doubles" + option turned OFF (so double == long double) + + Also Recall: this project was compiled with the "Generate 68881 + instructions" and "Native floating-point format" options turned ON; + this means that double will be a 96 bit MC68881 floating point + extended precision type; these options give the best speed. + + (See the THINK C 6.0 User's Guide, pp. 313-317) + + --Brent Boyer 6/7/95 */ + + +/* ======================================================================== */ + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ + +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + + +/* Note: the extended precision floating point type we are using actually has DBL_EPSILON = 1.08420E-19 + (THINK C 6.0 User's Guide, p. 317); out of caution, I will let the above value for D_MACHEPS + stay the same. + + --Brent Boyer 6/7/95 */ + + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + + +/* ======================================================================== */ + + +#define M_MAX_INT 2147483647 + /* this value only works if ints are 32 bits */ + + +/* Recall: this project was compiled with the "4-byte ints" option + turned ON (so int == long int <==> 32 bits); if you do not turn + this option on, then ints will be 16 bits so that you will need to + do + #define M_MAX_INT 32767 + instead + --Brent Boyer 6/7/95 */ + + +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + + +/* ======================================================================== */ + + +/* for non-ANSI systems */ + +/* we #included above precisely so that HUGE_VAL will be + #defined here */ + +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL +/* actually, since HUGE is used in several Meschach routines, you need */ +/* this line to be executed even on ANSI systems */ +#endif +#endif + + +/* ======================================================================== */ + + +#ifdef ANSI_C +extern int isatty(int); +#endif + + diff --git a/MACHINES/TurboC/README b/MACHINES/TurboC/README new file mode 100644 index 0000000..8f6ace8 --- /dev/null +++ b/MACHINES/TurboC/README @@ -0,0 +1,25 @@ +This directory contains a makefile for Borland C++. +It was written by Andrew Gockel (contact information below). +Use at own risk. This is provided as part of the standard Meschach +distribution to give the library the widest possible use. +However, problems with the makefile should be directed to the author, +not the developers of Meschach (David Stewart and Zbigniew Leyk). + +No representations are made concerning the fitness of this software for any +particular purpose. + +# Borland C++ V4 Makefile +# +# Saturday, 14 October, 1995 +# +# Andrew Gockel +# 123 Settlement Road +# THE GAP, QLD., 4061 +# AUSTRALIA +# +# Email +# INTERNET:andrew@kittyhawk.aero.rmit.edu.au +# CIS:100245.1253@compuserve.com +# MSN:Andrew_Gockel@msn.com +# +# c:\meschach\meschach.mak diff --git a/MACHINES/TurboC/filelist b/MACHINES/TurboC/filelist new file mode 100644 index 0000000..10bd8ee --- /dev/null +++ b/MACHINES/TurboC/filelist @@ -0,0 +1,5 @@ +README +filelist +machine.h +mail +meschach.mak diff --git a/MACHINES/TurboC/machine.h b/MACHINES/TurboC/machine.h new file mode 100644 index 0000000..8db69f2 --- /dev/null +++ b/MACHINES/TurboC/machine.h @@ -0,0 +1,247 @@ +/* machine.h. Generated by Totte Karlsson, April, 1995 for Borland C/C++. */ +/* See README file in this directory for more details */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.3 1995/03/27 15:36:21 des Exp $ */ + +/* This is for use with Borland (Turbo) C/C++ */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ +/******************************************** +............................................. +........ From Totte Karlsson ......... +........ Physical Chemistry, ......... +........ Arrhenius Laboratory, ......... +........ Stockholm University, ......... +........ S10691 Stockholm Sweden ......... +........ email : torgny@physc.su.se ......... +........ Phone:+46-8-16 23 74 ......... +........ Fax: +46-8-15 2187 ......... +............................................. +********************************************/ + +#ifndef _MACHINE_H +#define _MACHINE_H 1 + +/* #undef const */ + +/* #undef MALLOCDECL */ +/*#define NOT_SEGMENTED 1*/ +#define HAVE_MEMORY_H 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +#define U_INT_DEF 1 +#define VARARGS 1 +#define HAVE_PROTOTYPES 1 +#define HAVE_PROTOTYPES_IN_STRUCT 1 + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL +#endif +#endif + + +#ifdef ANSI_C +extern int isatty(int); +/* tk changing */ +#define fileno(f) ((f)->fd) +#define _fileno(f) fileno(f) + +#endif + +#endif + + + diff --git a/MACHINES/TurboC/mail b/MACHINES/TurboC/mail new file mode 100644 index 0000000..c78ed55 --- /dev/null +++ b/MACHINES/TurboC/mail @@ -0,0 +1,1974 @@ +From andrew@kittyhawk.aero.rmit.edu.au Sat Oct 14 21:46:38 1995 +Received: from kittyhawk.aero.rmit.edu.au (kittyhawk.aero.rmit.EDU.AU [131.170.71.222]) by gluttony.isc.tamu.edu (8.6.11/8.6.11) with ESMTP id VAA22854 for ; Sat, 14 Oct 1995 21:43:47 -0500 +Received: (from andrew@localhost) by kittyhawk.aero.rmit.edu.au (8.6.12/8.6.12) id NAA17054 for des@isc.tamu.edu; Sun, 15 Oct 1995 13:43:15 +1100 +From: Andrew Gockel +Message-Id: <199510150243.NAA17054@kittyhawk.aero.rmit.edu.au> +Subject: Meschach online manual for DOS/Windows +To: des@isc.tamu.edu (David Stewart) +Date: Sun, 15 Oct 1995 12:43:15 +1000 (EST) +X-Mailer: ELM [version 2.4 PL21] +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Status: RO +X-Lines: 1957 +Content-Type: text/plain; charset="US-ASCII"; conversions="7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit, 7bit" +Content-Length: 120396 + +David, + +As you may or may not be aware, their is a strike at ANU and mail is +being affected. I have had to use the online manual while awaiting a copy +of the manual. + +To get this working under dos/windows, I have had to shorten the file +names eg manual_0.html -> man_0.htm, and changed the extensions of some +files so the default viewer is automatically launched. Most windows based +programs have a text viewer, expecting a .txt file, so I have renamed +some files eq FAQ.meschach to meschfaq.txt. I have made items unavailable +in the page in italics, and included a link to the page on thrain. + +I have included a zip file that has all this in it, others may find it +useful. I could not include errata.html as the permission mode on the +file only allows root to read it. Also not all files in the manual.html +files are in the html_manual directory. What is the differance between +manual-27.html and manual_27.html ? + + +Cheers + +Andrew Gockel + +The meschman.zip was created with winzip 5.6 (available on archie.au) and +the uuencoded. + + +begin 644 meschman.zip +M4$L#!!0``@`(`)=:3Q\F`Z\.VS8``)ND```<````34530TA!0T@O34%.54%, +M+U155$]224%,+DA43;NBBS9/GD(;\Q3Q:#<_<0?ACS-IW669%7)^;)9@DMEMEY +M]"2)%F4Z/[OWY22ILNFX6%?WSK]/ZB2JZG(SK3=E6D5)/HNJ8I5&U,84Z[1, +MJ*0G=O*NR_%+;5M$<^L*W553,(VBQ +M6:5YW3KY99I`)]5O]\Y'$?T[JG[;)`B#=5E,ENFJ[:-JG915.DXO\2O^`4NN +MRVP;I=L$%]3VU:*X'M<%PVA61,^C/OSY#V[Y$/?'/,^C>I%5$6SQND[+&'[) +M%D2SY@Z5:93E=5G,-M-T%ML=,[!@_`H`KY\ZH/)7R^4&.DKJ=-8W%XLTYYV6 +MB1/$%KR+&U@6]C7;Q0X#T(%QZ2>TK(KE5\C*[2G,:+)IG)UU$!_^CU9BE`?P68 +M-#-IV"ML3SFSTW>@K!1F#(E$UP][=`5/$#D93PSAR33E_BH/[JXS`CH"'[9" +MF\>*8/,$*26K=$=AC:;2(6ZJ&F$.WRUA]DD9-:9O!YL!'RFS20H`"G&.400; +M('4YWUC_FN1+04_J+,UP1*&3H$_14FU!I*.!!MY8K@9 +MDS)+YS3K>5*:>5FLHFFQ6I(FRSJMK@K@&?'9X#4>?)*CV[Y_'0BW9*\?AH%/)18-)#('I&JS)%%@(3 +M:R/T>E%4"N8)3H;9I2+%5&D2D'93>_L-'RT20,=)"E0."#5#B$[+%'&L.0YB +M/U/@-JH3P-UD0P^-8)(`%ZCBDKD-]7>=`;6V=N5Q19Q?6D]A2HZG"$:4Z3*# +MP6[BZ*;8X&9OEK,H65XG-Q4U?9*=KPO@&19WBLA4F=LX`ZZMLAOS9 +M_`"3$:J-O=U+E!T`@$8$&:`&&(D@=A1MHV-\"!LEJ&+@\5;:F5FV0F*#&0X. +M>2^!7SG<(:`'?6(SG>2\6"Z+:T3":3%+0;,`VCTW7PK]1/=X7OW%/=,/_AC$ +M[D[7_&XB_//3Z`+^>S`ZY9^_/'N*/[?R\]6S-S_!S[7\]'JAWZ/H+%J-+].Z +MT=49=XM\Q/?N% +MGVWY&?$0?/SJ'_Q\+<]AX8(72!/`-Y'D@5&#I= +M5FD_8N'#,J6R,B($KJXAF2*)0N^SK(118<@-*78+Y!*.&"RN*:6>.T6&Y6>>4OTOC; +M&NO\@3=P9UDE8E=Y!7^Z%;Z"@@U9`S^U&"LKQ%>ZP)<%:33`ZPB)\UFZE97" +MAXCY*`02G`9U\A&4(!#QV/A&2`7505+XS-,8Q&FC,YIY)I/.6_8!\:I,0)6, +M2-TX1(VAL5J826^`PQ.J;GCI=5$#EW;`!"0!Y85-"B5J@!*@%NU4HTO<6E61 +M$)V6@&78O-K,Y]DT0XRK22Z!:I)8Z0HCB<#*;U#@`QK,G/G%XE:$/^V!E:\D +M7(`JH0'T`:HO\"8:1*29<2/$48X48:FK=WTS`DY4+)TH7V"MD3,41\ +M&.`_/I!Q5>W9,$=.E\O*%]O$;0DRQ@IIG3!:%IMZO:F)7V\JUG)Q1)X/#SG? +MY%/99A`*S4Y83UTP:4150K;6OU(##YQH05DNJH[E;$QL:`DL67\JJM2GYKYY +M/J>YR#1PB&0)H\]N>-]Y)B3,P +M0KY"9$K]=GE#0:!QE]C#=5F@]*#OO=%(B^.];1TLZM!@^P;J>TP0<4&WR.E2 +MNO6"&8PLT56RW*0\/LBR'.W\%.C:B`RFJ8`E4N0]1E-J+@@B7:CSHR\:CF`/ +MD-8L`4LVF99%Q<^00DM+]8"HH]DL(Z46"&I2D[TD2FT%J`XFP6JSK#/U&2@E +MBQ1'[-O4+#Z1,$AU:BKG)T("R6R&Z!##8U\]N1K#P(T7A''5U7BUK#M5O'5O +M@#[2,O6@;@7DC9..64Y@Y:F:CK->ZINU<`!01`\4/?`!#!`P!-T:)LH.;KFQ +M772-#EK9CQ)@YYL).3O2:4:B5&1*)QR:FRG&7-!R2'*`R`,]"60U6@T`6#`! +M61P('&/A#0+S"I5]>'-V-1X\J(`TA\P;<_*QY)=+R[)8I2!@XA9<#>*K85PY +MF#JD`>($[@YL+]W6)7!STLK2^68I9@W/DIQ.3K``ON>>\L98TQ/("?+0/#4NZBF2A.C59:/L:7C24)%M(T@F+RN +M?&ZH:ML-LT9'N+#R%/2-F;>/*5(<;X7`Z'(#TP4!2;8;^Z&4U$B@+9?I%B2P1X$'8YZCSV6^;#(8GS=49J@(2>`!\9H6&0&[E*N_V +MBJAM%'\7/[6$@\BCP(&E/ST;/?C.Z7F$SBNAN%'XF0D^JT8,-.L*0=QFI1,5 +M58^TOPM)]*DC4>2-9*^`@7@@7Y!E9&@7I"]'7FWD$Y'&`A`(+3-BDB@[6%#3 +M*%;@XW[])#B)&.M[5IK,;8:ZW.3&T9.5W-BUP)EYU"C@41ZTD$!'$:.<6'Y( +MBZO=KTSSJ_<7HH47Y.`3-"`EGEJ\OSC;OK\8-1&X5HZ2HWU1`8'QG"=I?8UB +MOD1-U-H*=LV;?)E]2LTT+6OT3Y$S)B&S`43&508"DZVZ:D-N/[3L7XR^P[G! +MOYZ.7CP%R+[R/%/.R`%@.F\(T+EU%ZZ3Z:?D$C;OEQ#N;/B24!&^0O;&=@QS +M[:P!9NOQ5@5(B^EC?:^?[0\_A@Y'T.'(%SSP"KKC5Z/Q6L?"87SGF_8O/"Y+ +M9]R]]H%;O![$ZV&\'HS70V=^HX\)X*SM=3KP%(9`^SP[(.](A8->K39'_A$0>+`G"T;<'8\G0XI4G2:H^.'(QUN+8OAFK>B% +M&CAHEAM@QL7D(VX#X-8ZJ<2'C-8I;U.E2I4.'Q,')^Y/9LPD-<4$.0=\288; +M&^[XR3Q;6MTEXWE7-5CZ,@>8`K=#+I]\`FC3]TGT*;V9%"A224.78$FIPZ%0 +M7ZUQDSQ5FU6TC*(CZ+I*9Z>D^+?VS_.RG7,CZIV5_\),K,5,*C]B1R)>"_A[ +M+5$YW!U/9700XB7#9BK]<(LF!;,.U#09!H,L!>BUB\TJR<6P +MGB[00$63#CW[?Z/M10OB&K"(HBRI^"I9:A<"A*@@;P+I<8'9P$.967H%[%0W +M3C7EF)G'-`6",K+3#K#X4K[;USM_PXU,B!4Q[13'B-8`YW69H9%LU`9/)@7& +MD-0ER0;G'*>KLP-CD_P#6U+(`"*XD^AT,MR8ER9-Q3L^F^GD)1BA1A9',YV- +MU?36$UQW??4.P,*N/WR8E^D,QY.9&VL:[GC8H[T^]H:+_8?G+YY%T<%@- +MEWOX*3V:H[]\#NIDWKF'$[H7W[N^IV[SU7@N:#<'\==M[<7ZTR]:.(,XNS2\ +M`NT`/%.B).!HK$1DN45#M$#UA3[G#@%1REH<2`G`;I%4"]C6Z2)!Q01VY\.' +M+V7OS+1`Q].&Y1M+A)G2+D:VFGL66.5`2J!;98J1Q$^BHY[UB8+:PEJ2W:3H +M8F&=^Y&U=`!'T#@`KH'R`EIMHS/1;4[0PWH2'9G>-P3/Z)#^>V0#$S@]C5_3 +M-!X*G:O-ER/WD>5EE?"BF('-81J&K0E@B-A7.4)A@PDWM\%LYL'3%?D+-+:( +MTDBCBD"(:(F@C!(&'*TPTG:9(I\-B9CL1<,A=E@5.O,_?*CK&_0#Y=&['$CE +M(]!4D8N'!@GI4[:FX#R)'HA`UX_[]B^S;5# +M$!VASW]3JSM=":5O_,06WUY2%1"9'8B`*DR$PMTH-I4),DLWO=8YQXA%URGH8XC8ZQEJ`$%/?B_1ZS?ARF');S?K=5'6 +MXI@23I9XV_(CP"N%3C`+J09;H&*"TOG_'2._U7W0.NK`$0==CY84H%+?G0T. +MS"T;UV%1'7A-ZH!F]I!X:2XZ-M9!S8HKL#'0_J<9&?P)17Z*>8VNZJKO&7D! +M0":<<+-W'QC\ZOIZ\?V+]Q<4(FP"CJ01FZ9DA*1;`1KL27M8BM&H!:O^Y908 +MP:JY[=NEO7E6!0:G]_4R;'2C\0^<8%O>E+=ARDQ=3Q*,06YALX)((9<)A\'R +M?X6/8?=1L9X5^?U:@N2$821OM3\4:92=&@,MEV-HE"#_0E#.W&!TAP%C.J,DO):.F +MN*&\(^N/H%@BFN9(_2Z[SDN7XU!859B@VP"\F.B75VD4>J2S:2)1#V[[XIUI +MH1Q^9QE-T&)G4[.:Z/[*6Z._@[`?+=#&CSQ02X**X*/J;+K-H2P/4=+NA>_^ +M":`"IA0[/=U$A=6J5\_`''HH=\@_GZ)7+?^XN43."PQ_1NY^_035M7`W4)7G +M2)N?[F3M/6BVJ"PZ=&A=:,AXQO"TJ#J^*P,^#=X#3PQ^+XO+X'?U6UD'#Q+7 +M(^6F=8W0+,`#2).]8;P7.W--411,JV@!*DA:[AIH3[!1?W$>;!WS$W)T@2W` +MD89-75!7%%"VO`$=R]:_$FG&M^'1F)&@VLF?M' +M/@O.<+[,LSD`.J]-LBHVG'6$2R%I!4-+1F6G2FZZNTGQE/T",)`\28R8:S2B +M+@J`4_K;AB(!?9[D2.:#X0R>[V3#IJB;*U$]O$YLFF.-[NO[:*X:L1HBARIA +MSE;?-$\.4!<(P[R(ED5^B=C%:HM,>I)Z"HR_`3&(*-"OUV0C5(@G4VM(2$9_ +M@H8'S*FO.,QS(H,$*`UW55.@.QJ.>)%5ZVX0^\"$%!S>?/APF903))(IF/Q\ +M5@+T>=B2O.CQY'L$`08>`/4A[?^KU\#D_O#!^(A`;XA/X&I6U]JF1)/H9`M!VHI+V\&"\EIFHBC +MFB\=2KVCGK%,]I4!C +MZ>IRG!(\;<[?S=D+4"A,Q6E6IFO*`4%T'P&6`3S3Z2+/@`98UC,.8<8WR*,I +M`J_$O&).+)=I7&85(I5M9"*'=#PI2OD^.G_9!#@\,XVD"MI^XMP>=1')I>BZ +M"(BND5GJ0NV-/8O:]RPJ-Y(.5JW(QPT,/YUEFY4AP.[TWO1R(1B5'A/RA(D8 +M>_V&DFLI16<44WRT>TH^J8<'EGMZN9Y@L$0'#U74>0+"RPF-"0@X6XUC3VV8 +MEU--7[^17"!4#C/-5O$R0M,K1WV&UL) +M((O@S4$N54E(QC$H$T@(V>]K`IPGR/_B'(OI=%-B8A]8Q]D,X<]>ZI)?+XMB +M3=$/$GG7N%55(?$(F?*U;MV'#\NBJH%RT*^26+^T.U>##M!IBKE#$8B;;"E[ +M?XV&8^XERC&%2,1$<90SYK>UZ,M&/3>OWWCN&6I0;285,U`ZL6&/PR17139C +M^U)=Q1M")"^^2\D +MC=H=>6D0I;<*%'@,3SH;0G(%)ZQZ'2ZZ@W[NZ-3[KWK9]Y#+K;0BQ,3TYPYH +M.,0$B*($O,#&'IR#T5*8DU:0GCP*#?'A'*8V] +M(L8JG'XJ!S8JR<*;XF$79O_&685TGH;][HG+E2C(7\2GR%Q>[[5ZS[2=IC_$ +M-FU.5F/3@&V/G+FH4-2\U08-*XXQ?FTR)EK<'9N$AU,3=*XX/#%+F^+'./%# +MW$U/A\R3K.0\*3[0A,VGFZ6HO1WH@T^A)4:-4+'U-2&*PF=ZHBO1@S*(]'J6 +MJRNT]$:%:*1"E(B(5^AD(>?I2DXSZIHR53+$5TT]EJUO7;`A7<(N5"0O&;>4 +MC2A9:<`H6=$.4E/5BX$^2)LNS=I@2]A%_4<4$1WX:8!#^8%VFCH/_+.!-OJ' +MK&BI1@:V4CI\"%<7;&/ZK!"Y:!.4%7@W.?N%,U(.K +MH?OGD?Q3:-'^.;@ZMHU@#]?\@P-G?MSM:@#_P1Q:UHHP#X\3R27(=C5LO!\V +MWA\UWA\UWA\WWA^'[W%N_GO\';9H.R]#YT\Q;X$33RPU-C9!]\;EIGCX="U< +MVDO1]=(T&"/(F4S";U:D%1HF*PP!`W&O-I14@2JFKW?L0R#&'T14EO@!Z[#3 +M@^$X+FQ33A@H*KM1.Y/TNJJ%>K*YQZ*,IE$[+,1L]5OGAWB)&IU&QG>/%5S< +M@5BX+R0`,#B69%BR:L-!#41IS4$Q)$Q=CEA61P*7:6Z.'2V[E#[)1: +MH>F0?(EPB63Q/\="EZ<6JY5Y^JJ\M>)W[`EGG8KJ416JN#,:&,F=F:1\]D&1 +M@$Z-:!XMK.Y2?*4PB2L,U8!:MT?V8O:"SBT3"@BS;DE?48THEVS_:59.-RL^ +M4`%[]F-QC130#'>W:G#D#",?;T7>"LHM`1@L9Y450VA$N2VR`!)Y]`.Z;V`X +M/G'8'P(-H2Z'>3`MH!0=Q3/.4K(.`;C&\ABK`:1H>=*YX*D]0#8OT:^Z63O! +M2*ZE&7/].*1[\4I;]_O^/::3%X51+Y]-:BAK/NI!=@5R?%(([=IIV7M6;?Q5A]K#W:7W/O+W=>B[B>1PPPR);8`D2@WLMW:=0*F?TG3- +MIW'K"<)R';F;P-AC4&S[WHA5ENF3%9>QGLW>%IE$5/HI?P +MUX,'8.[AKH3+.;W#>B[<<4RRN41[I2!-,'8C&R/L67(DF.4(_0!M._!<@I:U +MEH%<"KYULNPLDP?#\X67.56O&*CG@#P3>>TYQ/R^3T/GS<[ZM5^%.AH\Z'FA +M=-S"D'5,9MPM?-9#;#+@T!$K6GMS4@-TR82!D'^KL(Q&1OBL`%:'V)3K0H]% +M\AE/+OCA:E*(>,2U[AYEQ#.`?"I%"W%XQW8JT>&T1(BZIG?HT@:=]I1$X8"; +M#7C__/TSBE%DY]O[9_-.'6^[<11M._7XL'NV'1\B8F"#N1Q&AQ=9EP\2P,_L +M;!`/XZ.8.'5FQ59V#JW.H(L'6;3PS\?0#V-=GT"Q[B0\*L=@\J:62&]=@"3" +M:H6B+[;CW[,'@S]ARMF#J+-X^'7W=SS)-+P:#_$_1P^NQL=_?D'SXP_@+:YW +MG,7P25>?#?G9@VCQ<(@O'D!7PR[PY(%MM4-E1@8?XZC +MGU)*EAW"*^BF]ZUE2+&KA9 +MRB*<-PP-&CD1!P./8^!D<6+KCZKXVAQ +M:KA>2'30.9AW.\#FL'+(7_;7.`?-Z$>+%$SK&$$WQ1'=16U56O)MYR+T='^YWN0 +MU%=G].UZ]6?TYO#UT>VOCV]]32MH-*`-(B_VKM]'YD_XB`A[!=H0 +M?D!>9N1$V3(5_?7Z)+HWMXWNV3W48[CX/#[L/SI8Q#@+CKY!5P+D[0-\!;@= +MCOG`?1%?#77?O#Z'=^AS>$N?1RU]'L5^?\T^H<.C1H?:&5;M49CF>.YP-CL! +M+'XPA#G@?T#('SO`4'0%@!(.%0[GX&$G*+"(A_U#_=1O3X/M^>CHUH]HANY+ +M]]GQ7FBTK$W7G\PH,WK;@@C4*VA`,)ZAGO"LX6[RCCN<.)-CKLG258?)*J\P!XU-!MBFQ1]O(@>,5/+2>6M01!ZA>QZ!5 +M6EW1UM;84\;")4NZG$Q`]3V\'O!Y#Y?WC=(?K4/*MHRQE:WV1+6(U$ZU3ABW +M%?2M]1^3JFAU1ZP]F.:7(!WI4+9U6TM)CRN+/ZZXE5?<@W&%8(()4XBIKE^[ +M)\;O.K8'"WA)&#=UJ^'([JQ@EQ&A&!X1B]99JD>/9JG:E@IYK8>TU[,>&SK4 +M,TE])!1]T*L8XV5UZ)'QADN[U4M]9Z7%IO;>Q=E]&L1NO)H!MGB'J[_@%?EP +MSRB;R58CHRP+1&KZE`_N-@KF:7YK4)!`2C2!WB.(\4MC;`]8M"KFKUR;(N)# +M\?@XCL0"Y#-[9\!@;2A@MT:))/6J3JL%1*!-&E_YY46 +MV8F)I#.3"U=*`5@@M-;6H`&],B<[:Y`1AS+DJ)(\30?:+/?R-?UT5(U`)]/I +M9D419S"'FJ5:8DFDK.CT?:.8AQM&CEC06JM4B"9PNZKW[]]26Q03_TMX-F&* +M?P#CPP';M82TWKY90EBMJ4,&O8IT)`]/:>W2\S9ZZ]NNZ-"NM>`?: +MY;`]?L'GO/WN%"G0H\(O4U@_.6JR(%P5P6V4<@"[.9H+968 +M`$.%2"-*%X(N?_[^F5:M!6@"O7]QP!HE`H%_;X'HX=>IV$U?U&H@-2V3/_Z@ +M8WN?M53F:J=P!R18HK^=14/IP7NPV\7;Y__GV5OI@U[2!U?I/P]_1=R@?PY^ +M/0U>#?!53UX>_BH?BAY#2W/*R\AJ&("M@`RD=JOWCE@\>O%P,M%TD4X_J0]; +MSF+'+`DV904JP(JR=?W*7E4R!TA/Z'"C9!=7H,?C\8T?Z-".L^LI?2A4E?CL +M/*@/6.B4+$B;MHPY+9@4=[FPI\8,.R`E@>O:Y0CA40_FHFX)\*P1O;7%C6R2 +M1[M:P?58]>0GS;1>A-40`W3?6KF]4V!/RFAA+3[D.-`$J:6G5?VX-E8LD08Z +M98>'=>U(M$'ZXY`K'Q&"NQK%++*SZG:BP7*,A_?/MN.!=6K"O^^?]<3WV5XO +M!;^Y_P#^>W;(_A%+S+7U!O-F["3Z/\'3@04F^K?Z.X+3V.*PB+PJI_XCP!9^ +M*%X._`-86. +M=?O9K8@UDLH-4G3N%TQ, +M^@<).^_<^S(:B2-,S"1;-8'[XBHZG:B.GC#4A`_];KD1<#G/IP0:?`=D%;;L +MU=WN*9JB:!GY!==>;3.A4=[<(:^*OSWGXY7_:AFDW4.Q5Z4ALU4*G6&LE0?'TZ=GM"AZFQIX-5S>B^\`6'>0#'L!I +M/):P2*C*%%9:N='2FLW)DL8) +MI&%,^@5*6D!#8&AYCM!0+[=OQ5S#.BE/R!YKH2HC]*WZDT/V2[E!"9X>:2D1 +M(%GM-G"IQ7TC>ZJJBCHV__U:@>Q;W)A//ZWI+/5UZH4S=T@W\LD-45)0CW25 +MBT+]44&J\"9'?RP>9,;ZN!<_263('CZE\G%X^,BTE(.G4_,RF^DTZH$5+@TB +MUQ(+`E"@OY^T'$KD8H9Y-'KY]KEUF,5>G]_CF_'3NW=NE3+,2$2146$EW<+W +MT[,IJ.Q=!G-!W#:6>FAVN>C`M'&^L,+#T#"%')Y$O8'\>W`23=QC-*/]/[T! +M\B/LW;9N-HD.N8E.RN.@A_V!43YU&-OD%H1('A\>#K;V`!A_W#;[]]?$1_HC#+PBL:HOW?I?='QX='A\-OL7?L_O'QX/B; +MP^-O'D>ZZ=_=:(XXGZC**C1F7+](5MEY?3:P2CA%DLI-ZDY#9Y4H$YU!]TS' +M/#I\]-C7*_"=G<&WCX\?N^@*I[Q,-.&%3U5QI3JR?XG+VU/@S7Q'/6^G'(?/ +M5-14K9#3PS"]6`2%*_)ZZFYR0&<:9OVK_#8SJD[E6%CE:B196D#4$LY,*=C! +M),D/(X&L"^UF2K$Q]+AAW@Z,+M5V=-VDK'W*UFLZ&*P9E[S(^Y5Q4_<*(C&7 +M!F-I@06;9\SH40!8STS$E5@#X=FNJ)(3CI=-FK^ANQRH.O**CE0C8*>^Q?7_ +MA_*/'(D?.5)6?C`D?O#OD^]12+Y'(?D.FQS%F'N.:8*6A7[%Z)MO3Z0`.="- +MG#B3X["@S]+M&#**M6-!+H$(+,F$F4@M!6&DQD]^89M+(4\J%%6JI7@ +MH1=)>-SQ;N>1+192IU4]\,6<%(>YHQ'<8@#O^N9E$WS/2%`Z-"P#8`/WUAYL +M&+9J]R)=LD>;R-2^IT(+(.[GY+XJTVJS].HWSF`;*O&5D=L#-C^XG6+NG4_X +MW(TS_I'S8+>Y&Y^NN<0&7SDC9>^`1&:]8M[C4EE63Q*G"VHR,"F*R,W%:5]- +M-Y7SVC.C0YS$FN<:WKB66U'04V#\4D$\KJME+(>P_)))=#:C+E.^LPAM>5)( +MHT[:O^S'MG8<**_9.J5M!;Z32!&BKBTIS9IN8U:)3@ZNPJP+8VH__,!&4!)26%N'G%K/S#!RW"Q!5PW%@X +M)7(?4L(M^C.HKM+=*DQAG:8;OCE"U/T/7][?4[J+"D<]^_F'+KL0Z"P=)[H; +MRDV5";8<-0F%AT9V;.JX7"<4:KS9U;H/2]/ZLJ[BUW-/2)A#>/"#E0]F`#_? +M.K4"D[&ZH)IWL/A`W8U[6.8`3$^L"-8Y[#:+@@V-*F/8[5L5#@9E@\=B!34$ +M,H%.VU1U>8)P34JI,5I;SE6ETOW>)91_'Q%Z)+5(:S +M^[GH/G4Q+5.,@H4)>O_.I6V2G_>V6-DL"(VKK_PJ0D0^5PDF%>2U'DFAPR*N +M)!4+$.,/X1^N#C@=9RZ#836&SZN`7OI]B9WYKVQ1&'B+*9'^.QW$W5.B<-JM +M=J,CT!%`CR#MH$T:DO$Z+1>V-$L2[:2?ENEEL`9U>FI]9T[:J,CUR4[5_B3!$^VH'[C4O2.1KEIP.'\;&U9_L3E^0K8%W1Z&/.*PC(A]57B:\#V[@ +MGG;7]6H)+1N$,3&`8]5#K8R"("!,N)>O]&/$`'+;2Y4P/^A@$5SMG,I&.HV5 +MNWWS/RUG:U^6_O^3-*Q;L[#VIV'=+0LK8`FL',9?00=?P7J^@N5\!:OYBG(Z +M/!?H'3.C=NGUT.8GW6F0OY:ZY/_9'^*[)?_H]O2C6Y*,]N<8W3F1:'_.#7>N +M],]=#.)!_U#SA"3S!V"(#]E5_>\DZNQ-U?ELKL[=LG4:0O4NMYB*%"7&>IWZ +MU:?".CWM%TUV,!""_!`/,Y=@5N#1\J!-5ZYJXC--H-;-W,$Q,0Z"N1GK<*%[ +M,U=:]I4N8/*[XCLUL:\.Y0=M,Y@B:-/6U$![`(OK;CE_:'L63>)FMGN8U.ZN +M^:*0[`JV*O=K\77PX3D]0F>KD<0'A9F;$5[DL-+*8`)LG`[PXC$."W;A:-N; +M_/''>/A^2)GU5'SY.N4+=+CN.58B\&?WVIL=V-:+XI( +M%YOUFLH6@A)TB7O5ND"T1`AL#]Y?_`HO3/29/_!1]'/T:]3#CX;P482]"0;CUMCUON&0G=N/W$YW +M9S$BG"C^H?N(\8DYUBHOD_R3./I=KQKN(#\2EM?'V]2D'Y?PQ6@:T([%3[DU +MS4,O>]\9;/$9]5JE'1BP&Q%\N(&7,>*5`)`XM19N^FV#:"#I[6SLB>)CN$@% +MTYA5E]0!DUPEV9(T6JOCLS'>;_V.TM;<26!K:,)ZZ@(=!:(%<)%HD-*V`[J( +M8Q2S=)YER64WS"32XM:VGC[58`&((()C_I^=7UA&+[@5!-2:+%5#- +M[\NTB#DP4G1G4'Z`V9VH#RB.FUN5'($;GGS7`/WK-\1Q=I#@4ZZW7(BF*\%T +M!2*Q!_J4$A!?OVFBL-T;>Z9+AQK%.)UX$F]=:A0Y::EZH-Y(8AVNC;BY9M5Q +MZ7\)I0=%T&/KO<*735D2&^]+&NP%])0L@%!?./YB@6ALSG3C%1&H51R,%@HV<$BTN`QV.B.6%$4I">NS'>1$=_H5\<9[5/$6K3&^SNJ/WJ_[9#-I'9]1:VGK7&DA6`X#*!C!Q +MBDYE!:S(M"93&Y;@GHX4F*V5>.2-L++7;V)F8/"PN3>3AN40[HV^/7$+G[1- +M>N(%7B?RS(%B$H+"9@U,/"76H;5%$U0CE2QE"4"7?AJ%#O&+C5Z3.,/BB3:' +M&R-!;O8[&0LP--8U0@HBRZJ@2H%,-TPS^+H!'*"@`R(AF*$)+`;\=-CA&]R\ +MJY!XTG;V7;_FD#.R&]Y]LHO;*M78,V)T0Q&[,3V?"7V,]WF'#5O\G=9Q8['3 +MOR+%EUU@^,*C7D^V23MNE;GJG0FYMY9?LWYQ-SLLT:=5@5J+THK740`:2.:M +M_.TR9/O.]<^=-4L-:5)LQTH!S7Z0G/-T7G=E2+F8ZC-#QBQ0Y**J+2A"[D:P +M]B5[66VJT=+]H"DZ!'J]GI8>L^G![@XS!:="K#WCU[N]3`59>^$E_P._/4BV +MMRD5._3NH*^*DOV4K=6ER1/*-<;3V8EY\:[QOD-`0.&=(X[_/<&@!3JZEIGZ +M<+H,2;*XDJ599U<%E4/6=*`7[]IQ[<4[']?ZYF>JD-E:1MT6N&VO8DPH_?3' +M]F&>_ABB-!=:;XQ#*^#KM^P"A"">O@KZQ2O"M(&F,>.UPE[%6+THC>Y`9>4U +M`TR]Y@W#"\-9D6P6*'W5,)9DSUM55PW1M\;JSKG^Q5\/KK]>;46#:739#A9%1 +MDE>_:4"3+TBC9)N9"5*`WO]^\=.?;(+1U65!=H_T$MG>O/2;J+=<*4L?-5-O +MW+5F\JDZ@2GGP<;A&PJ1^8G_YDO=\`:VDT?1D<$+ZPY/)([>.8P/NR["#C\' +M72_5!GX/NQA2>2H7PIQ$]/W`?C^@[X?N9_C]@+X?>-_GK1WLI.@,.46GT?&^ +M9)_F@#O=:5)0?V/'CWBI*[CP^'CP3>/'SV6S1P< +M'P\&CP>PI[ZZ^77_F\??'CT.7!%-(U[XH+U_SBL\+4>Q_+@0YOV_#E)6V_HC +M[Y*7/"L64NBIPW">C;H8OGR^<`XKNHUH7W.^=8^C`-XWS<6@5$(?JZ;,[%R6 +M(M_R31[-*"P7Z!^GE^@Q#N^HBL]ZOWW+I`H!,$/,+7. +M8>>OQ5+S["G>C'_/XH\/!G\^X'_UY%\/!O%'_EMYEZ.*,SW:^)!>O]6S"]X?0T1D-(- +ML^5(;+U1TYK0P^5^=SIKG%&2*A.+K)Q)6^OI^>PN:NJ.J.FL6U+.'=_.::^/ +M"'!P]SX*6Q746C>?'SJIZ!9F>\\%WL\"VG]-BFD(-ZK1WCB9U;@>.*BN9_R2 +M65]R\E7T,AH<'MI?=(2F`QC0C3HO#SJ=K-L;=!]T/N)?+C4174+5FC36EP]`\?=@#'U..`)\HHW+[),W7GL$G?J,+E5S[&8E@# +M*H9U%E;#XM?W1OG:^)7(^43$M[V08Q7W7XXJ2*Y:=4>Q6K_]$0NG& +M(`$./5^3='8.@O@O==;;V]G'OSXSY!W[.OO+,T/VL]/99[_IQL?!!Q,^DF5? +MT^&YQ<'B8-Y9'&3QXN"C]<_)+O_,*<*W8K16[-RL8U<-W/$36^7*(\@[$;AS +M@DO>AIZG)MJAS"MG;"LCD-.9XCS7+^BTY\RF,;QX<<$$PHY`6'2U?F[-6'CK +MPAWRI+E\WHR3I<%2N;&G`^BL9-/Q)^2#U^>,J_7T$O8,1HHG +M\2#M?8V',F.@\\/XJWR#0?QT7<%7UN-J#[W*[3LHL\B=%A*E>J(D*$P4TP2/R6Y6&-=X@*RAYP1N&1%&BNF=3_L +M:172B:I$2DKS!>!XA$3O(7277\/RDX;;8&=Z:KUZM^BZ+IN*S**X'M<%7WHS +M*Z+G!+3_\)27'^QU8&!SYYG>.*K)\#&77_//'HMX12S7"WW3`A#:V!NWQ&'E +M[EOAE4ARDA_7\&M0"1BTW*543\7YBGKBU?INREXII=J\ME<=):/MV<37(CC: +M30GP3H&4PFWH?<\K;WS91/>7)!PZ$)7UYA^X?G0K=QK;`@Y*7H[N11\5T%A;T.) +M@F#2^^'9?U=`Z%FG,]IVQUEO,LZZ[X<*'US8G%5U8T:K/ +M:V6]8#ML(6HY^&'#S*#)P!3L#0E^Q@-N,Z<04#`N=W%`RA/`R`\^L,.0V.S);6:+[FXL?/LTIJO."!>A;MO +M4)B<&&!T%4+I[DM4.:/)+``2M3/O,%.Z`()S&H!5^%?&]([_#_?XSQ<@KX*UL)\J?8`S_E?^(;1P.M)'#1%IJD*T!8 +M?6*\05(^H9#OZ_Y%'_-O8$85ONI,@`E)GA\9\$&6T)5W_R(PE>,N]L;*ZWN,81TR1="6TN!A8WL+F +M^;=K"+6']T7?H3.;..)AG;&N)YMRCVU[SK<1N8PV+W/W18(EM#`DI'F_>A). +M75AXBP)=H.[JC$CM33_][[YT\=_0!#/ +MP8G92[1G`5;P383HR0!^R_GK!<5.Q]70-38^S&BA6 +M+++*Y]:5+&T@WPKP:Y*R]+$7\71@#EQ]$1[#92MN=+`-$&E/=1F>1)#]\_SBV9OH(%M[E3P4CWF>^>_WW\_?.?Y(*HIJWM97NT-;?(X94.%**8M-X*E:T5`;&S":>C1T%5 +MSFS=.R\7%8U(M#*)Y9'7(,OG!;2@DF/J1I)#^WS4X1K/4F(KN2/[LYFA?#6G +M71!5SZDJEU9-U9=PZ*W-E<$Q).FCR)G2#+0:;4F(K[T*9OM7...].I! +M7;YXB@2>9Q8[?TSC-I'_"U!+`P04``(`"``37D\?$7:`/JX<``!61@``&@`` +M`$U%4T-(04-(+TU!3E5!3"]214%$344N5%A4C%O[GQVJX]/CX^%V#A;=3O_5IBZT95=Y[7-7NJO +MFX4>KZJ\&.F3%R^>_][C#_BE+Z]OW]VZV[1Q +M58W]&UH\+QM;9C;C-6I7K+&`KK>0TA)S9ZK`!J;2]M^M7V^0V;*VO%2],E5M +MAR.>9W5AZ?@U1E;8:U6Y:8%%1BIURQ41.M&O! +MKI&>MK0&%H;X01?4$`?04U/GS)_-(@?'EZ["TVQMH"59MW*M4VC(U&*1O&@2 +MEI*7@LH#Z]VJL%C&Z;O2;<".I6T6=&`SA8AP!@MI8>-Y998D(5V8PE06-HF*R?MI6_&SMG0GVL>5"Y,`'7)IRJV;6-"UI +M%JUG*CH)OUR1P;FV#M.AVI,<<_F,2PNQXH#0W[RR2^Q2*^)>"76J\G4.-#`3/FKC%!CH4C:'H\QV'X@+LE\2[;EV;942JZ!Q +M9,IKDQ<&FY",H%,P6FAR-B)]SM@D5I`7_B2MQ.'`2;"O;D:DHY@%TVOYY&P6 +M=$!86P%W17LWO-^LV=`!O:R8]VY)#BE1MWL#4K?:5OE\T=CL6](],JT1+Q/? +M:#.O+/,-?,))-^0Q%`V9.==`A*LZ;/T:`_4D+/_:M64F;(%IDHR(?VP2."O3 +MKUP*R=`U.F%L3+,F\K5[9EFC-U+W4^(PHSUT[!YMIL]9.E/:P7IKI[DI`0 +MR4F"5P6IO"U=.U\DZMR5!^!-?0?!Z2>_++9P$K"JO.&#_?<3K7\D_6%+N=-1 +M5*ZQX0,L#3R%@V4M12`S1=(/$*>)'O\\OKP:O[J\NKS]E0EGC3(MU`)<6YH[ +M8B.+$.#@<,9W/ +MT:HTZ:523_7E3&]=*T*J%S"KNBT::,#4<[FM^R(8Z17%!!9##9];X1`F)1<) +M("VBPR2]K;*\3D$DG'FYU8C#='1_'AH:MR`M7S6@%1J_;$LXHH8] +MP!)[XH!-QSE1`CY?4/.+OKW1/US%_3>8,_Y;ELYGX7,('O)P$/-I[R4:. +M?2V`3V^;6Z>[0%F#:+"G%)"085"53XD)701@+S"#<=;B0`"D[BEFK[W7Q%M@ +M`'$`16.K$L;'D`%^523Z6Y(DOPO'H(WD#Z&$@XD;J5EEL]].3I_]#N]JL)/( +M/L8>>GTRXE^G[$+IKV?)L(=;,9!A%W:T#)SL2V1&1T[(M2AF +MU4L=AOUVC/,]_YW?Z8&(Q_LN7CQ&X(9T;CA28>+QEZ;4#&W(B:8MJ9"X86+- +M$E-@J)#ABE!?V0@A+%>&F5/18S^N'H+^FYF/I)[4'J5>X.0C5.^]?\MQUMH` +M+FD1H2O*Q1_K6WX'BZDRU2WADV[(A$O +MXYT8<8$I=)@`+:I$^[M3,/6T.@9$U6%%V6&""`N/_@4DF24ICE^5F)(G*1\! +ML#+][.HD]0#$,75]!6)*O:(KQ4Y./OT-OAR8&=L"ZB1@E&(_2%&-YZ11I??< +M3%]M..#X!=EDTS)$\1#A-V0+T%:TF0T$N:HLDKE;Z\&-N=/O +M\@QP6=]>C_3[R1@YAQ]5FC0IG1K,5_ +MCO0/MB*(RHLI7HQ\UVLRJ@<>I-[S%E[`(1H&V^@9`N,/(@&+D"38]X*$GIT8>N4JMNPJ"&8KSE42AGUSLNAL_!-)8\3/1(,5+ +MDAGPBY`-:&OVG"F%)(\-.;YZY!$Y[VTEZ2DZ9^&"TACIP9R?A/$OJ^Y&#J:FU9WB.-GV)["`@[4E2K$&<'1Z_%J5>226M3J +MJS\M:_Q9/2,4,D:]2D:OBD&[4JJ!??_R[%@/)'5]/_G+Z>E0_R=I5X.$]8A@ +M`.%L\/Q7>#;*C5T%:$?8%X?:(&?VJHR3X6!;/ZB'JI:4=8A6>;3LP\Q"ND9;4.I$^:8K=YQOQEB=\SG"D$MLN1V)!M6-6^FY644J@[M\ +M^O3FZOSI4R4B'Q%F61#RIU-2S:`EZ*Z1W\`EP3!VK9S\):3[T(1>ZJ.^M1QY +M%3U)3J9'4R0*V3IG'?XM^4"'3N:??U?J$I$[RW(2Z,B?!0HCA'J8`HP,!42V +M+=D6>U$ZWOG-6>=HU!Y$:%H\1?Z;-/>-P";XH,S>\V<92^X=86%%=KBVQ9;C +ME`H3-0ZQ0BS3@\;>Q^1]&"/R##F6IPC+[HW:`;+Z.57#)K?CJZNQ5,-".7"H +M;TK&DA&1A,"&Q2J3-KVP&&H7N\YB)?67)4>RO(3*0>QMWI!SZGDQ(AJ8DU9' +M7O,=3?ZK!T&:K>"I:EKS[>T0LTMYZP2D'Y^Y6MOV6'CX5,AC0!#'IPOY[IOL,4*PU@*OJ_,*4MZ4F<@`^\!UAHA(E2 +M=(G:+HDX>\)9/F\I9P"R7W$!J8:"M2L6N&?]802-D0E<4/!3D([6NV!@)9XP +MZI+B(L=>NMYE)W4[Q:;1'2,5+;J$I.,40T@E)QGYQ7UYIY9LM0^J!8I&IL:3 +MXF].H&4U_R%%*EE&L8@A<3E4L"?2YTJ\\8-]=W#\8WOJPT,J=1S*GW%;F#=1E!=! +M/8FZII<%(9R`B(*R?IOF#!\&7$5Z9^&7B*:U*2B[@2+/"F<:``LX45[-D\"/ +MO8Z2OD<:_Y#JG=F/'X%8-W%+28,/BYS$[$OJ2[.56$2%WU[%D6M@5#/(6JG( +MM'.H7.!@EW@2!@&5FL3<453ZA.9S"AHLKL6]CT3M9K.6NZ@]]&$D^G +M(1=2M71H_DR8K?2%)"JD!*?PB-5+=.L-J+L00VXQU,M8<+0>V?N[R='7Q\?' +M<8HD/(A_.OKZ^KP1C]< +MS)=4PB/O>&0&4+5H^!71\&J8^.%1'3DTU7PO,*A)Z&>_U@&3R*6^.%'^)0P +M?%HPYU94RZ-"YF[([`7"0%WV,\D/[1YK"/ +M,TD(@U`48"EP/-5".@_?EI0]V)SSSY]L5>9SY!A,U#N$F!P:/;@0_*M/AOJ, +M>\0R:7P]N>0]!F,(D'$F]5+R;L>.4GB#J:.&+,_A1E^YZ-[+K!GY"`LM(SZ1)$'%`1K16I>3IZM +MZM.G*86S,CLX8(])A7[NS,CR;E-VM#)"WB=U08G8QA:%=*<>#3I8.VAXB*2^ +M_N:+Q9S0*<#*BFUHY>"`NNK@IT]K4^(HV%TL0=9%I1#?UBO_ +M."#&OICOJMX3#RMK%2-:*8\G$8F+N;P]$W,9/7"DFT`(V1:AEQ7T`AG>7:+? +M"S"Y9U4Q+Y_JKB3'!K7:<@?*[=1K=\+S+0GUTZJCKAY-F'@> +M87H(2NSNWDS.;R:=YI.J*(\)>\C>PWWA)KQ[BGRXX@3B+(;1SFCBH4*>8U:8 +MLT+*V9`@@SY!DM&\>H$R:'9X1&9&6ET@1R;G$-7:2[SA$EQ`%&#?CDHO7>;[ +M/7^0")'JQ5ZZ"/H71]XA)8@'<6SHT\@7V>>(/R5<3B!PA.S2IFUCX7.^ZQYK +M"H5_11:9*N;S89_1"0-S>V\(&(\PL4$,I:&TQ6U;39T^8['BU;+N7KW)T\I1 +M3Y5>$[07)$1Y_H[;IB7_G18\CY0#II)ROPO/>SNQFC088*I,`D\4A%=WWX5W +MTW\1#!-N<31CYQQATNBAH\%*4_9,U,+S8"(4Y@!D2@)T(FEJOQ=QYX,ZU.FD +M5T4=X[J[6Z$RQUC7BVD10P0[#0$K]5%L&G")A2!@U]+.?]#[=HZ1(+N1]$@'G(N/Q.48,HM]`$VNFZ01CHNX(2 +MON/6?$E#7(Z4ZB@U=JJW/-U5HY7/7E^-?YCH[RDMIG!.14H16:5I +MD!HO&@J]Y(0:1U"R#@UI8FG_OA[;P=KEF7>WO>('5>])'7%:1#ZZ%3#T701N +MOC3N#KZ:]OMX%IJ*2-CHL/^103ZE/6"0+\T(L)@*DE)$Y#M]U+P@=Q)S!AS7 +MQX(^',`C*O-X_DGKA<@C#OE]`A$GO=23$A;)CJA$'R_Y]);1W#Z1HR)S/?>+ +MS`H#LQG/#;418VB1VWLNUF)VAG/@1FSHRESD*TI2?<6571&K!/BRME6SHV8 +M-\PKZ*9DD#T<'_W-\$&?+ +MC48N;$NMC^M(X;YP_Y94GZ/2'`Y:%_+PJ!7)SK73>%\DW#`(IQF&$J,G<,C] +MF:YK_\6>IEA0=X]A0+D3@R)V5O&F'L7GY3#I@RU.,%I6,-\^]Y0`,D4JZ-K* +M9'<+W[.4^\&8//@[/.W!B^=#7Q/K)_,-7R*)&ZIE6Y:FRA/WF:]_P&ACA<]? +M$&G;I+1(S.;`2G<625V59#:ERR]Z()=,I-:4WR<$3TUBTJ2]XZ6XE/C3T+.[ +MPTH[E^NB7:CNM`P+_7&I[$)-?!R,"DDU8PJJ>QY-Z^Q09%@?T94/_$^/\&+/ +M,S4;!S]=<4GF87+:\UA[GHIV5W+IAI8)52"[JO."F"FI'0[>D&V6F9O-))UR +M[;3?=5&&K\A;.+BNUK(T]_FR76J^YT]!/FO3#EA7&`9U\R8?^DC`8ES$`?MH +MP,>U3;WGX8\(-^Q\`@`+%\;[AA$U@&3?-\WQV8\7;R=?G2:G]O#DZYTW__SX +M;GQ]KD^3D^?_]?R;9U\__\:^B)L(_73?0E;H\2_T%1C.0,:7%Q<7G7<3+JFN +M-]5Q2008PY=X-21\WW%#"1ZIZ\]WJ*8GQ_-75Q]!RN75S34GYD3^1YQCQ(Z\ +MU],E+X?LKNRJ,9.?*3/D6\(8K][;>+8Q%\!.<:"25?;6T=ZCK +M]OWWTFK3XI`]R@B\ZQ/>?^LE$,X1F8\!AC)\$8+43+B"$68`0)S^[[,3S37:JISGWX[/=NWZQ64&GARW`0%D[%>-K/CUK +MJ%1T^QXV7*V@^S\^M^2DMX[N/"B3"@S93\B2KFGH@CT3*"!]J%PAOM?P78RZ +M?].8+FB6MM-^6-+DXHW%^>>KDYO>TBYJ_Q0"R)^F<)$9^`JU:6$Y#[H +MVS/R_0^J=_JO3)BJ,MLZ7"&7KT+PS=V=`E43DB:*0U=?/?YIN&[N_(2-_$#W%Y[M0'"CR)>%D^4)2]R4HF5HZ +M%5?5+XY?'&MN[!!<)F8$#>UX>2(MK;YE%`7?2%;,GNY+5E6?,&IB;B@?0`J3 +M+^V#>R^3\9NW5Q?Z]F)R.XF7_/=N<(?BCMQAI9+ISA<=?$3U_5SE>V8O8X,W +M'<8K(_+=K>[>:;VB03I.D<]^ANK=N^VF?`Y]Y-";^[RWCXFW%;K@')K/(Q)] +M?\O_Z^-JFAK'@>A=O\*3"S-57D^Q57N9&PPIF&5"4H0:]K:EQ,;1QEA9VX$- +MOW[?:WW8"0FY^S^%SN-E;Q@F%3:I(GMV[/UP(#?3L6NJJ;(X1 +M/R-`'=ZCPH5P3R]0V\`S-[*_W$R%14T38_>:T3R?A$KS9+%G&W.CEFEHTGB&O47Y78M?@W"F\9*3G?D2./A6'/`6M +M9SGY-'_2/ENX,,&B/Q"6"M=JYV-YJ1"PRL+Z"F:IJ&,:(`N%>4F;B_=KA;'G +MJ1#TP=21('JIET:X72+]4!7CQU:D=]D!Y3HF?P1Z!+7*T]%`DW&CZM//1PI9 +MQU)[9W$LNEHM8V6'>_NQLKUZ$^R^+ +MI?;/[([2QA2N?!\;5)_=`9(F$[VDGVXQF%\7?WW]-<&U60//"[3U;$JR7SLT +MD`J]X$M,1E3%D^.[6>6GN!E`RMB/TT5%(=4[)AV9F"1B"KOP@W(1J:?#2J5W +MT$P.ZG:=':.I.">`G\5D.[FVV`L'HJOD)8/)_"?9).6/?D^"9*>=B(JD@PCI +M1K;*66YJL]5(*9^[6A2E<20`ZTMJ/>O/S=G"KXOV6*"W=:)*:3"L61QS7_QQ +M69<\^5QD99:,RJ)SJ'_DB_?T`FKT\G?)\'3T)?0[E%1Q>@99,HHKI--G7-A0:X?=P\8.LRG5?;KNAIMOA:O1=O#"+1W:#FN?3\QA;F +M38)V]DX,HCX0@[A-1%!SH`?9,XU7:O`P`0,'",CGS5*&E4N)V3TJEU!*(4KG +M.39?Z^-D.3I.D:_ERU/L:X=7KJW-DVJ[7']2R0#;7'R_O9L^_AQ?"8":N^`- +MVQ,.W;M"&>&JJ#8.OX7Z_BL!I3@[@[/?H6DOTG.5]#M,8"75-DN]ILNAR2'A +MH1RI@&4U.SQ`G3D#1,/'\'NA3]WIOC8#Q% +M*/J67#<:C27?A3+/<,^]%>&J2!Y-1T]%!Y#,L:K-+E430'5=5`3."UK!;&6J +MY-94"SS@GW95(VJL.G]Y1G%$YVC;#Q8S^JB[3JS6D>$^E@)\2R;,,TS;A6UH +M'O...?][BT?K6AE7B8GLDEN]JB7*?(!)MUI>PH`^;O%EG5P7)*&'_;T_"?&5 +M"9&&HU6O\I1(K%_:O7E'\V/1"/0^("%EB#4'EE2(?Q3:8,R2^G/XP*#$GS*# +MB<6G4:2'N$&"PSV!)>PH>D]`,U9IFSR*%G9F$2+BV@ULA`>Y4?.5`8S3IM''9^7!KG=X +MIC%I;C!V.;'&N:D7VX:@Y,8T=JU?=7*_->JC!C#$M<6H=F_'^^$6!82H75[P +MLB'Y:X(#A-=.C`PA<-O'HZU3CY"D+F4!D9:X5$434G$P9Z?;EO=)B$E+NJG= +M6"GPB6?<"OLFL!M$JJ-ZX;M'@\PF2JG!9?;I_\7MM4EI:?/N/1#6J_&].]92 +M:"#V+4FPEM[ZJ%S((&))KI#"9BA%B7T[M@L13/\:&?S]#U!+`P04``(`"`#Q +M74\?-2B,[X(E```C90``'````$U%4T-(04-(+TU!3E5!3"]-15-#2$9!42Y4 +M6%2L6VMW&S>2_6S\"D0S9T,I)&4YR>S&/K-96K83G4AV$MG)[.PC!VR")*)F +M-],/4:L`&O/HT96OL[7+UO95Y7]I?='D +M>SNK;_S"?M?ZN@EE46/4(XL_/_BJQK-]/#W35T^*A;UR%2:???'%9\:8M^M0 +M6_SG;![JQI9+N^RI.J'Z2Z)J*[]RU2(4*YMXF)J+AM,W+A0-_F+X?&]?N-NP +ML->-W[FJL0YK_GT>5D7P.WOI]S=CVZR]7?A;GY=;<,@1IJ.`9W#1+6#MS&;E +M=L^7363VQF^Q:B%D7%$6^TW9UG;9;(VKO#.&6V_6%:A-7=%._:*=NM8^M:?; +M=GZZB91/7\V^FZ8'8R8?Y(\QWYV!Y1_73L22=O&E^>Z)O-[;HFQL6WM[;F]5 +M.;+=RXO7W\[.OQG;EQ?7_&#+RE[.^(E3W50I8G0\V:+EPO;E"K;>7GK[=9E-V[E +M:Y#X%)L@B45I+^S*-_B0M1L8BZ.!8,!G&'#Q,28MRQ9J=W;>KKA^8O&C*!LA +ML"@QXW/.:.RN+#YNA($`SF"RF[U]7L$P_@;;RM9@SU9M4=#V_C9Y??)($/!01!OXS!G826Y2^YL)K=TM3LG?XD^31*^S+]U;[%WQY +MCO$7HLN.W"XT:WLU>WLY>XY!7Y`EC.<".U<^V#X3YU0PEAF]A+RIX +MD,:_H5A@7.TEIL'0RFKA*]*]*;#8CCQTYNWO$.*^_'"N/GO8U4VG@QA7YY6K +M)'XMVR+32,I=-[X0UX2O5!9Q$/]L*,B-:ZIP9^@+K3I6C77>PA\9+?6%S;#W +MN;>C>17\,M\?PVHV&U>%&M[K:F,>G6#A`F*AH.>AB-/`Q*W/FE*#KBZ%*/(, +MC"#R4KV+-FOJ9P:Y0OF8Z/A^^-U$_^D&URSWM<-S0_+(9FXF),& +MP[RKFTF-KRKH)1J5C-!=%=C% +MD9T[VC;%21]"W,)3'FX0.ERQTEB9=BPY!YLLVCRW.G3*;"C1H_)CNRYW2%#5 +MF!HLQ0A3U*4S[TEL+$OY.T=C'7>;.5Q-HH +MU,`LZW+8L1@`G`"$]YN-)]MCNRWKT(1;9D_LG9X##N@#^C3F5JI:WJY=#98V +MWI2R1MU44%9;^6A+58LX"_,;F!F6!1=KC_^%C(GVJ7UYM\W+T)CKP>SK,D;9 +M(.$6E"%+X`+[E6OK.L`P7^9A$TT.\:!9EPM*RD"?L-]<-SBB0:4W<:O'G7H@ +M=CB)AV[P[_FZS'U]LS=+1U,,M5(>B=^\)Y!.6AVQXS$D':(_SA$-3+/#>Y)> +MP@[']O+%I3VDK>,E(!?>+^H'J(Z1VQH#DLSH+A>;(,>3N6?$7(SM\V^^M:/G +M\/GUY!O7+C>NF'SKJMPWS?&]Y2B=7HL/+-9O8+@$.;`(MSX)<&R^^_[!G6#B +M'"B..4)TH1YH[WO@U,R@%2BU2(D4?Z-)#50CF?T6T<8W^T//:'RV+@(1H^$J +M@R_V6W7`>]3@=+,.>M*:EM[1SNX!FS)'\N+@1Z6UBWWA-A".P\M,=CF&^B?# +MQ\I/ZO"K>".8)7X4EUO:3AX+_6(,\%DR1>_P/Q/A'@`QY*Y&K +M03BMX7A,-32%Q<\EL+LPKZ*(Y!`#N`(C6%DQIH]%V&4!@]@A4]F>CU_:L@EX +M/51,9"&9LY?%&&0]-WCY;MP%!O'@_WX[MM]]/P:G\`$"L4=9F;>;PF[#;:FK +M]WXU<+81W/3XMY=5+VJW"]<,D#(92$MBQ5%O''=Q+`RX0%Y674HJ$Z&<]FGM +M@-H@Q@NMZVS=4E4++R)CD*-=7__P8HR,`PUDS9"L+#-TK3M[!.)Y:/9'W3H/ +M#/H-X0X$^TZ^@8RXS0>#V<-B/9#?\7!I&)*XW/U!]7!E6?7RG7I6([`'K/7A +MA6.W\/*L1#;E;$\W+WYN5]33JG(+,2>:P_E7KU]B(]PT0Q&)3(6B6';H%T=]P(B5 +M:,O%< +M'C%0K6,VO;-_Q4NR<"=?;2MZOQ22OF[S!E$:H#[^8;#/Z70Z<-RHFF=1#[0"\"\;U['3@;Y8KF%:JR"!=:MC +M=&8Q+UOFH.7HZ$^8_]?_+(Z4T]N?-+>-[HZ?#>H<%[34G$L-#62QGS3E!%AC +MW#TL_+Q=35#X51.QPU@530FY8SI#U'0I0]I13*WCWLU\DTV/!9%4'JY?@U-I +M-YG:YTL&@MB`$CH=W$W0*19,:AD+`@8,*?9*1/`++/"ND+(G5I+" +M`R2&_Y\"+62HH@35@O_6H7YFW1(Z8Z8<)P&)A\KX;3O/ +MZ=$EN[J:/VC%TDF:>^E[9&6U+2MA#$-T@HD3ZG+9[*3TB!;Z)FNT0;>PW^>. +MI@IG='`O%D#-KD3*>=XV6C1**`-D3SN7+4L\C\H91S`>';H5\!/[RYXU)F$3 +MA*)^%B?9'(JD(BX*Z4H%>E$U[BOAHK2N0=6_!4.EZ<*/]FL1D<884<62N=(5 +MN3*KIUC.1+\9E#'F_.-:';V#_W:D&;SVS<^;[>A89)*7Q4J>&%Q>`>\SD@PX +M,Y+Q3C5V3P>!6WJ!%`*Q:L=J%SP%:O3RD&85)`]KO0T+_SMQ=ZS*B2U[*3QW +MR8CO[0D"`_1NV78YZ*B(`KKF"'-`'W([N+)!J@M;6(_(+#F9VIHTM!NV.24A +MIS[:>YLD7LH160^X-+^I&%F?$+$/?YI!2`O)OZL>*R^2-=OUOF:A)D$RTJ'A +M+R-LDB,6O!#4H%V*6S6=K*VD?CY:A]7:[!Q];N.JFR,QQ7L5)]>;E^!>)`MZ +M:BNTHHO3-T-50N)1BVEN$_N8,C^UW$E[W1+KT_]Y:(!EG\/`JKW1K#$9B#A2 +MDK[,H)9B!Z:3\**4QCK;#*Z0SI2!T)=M'K'O$/I&MD/TQ-"HT"-F5JS2H6_J +ME,T$+=CI;85//87#PP$HG.M3TS7FA!C2?U``=!M5?<]ME0B +M)[)-.J)95MY#Z>[6A9PR4T_PMZFK,M9H&.,/&_7D0G4VEJQ82$9<27B$TE&' +MB5KBPM3*H7R'1QK<7>?2!ZR:^\@H!N8>OH"-C;OQ*3*Q%ZC,N]CJ.Y20MH=^ +M)PI$6O=Y[XE$9"888!/N`&",^?>R!2=[M1G);F`M+\L;2QD7]0YN,'OB/B0^ +M2(=LL:O9G['IJ<8?.6(SKT)5-T\EQLS#:L6.VX!.,N3A^4`Z"-""(X/&Y1S# +MG&N/:$<4*B8.V4CFOJ_#SNH.]6#Z3BZ[R0E5]TV\#E\/"I=Z?+\]9Y#2C]41 +MV"K['0P]$1!M$X@VYMJS/G_:@26,2A*3^(RD>>A,R1)U]_BZ+ZK35\\.35T< +M@X.U/P6)1(J'O87H0?1SLP1SDXA+COINQ-&]*7(>$*J%ZM/E*WS5K#?1ZL,& +MSET]0[31K9R"H#\3T6+;R:W@-X7'T)P;U04`?]9U*,_3PZV;Y +M$V\6R+EH?Z8I^Z39BR5IA==6F3?B;J(`E.M$Y/)*9.,UC8, +M0>[:51:FZ!4?%0NDPK.K^;[1IE-B;*P5DL3`SR:?]P,ZXIJD3DX@/-A?0O!& +M[TL4*[&N:']=L*#:!L?RJ%O)[QP[D3Z:=,0/CUMXBJ*`#M'*K5PH!N#7I2QX +MO\-_9P9GEL,%$]R(C'2;^9&@7Y%`2OJA%L2-C+IH?;J:@*2H&2F5"A(+O-:L +MZ@!B1H>Q@M\[>\;3M2<,?'4I%2PLXED2$<>MW4*J=T4((OJSQQ8@)9\T82-] +M:^1FX(\*0>)'S_L.G*(NP)!7;B3L#N/V&FCQ88;319C%A\IF74K[?U_X,%H5 +MIOKNO?BM`JWDK@=MDF<.0!U/'ML]/B6X/6]7XG=MOJ"`]&K(G'7J[B,Y3MQ) +M:N$U#("VFJV$+'=AHQ:0`NS>-X:PU//@Z^3D[=],B74V)('@ML5'4$L)]"$RZ=RF.V';"*22&B%)<&J>^\S%8COY`BT0 +MR+I2F7=1Y/Z)3M?U1;KOO9W"&@@7_$CZP\)LI8FBV`5&[-T5R*;4O2Q"44\'P(7`2^6"M0^H+7^WMVB +M>#@?]%0[]0R'8U25O%A2]Z7F,.J6RT'/\D$IV$2%+9.J$\F]%'RX:N?(TL2H +MUYK?G)D3KHX4GTA?K?XX'IU6/D%"E%:MRX_9Q32/SD&RBM%_<`XOX`;@;;;M +MJESD^_.KV;%Y=)VMRU(,]VJ(]ZY9D\HQY:Q%,'0Y3^5?IT/^=T607E"SQYJN +M@/54;FQGYV_MXR>/'P_F&(.-'"61/>4:!&GG@]:40)M7G[Z9.4/8^^ +MY:&)7T@&*J6-:<'S48P)&>RJ.X^WLS]_^AB&2:>\F]IWUW]^\N38?L+#_0:! +MZ#3AE*EYP^L]7S$6F9.3-YN-LVN.20*D]IW/)B)##Y'[T6 +M&2F?3<_FIS3AQ6V8-H`J_S'].RN>Z>K7_]+ZC$J0^BQ>$$OEF;AGK+Q_US_- +MP#^UN\9I+]Z0K+L%6F;CW=Q!U6R!G6I%BFHM7>\[Z8P +M,I7S@&TPF7N2?=/W+U)/CM57.Z^;`#'YV)0^#'31(@V!7XCW$'DR(#[!,I3W +M\T25A^>*T;7B:>W+H7!AROX +M_^&KJN8<(0%8MHU-90RX].P?RUU#/+V6BT"YYF$MR?78%PM*(DT6(@,Z&"2I +M0<;#RAH04&?I[^1<<:K,.3`H'@GQ7N=!1K;V6U[M8>-?P,+"2U>E\%IF21B6 +MC2(H9YEV/T?QJ$8QS9CGZDM!+WMM+XM]2M]!#Q:%#V=)@9!^"8#YLO(;4:);`YG4S0E$L%NW8XY&CK:.7!&I/>6!Z1(\/ +M\9R=&S0:B]B:FOM!C;"KF"YL)_U[(5'R!'N[,2P*%#2I!I*S5B]=W!ZW)"Z4 +MC<@;3;:_!A^M2:^\XN',3\X^9XSFA\]BZ=3*4:!T]Y61&.Q2_S/:*#!QVH/< +M#L0N>$(7\UF26(HP>J60\B.)6`[5Z3H?:!$1\_9VN<'*^IH[3#:=+N11CHR! +M6>8DFT449MB@&=[LT)+ZCF5A;"6(SNH\K-:$I[FK5F`HGHG*Z+9&Y)HR?Y?% +M@&="B7$:R&*56H&\_F)'M8.]\]I2&4&8M@&9A8S>8JQ1=[QX\_(:^3?:!96< +MO!QN]0'#TP>Z%Z\M22)X]G5K/9'"``9PW@P_@IB7825W4GC5I7M$T*(M3L3\ +MX$Y`Y!(\RJWF-A(@(%*#*>296C_B0@GEU=+I(M(;1#:3KM.HE(%&[[H+PT17 +M>G=#W*1H0M7=%6#WQCQZCT&0-8]D=_R4`%O":F1IE65R@UB.6_JV@_X(9>EX +M52(*&$E<^AN8U2VU*MK?6(H[',I/DWHBSQO=;&/H_8P4?S:AYIF;8"1%C%/S +M:GCFM>/Z.\UVMM\L-'\9BO9N3+<6(NJ)[-%TKFUXR]*V/P6YHUSWQ[8>]705 +M^W+\M8X7Z:P36/-T-+T?22J]OT83FZXE:0M-;8(AIKZKTT]UKB-J=O[UQ>N7 +MUZ?RNY"$2$-_J42Q8<_+V'9ZTO@^'K< +M7&7D!:MV$G;::RFKB0KB:>.G5C)-)U..P.9D(2$!%@"E,QT^M^[[^WNW8&D +M'<^$_2!;I$C@<+>WM_OVO84I?`A8PA$O4+T0^\0&]PB%K/X:-F-XB=-&(]JH +MIVJ^"#4J6Z61"\#?&=VORJ68%6\3A@E99W.(4G2O_A0HRKQ\HRP:G`2$MB]D/S<0"ZCU[%X=W1D:VEOJ".0!0-@`RF`L5(R +M$@,3R+(G]1O!;RZ4D.M)4(NR2D/(5737KIJ)2G;AA;M0"12]PWS!6HD]&D(D-'O/4*-B.AGXL\))M[(A'6 +M9?%%<5H<%6?R>[6>FS34C/%N^+S3L^/3J;3(LQ_S\ZYZ_^^]$S)LUA +M/'CKZ&*BDX)X39F6W7H!1$;-1';5>K%6GIZ&&;**8DIM<1G&QM29#&S'B@9*/1?C`55P@J20+CL=AB9;UJ&[DRPE31KKSE.)SQXBHDA"SJD3`6`MW;)>U7T. +M+W[<^08OH54$5*@<*0D*Q&Y18K`IFK>=HA-!#L&;TF@G;LY%9LYZ<-X0DKQ! +MKD1+<0$IOGG`&.$08ND4/S`GGV_4#I3$(Y,U\B^.&%WAZGJ7&8U.BS`**J=: +M$17^7J[[K+Q$Y7?@MT@D[!UQBQD^!V+ +MP'7,]#0E>B)_!9,G4BDCNQXPPQY!+/)9RZ8R%!J@K-Y\E*1"GRB=893-MF^L +M*ZT_!H]A0;##J9N$M!@+Y43%0$RD5JF//W4GT@03%VE=,J%NZ0C+=;DL""85 +MD@5Y%`=1- +M\/"WM'H8`.QC?I5B^^W\Y[J7$Y:&8WC=$GL"$$86@:D0'F_"8"PW0HY@KCZH +M$HI59X5K"=#S2#!.*JRCWS-G3\-S_B7G\C,Q`]>L=?M!,/&4N\J@SZNJ[W7[ +M7JUK>5(YV^\'3^C+/"U6I8FJJ-!B&!4!9*%Q<_9L2)@RWT;VRS$61I"^.6*1R`%]S] +M].*)ID68J*EZF8H$R3!&8@86',:PY<'&Z+TM1G89K[0^.N:;%-W:6X_YUK%V +MY8F%1R4@K#+>CN/P2H)P'V[:M4&,'\;/XSE%!G+5M.N;6T-T4RFD)7?.X!UY +MR+=]&K(=<*%.8_]4Q[Y5(J)],^F0LG\^^%@^ +MT[$,1I&QC9-ZU$#\J::-\?N_V_-]%X7O"*.S&.1X"VS>&?WX/HEV=B<%A#HN +M`8K@N];QCT>//_TG1P;![])6?)%.:G.\&7X6&.[F&+FAU6J>V]!X.9OI7L@F +M+%I8CH!G8+L1P/6R]N*]U_6)_+4+.^=0K^RO#M>IY7VM=,).A,N6%EH1]SI9 +MG>M^3,&@)_;+5]_+QP+PSV:ST-@3L$SL(&(8GB0#T"PE'^,3ABXF\!-3U@M# +M?X_B90T0$20ON>V-..4ZX@"*.SUY.#G@]/S?>PE9G[!_KX$M>9P>0YQTGO@- +MQ%:2LC"VV<$U`CVNH:\:H8`3YFU5$$UD*6N19:BIY\3X^746OZLP99#+RDZ3 +MHTSVW5S&("-X\,!0`JX;HA:5C85R46J;B2VR,#SI"ZO^*IJA1XQ\,SN7%'ZU +M<"'$I+"`Q/V2YP!K69\FNBKDK/L0IK&E%L_V?],.DH7]7QRLO5@EY4' +M[I`&*1JN3`8PB$#TVQ0CXY7+CI9/(1\=[6/AA%G=O5EW#LP[W@&#)?4`A\RN +M1&V(ST@*>T!O<;BV8.$%*O=)_ZHIM(F&"P,TV=0J=51@2\!Y_CUXA=8I+GKV +M./(SB+ZIM.C;N9);Z,1`SF?-O^L#U0,.U9>.?\6Q>88-=VX`I3*?Q5`>%6_Y +MWS28;]N`4%2#6-QUTV+K3:2O1O2Z1GD>.UIVP,W&828%G&)&9Y+/K%*YH"WOW--;XQ^M/&J_JH1-A(A-1*%D`UY%XB/*!5P],X1*=^1A;X%, +MM`OEX5T1%FMM/;S>LB.PB+S%X_"Z>DA>BR*+L>M'RJOYE.,UX(-^WP. +MSG&X]F#R24!DCOEH]#G1UA>S]9MJ:RS^?.Y8KS:N"\X"6E(8.@L!\_*AAM?F +MLW="SZWQ>ULW]&;9PB`'-*\K5L7DMJ._KC;S]BZU-QO%P@ZL/OC&*2-RI7:$ +MA*!RX!XT2/:*L/C&M/X6ZKX-8ZM*9X2IV/#GX;!A4+S:O[X_?IMT8HI#Q]'D +M[8$9[$9+RTD:@X!WH/?,4WF.@?*3'8'>#P$/Y/HT?=Z9 +M-T:8!DTX?!%8N@;7>+FJ98G!F5M5D6YD`84D]+4R^&/[IK`GE?`^",3P39S` +MO@:9NA\>&PS,QC8VV5'O[H)C=#QR9\1N;QKRD=0JV3V"<(J-@&5^=X/:7$YL +MZ(F64!&OHI;I7;CP(F[QJ2JG;U;U+"RSYW=^-;RAQF+0E0%,F9<="XUQ(L?L +M^/;PLA(O-9\6EZ]>3\,E_BW.;ZNK37=;W;%>.+>4:3)P48GK,VSDLS)V12`5 +M1CM8N491#4^2,D2D8RCEDQP<\`3^PF67FXDE69%L/),)-!@'7]P^6I=NH9?2.GF#SXB'KI +MKRH4/C9!__2L7L[;Q0A;Y6Q3//[\CW\P5I7V*ES!,\!C?WO[K+A54E-$J_CW +M@&7$B)@/8=2U+X6G]LJ$0FP-(U.9C:0IC'1)/P?A +M7&I]P-3236+"^::KM5'E_AT\P?'3X`D_']!H[LN$I>A=XBTUDK#F<+XT5LX+ +MKYY=:">A57>2LM=:*RE=C_.>_@#='9V'B2I-TX:=4D6FY&W:'13`Q,T&/::\ +M&JT2Y#PW+/]+QL)JF+90]Z5.IH;)/[57V$`L)/Y$KAW@UUQRB#9!;`U+)+,A +MVU1#QTXFN?*B8VS;9$^ +M6U<5.J(TLVGB2AB>5*YQJKZ,UO="+>14&PHBXNX*IW]/M3E&HO9H)2E1P;)V +M`I(`DRIA\`D2SWGD."^4+1+L[E[YP3&S:ML%^25EP_6?#CDC-#NF[7Z(IBWM +MEN4>EESU;R62?SAKWV!FSMM5HR?:WVA:6CO/.I+KM0"]J,_5VE<9\GZ+1EAK +MF'W&/L6D$.#3V7A':]RNO&E$+`H%:5=H13HU,M +M690NAFJQO,4>-RZH]Y,9=@A`;QRXP<\?JQ?D17Z%DP.!=WVG4GY<.5%KPEYJ +M#3-;SA469D%BRLQBX8%>?\8Z0T@SG4MDNS?REK8HHQ-0%28C11ZPI39/<4+Y +M/,#'Y@5J+'MB,QE27S=\>&:-AIWY.'Q3DBV"3SWZQ#YJA#,09];]6@5$\@Z9 +MS-&R[@<2=50'`B>71[UIZE5A(5?]C"H(^:96'36U9RV<5=B?J)Z%5O>N[MC[ +M1Z-`%9#Q\;U`_?CXT\R4HF_=T]PC\X13SMY=N<"D>WDO1Q#VQ+8:2,7T\CIO +MV;.KM,_[29O:"0_T#N9W3&F^>OG#Q_+Y==\"$SYDC/:^/N+ASW\NGD.U8<*G +MQ89ZO%+K'49LM)D]OL6G-5[11*_7I"VQ':WWQ*S@)^59C%RFU`S20(GN:]2( +M6+5W5_$47R$H0O(VV\S8;;49-'.HV=,BA,$?<'#J*0@Z8*8#$]MXS8IKVI:I +MA'E-[#]@[0I?YYLUTI'&N;$RO(:U7JEWHIU1>LJOZ5,_*&KS)9Y8+%3=;]2$1&?S'(Q+VFD=-TN +M/D;(>KAIOD#9)-._?GGZ70CA?U!+`P04``(`"`!68D\?04\(&DD'``!.$@`` +M'````$U%4T-(04-(+TU!3E5!3"]-15-#2$%#2"Y(5$V=5VU/&TD2_KR6_!]* +MWM7%9,T8#)\(ZXWCD%TD8+/!9'6GE:*>F;:GP[RENP?;G.Z_WU/=,X.)?8$< +M$O+T2U4]]=+UEPIFPJ +MQ]U.MW/Z^V%+<4*7PFJUHJC(RLH*JXKCK$-;[>,E>&!$WW4Y$O*I:3 +MJE`+O:9B3KJHK,JEH7FAJ90:/YG*%Y0YYMW.)O>@VSFWE`CF%A5I*B/>9BZQ +ML(*,U55D*PUFRT1!K-"2C$SG^U&16V@EXP%%(J=0@J^6PO)&+$%7K&5,(H\) +MQ.J>ORTM59K6C%0>I14N,L"L03/H=NZ`H-!FX-%&$E\JMW(A-;5'K$`J5\V& +MD])<=PM3"FV`J-D,3M_7QAZ-SU:"J5G%RD@8=O38L%$1PYI%<6M@TUL)[RES +M`M)2L\,RZ-S?ZW;^W>T0_BXG,Z*7DP'^HZ)'OX$A83,;O=.XSFNLC@B1@[+X<\#O_L$6K;J:@\N_@\B9NA#IMMY +M!W.JG)^A5\?E!`G/Y)5(!WA/TJW#PEK8'$;BF'/I(VBB]J]$V!>&$JGEKVW, +MSD`T5ZET6CF:6&GGO37%!>5P1_W,2.#A^:MM0J*3^E5<_3$[HQ,ZMS)SG$[5 +MF,YI!E==X'=*UT2G0^SQVR_R=$WB3JA4A*E;(@=0\[P$)5K.?^DEUI8GP^%6 +MXAN653C,ZI?6?@2)S=+>F%B=FP\7+FVQ/>850+LDJKSF@"'&#M[_(<#I\#70 +M#V>3MY=G@5W9WMA_>Q%\K;WDV,S%%W_MW>3/H&',EY&TZQ7\\T[++Q5B!4:: +MF%L9=SM_5DB&+H_W?3CE9BFUV=LEXW`DO(QV)?*\J/)(>D&3>N6B$=Y%:F-C +M<=+4A@/K,!C5?*%JPYHSM5:A"VG3&]\8J8'TT2ZS;\WS@,G%)QNO-WXOM%4B +M;1SNCQS9(Q*5QW+U2(X:A\NE\L@EQ;U*RCT8M@;7[F%\X,C)6B+ +M@.:HR.62:EUWFB\,K-#!OS:$N[6W'C[=$Z"Z='%)])7$HE0T];//6T@7YD6\ +M]PT9B_NOA"SN'6).)_W%O2K_-SD.-VBQ>B#<16<+*])+$5U+6Y5!\F75&[]1 +M^>]R=1P +M?ZZR\K,*96"LX`P5\T/:A1SQ?1"89,.\&SO>P/R]P\(:UFU;DB?,^\"S-?#F +MUG-,C/N'6T`/GP8:"J.BNF5848$Z5O=?3T,^W(9\^)V01UN01T]#;AJZ1\7R +M.8!'VX!'WPGX:`OPT=.`F[Z,ZZVRSL*HTIFT21$_!_?1-NZC[\1]O(7[^$G< +MOF7FCO.[PN)X&^WQ,]$6:=P6KP;O]MZW$./VAHF?\?ZVV#/N'9M/(->1^906 +M"Q2:YLNCG":85+BQ7J"C2@5]F%X_)JSS^F%P&/;&&PM/_K9M;#B[/=0[G._F +M,A(;7$;BVUSX_*$Y0'?%'5N&S+79MD'EMO/:=4XBY.ZQZ08&)#$LI*[FQ>). +MQ4BQT%3DH=1:X.9T +M1@>C@P-,?BT1(T7C.RM@FABE:HT2YF<9(P%((&$8PVVA+1Q^V!TA+N*8XYJ5 +M*@6>*;'U!\3MD2?+:W:XK+UOF`&4_XRI%%`#DZ%!^]H[KFES"!Q7-P&FC3#7 +MGD\+8T]JYT]^.CJ@OO7-.A[=(D$G>'/]TVBT1S]3B9N,F\V*YQ"CE5HX%O\L +M*C=%EV+-_7DL4[;5FG7AX5?GC1&S(I=KK\>`Y[Q8V2'\KL$T$AKMIK11L,FB +MF7RO"BM/N,/6KIL6J?&VLQ57#G`&E]*R=>8;LPD'SN1Z>G[.D9%U.[$ROFE$ +M\#C#-&'7B'G/ZB$-033?@7W_0@^'T6_X]H]K5@=NSF&Z)?U61+!AC\:5ZCQPY#A;8_%6WY6=.V?U6`C"P3!,)9F*.([3G?U +M?#&)[P3",]Y\&O0;G.0:L,'V^%+*--V8+7KC-O!I9]S7;+X=_$X+@'N]-;O\ +MP"/C@W+_!5!+`P04``(`"`#<74\?286]:WD&```$#@``'````$U%4T-(04-( +M+TU!3E5!3"]-15-#2#$R02Y46%1]5VUSU#80_AS]"G68:7-P9Q(&F"'YPC4% +MABE)6PZFGV5;=Q9G2ZY>[L[Y]7U6\EL";6:`V)9VG]U]]MF%G9V=<2.\52=>F*8-7GCX$+XNN<.14`-;.G'-7"LL +M`OM!S'VP9#,WON*ELC`4K2@?PS_@GO25*6-^D.!6%'NQ(VM[H`NPBRA\)?E6 +M"A\(4T?:@1S$*H6*"`/NL0] +MP3_7.=WA3F+:S:E)2'F0->I;\6*DQ +M-M@0'L!TQZ2N1-\=0)^''=^J$P5"`9#YJ59P-&NW[#*[S+-''36&L+6FP76/ +M#HNFEC%-\B2:MI;+1()0UR-%"J%9#G[D?9+SCB-GJ@9K0`GTHU8CSX,@:7L?>`E`!&\!%=2NYT +M0U'GA<@PNIR./R]F5J!E@Y447R4.,EIQ)MB"V%>2UG%71=S(/'H=*I.PIJR" +M6,R3R*$0Y^U^<:]:?DXUO]W\]L=F,;`4TC#3YKL9OZX8>_KTZ5S1H>21KZ1" +MM3R!RWJ0)K1:]-1W&X@;_8+6]8)-)Z9,TY?_-0`%;T:IPQ=&XK$#!_H3Z-B; +M'L<#J9[$?!@&`]Q/7Y=L^/VOS]$;Y71XM2FJ8`&)G@WRWBB$[P9`_AP^_G= +M)N8`HO4'815I=QQ. +M>K9/72[[PWPZ+*P5'=7<@F=:%.@G%_GG3!I4P$B/-X&,&S@H((L1&B +M0@TAC#K46TN;V&!T&VRT-C00FS70D(!?,#2/^OM2'Q$K"@+^@@\=D7SNCR75 +M71*)"OSJY$^+!^R3<12E,EI*(=$OX8BS=V!,9T*:>F6:Y$4MG)..T2I))OI( +MC2.B0"#+KC=:CNXV-)?H[K"E#IO4K!45Z1GM#[*\&LZUYDB;%VM-W6G3*!`Q +M6J.IF_%B=++F_=;IN@:;&<09F2SE5FD:B`_5]CP=9;\"2+7Z780MMIC5 +MG\+6TOO%M/?,0*45`O2[%79OD/O[55RJ6*L.)N[(J`WD:M=]+[]&KVAYYZ4I +M`EF;=DU4-/K@/A`\J"$FX7IS\_$C3TNF9_UR.QNB<[>!,:"XP52[Z^^<(O7EQ3Q\!.&:XR@4``&Q9BWJ=/LR(*`E.F(KD2I)V7%__LYC?"3D?A49I,B[-.@)Z?NFTM6B$\2Q/(<%88L?II4$7! +M8>&JP>R22\4Z+$&F(SZ;OO68JT):AC]8%+>U,+(2RO&2:75:2B58ILM29$YJ +MQ?2*#6!Y$*RRE3;,%8(9W3A(VC39,S-,DW\*[DAS;?1:YB)GA3""?M"JW#+. +M;+.TPI'6390$GA0NM?[(!ETVTN22.R-OV86NZL9Q\L7+7@Q.`)6(B?Q?[61Y +MF2:+3`J5"4C,&^L,+R6R]9='(5/OE5P+8Z7;GK`+KI;"&`[)BRLVGHS')VG2 +M@:8C.4-BYJ431@&^%B4P5L"9K6X,\HH"H+BR9,LM$_X#SW,CK&5.H[YR]D&6 +M9'UH*^F*7^!A88=<-4.1-T/>D`$?F^5;I!)9A5ZVD;8`GM6-04:M8#Q-,EUO +M?4%WI.O-\I!8(A02!E4E?`/OM'6H*)3"P(_>2@V3($DN2DK'EC56JAOV4*H8 +M+.7J49I46@D(FER8$Y89D4LW@@/F!E3C)L<39F6%4IIAQU!BH?5,H:J"@@W2 +MCIK/OSD?LX=\"0*R]XMO)I-'[#OO&OCITU#@/[#X)D2PAPR8R=-QY'*IO1"U +MV62O#Z\:IXWD)3ILXGUY%1C:-9J+`J'1VF\,\!IA4YO%"B!M*PF/@$Z3%7I* +M;R@]-K26A>UI4U*;EZC@G>H?++F5V;6N[6"6,IV+CQG +M<\7>_?DX3>*D.*JRE-9=@Q)0^MZSJ!TQOH_I*8;(*DT@TM"X.AYE*3A4VD^# +MV9SYS\Q^:CBE#M,)0Z,ZJL'6W%AQ+6Y(1?B"1/F.$;><(C^JHM";:Z=#FG/- +M7K$A_OT<82-?_B\)^(+JR5X*!6NQ/]]TB64=+8G<.U)UV4*`Z$>;&;F,X_>Y +M-W$'TU#SZW%@\05W&*F88MK3MW>DCR'GTR@^LY0>PJU?[^3+(OE*88%'8KP/T7K^!QP'TIG&$`O_O$WX2 +MA'\7"E7`*"%+(^VA?9"G`?)2`ZQ6.7-KK![A(Z^8&X#"%^CV-K'HGK/R,)CF^6?'00,XBF+=4R'$\\_:-3&?D7PD_&!-H5X^^?*V;[LZ6E<0O_/T.$`B+3% +M'(BDU=3:][!V$HGX5I@J'DX,]ZYR_B(\="'V,-V+O2-F+B4V[C1]:] +M=XG'1KI51M>Z^PT0S?!A+Y,Z!7363BW\'Y>[ES/KYKD,`R=CIH +MUU2XZ/O!9VV]`^&H3:#8L!:0T/]]5V;J\YS@[JMZ]1_OE.[721_!9'!=3DXG;O +M[H@OC[NDK)07"5E9?0'#.4P7'.:8?\G:O2L&*S@+:!"32#C5#PUA;MEX^]'K +M(RZ'UYNF=F7RR15.*ZP])N +M3T]/OSS]]/B)RUVAGAF96R64,=I8(;9^5_'D[?G +M9^?XB*\&3[_/R[2H,B6$.%A+9_+/P]5!DI<.#UA;CS[CTZRLU@.1KJ01=Q=5 +MF=DNNJUE;14%JJ\M7G'AKND9N.,7T'^V]&_,$KU]IE( +M$KEM&Z&RO8(A++VXQ3?<^N0>1P=Q>CDZ?S$]>WMQ-AE3U)*+56X%_KM9*=,$ +M'!_)(4N5P7CA5DK8K75J/82\$JDL"G$%KU$,GCCWS$K!_?I0 +M?`(V*=/*BE([892K3#E,DOONL^%49/4P:GSK-I@7UP8Z-07"MT!6[3UDKERI*6I=!DN60$%F> +M2H/!LTV7G(19;P?N3RBW>Y& +MU[;WKO&+Z@F&.Q]\J_KBQCL_U>L-PC4O%%)@4J:DB$MEH0W.R_&P/OJP%>%' +M7>O2&5WP+1;*<';A(1D/&2>-\[F%6N`0 +M2X08"G6:PV59TDY&H.7']8;%??6OM:60EM>JS!7#SI8.#CG.O6JSNTU>IXM, +MZ.5P.$PIHO@=L]SC`@($DQ`LDAI-IZ-?SBZB!-Z%IR?/)]/X..&%P^1LL;LM +M)3[!P5RIDNRCLWJW;(Q>&KE&EN;.POU8O=65N,GMBBS-M+!ZK1`/'&@#?7E: +M%8#4?($23)5Q,H_YQ/5B!UXU="0^V6,;A+C&KX61RS4Y"\'T;EU#13R9K0AH +M?!4M=%'H&^P;JP1[]D2/M#SUH>B%,_;[XKNGXK[H)U^X+%B0=WLJ1K,WHS>B +M+^[=1<&NM=EZ:P=(CJVX>Z\N([S?>]"6R!>!*`W%5WZ@"JOJ-^2\WOW^-9I?C/X\G[\?!V/MD6E5^*O5-#%VO*I&2 +M69],&-%.?&:-AZ%Q7U-98EN+0 +M_/RN%9%>IOJH,YWZ6O/+UZ\;RW\F:7[D$3&"EC_D7RY/IJ,H^NB6\?:?%75> +MEIR>C%_5@D<=G%YPAL5'3#JYMW2&%._ +M,&[",4TEM1Y@@=XH$P`YJ/%++D;3)F$XM$YKZ"VQGPM+@OH7D_&[1I9#RA!J +MEHJ0/S6T@!N9S(O:11RZ)2,65>C4^BZX\XJHM">S:@ +M/J=JP^:'D\+N6!9'#R,&$#0I4\JBG8FCR6D3SJ.??0V!#L'Y,%*5V:%>''(/ +M]5;\$2%].7LW>H'J.'H4G.@96:'0_(0%,\7*V!A]THQ:V?Z`XUNJI>3E2>JY6\SG5E$FKQ*]5&-7)Q4.,;I`;^^]"P<.X)!^&4YWU$KJSVZ$CL +M2!)T"4)U3;[)%TFI4J)99COL(B!KM5VUE,K[\.]T1LV3D8_\1&`M:I@1AX>1 +MK[%G3V?<4PGW2%C.M6E)DS!!-E!"!7&":<8^$D>)%+I<4F_J"]9ME2(E""`W +M)+_F'&1Y?`$,#&M\7FQHJ]"=YI7K*FNB>,9^)^)$SQ4'7` +M`O=@&N4Y=+++H?&1O;S/L8]Z!X22&-^&6W20-,0XJ?P76A23$ +MWDQ9XMEK%H47MMILB*\I&Q@)#,190L2)K>QP[H:3MU_C<4@A/Z<062SA".!0 +ME@2"AS['S&JM9$GYPRQL9\YM9MQZOA7U$,L#;(L&PG#,#$0*PN]FP:@A`Y%+RB3'9&H#("44T26&%T5I[NL[!2_G:O_PP9\#(T?C6`.,-!1M^'.N:#U7 +M1;RH&20T[=3JU);]V]MH!SC-03RV?30;)PL^`(V"^$>6<:_N5CPY#WB,^-]' +M]?K.HJ9U9S31;3$(8AB/-P6!&T=8^Y[)#)KW=N8O'?R' +M6P.\N/(D]?\QL@4X[!)M\F5>DK^HZAAJ;L6XB3T-EYUP>V0BE+!^Q+<>F8A. +MKG/P.6@-,!3O(_HM)`*ESRFB-NGF3`-X_U6M]U*K<+O7>C4W\%D1`ZF( +M(0V,E5M<='+%[>\M7N:_B#@N65Z=MMJ?\#V-!0T#VJ'MV!$4Z%C +M@%7#>-'$/:$*MP2H&M\Z0-_@ZFO03$EC#?F.MQ_RC>[HEY,W;U^/^&KPTJJ( +M?)UXQ,V[&=N95[\3)Z)_^UK4*_%#PH#NA[>S>+%R`&S@A2>'S]8TUN)W66N( +M"_W(,-B[,!=/P'1^^PT?GCWU:OKU0C^P[2PDPLZMV`-=J4`BT<(WP&-B'JP7 +M'35/Q0\_-'/R#`$"&LR(BO>3MGV>6>_;)K>V4@UA(8I$\;$.$>>BRTO/Y*-/ +MWY],QW&"W5$8B6TW0)U6WHV)OP^&%A+Y^S_$4TSU!S@UF%>:F[3*W<%`'&@Z +M=_PNOAZ'*^:PC#(1"^\?)XF_NPC7#E2RO1TA<=Q^]../P5/U/<5W^Z^X6VOZ +MK27TPW5Q'/W=.6QKU>#!('P;<&WTCX.2(?_PEQ9*A=/.`)N8KL&_>R35A\=Q +MQ(-]B[MW]VU[Z1XDN=9Y)KZA-3BLHX[FTY;;F]EK7_LZ:AI7VS4'._L=#+J& +MM;:%D3%]Z`\XHY&`FR:/A4B2W3NWP;X;MT'K6O`V)-3,/?0;VN/YY2O^`U$R +MULX/QV%:LGPCN+=O-`,2WV[2:P+`A33)PNBUH'N9`BUWF+Q4\VJY5.&/%J52 +M6;S\#/>M`THX)NV.;F;YZDYBCDX_L=HANV%R.7TQ$N3FQ[&_@K">Y@=*,G6IR$U`GB=VAEPDR!.AFXP8%`293.A +M2(&D['A%__?='2E'=I-U]5-TY/WZ[KL[9NRE5^*RX+Y8,V&ML6Y\'F3C]2]' +M:UR(Z7;Z_R8:C9'Q.B6+ZOV?S=[?3F[OI]14BD-RM!1M['^`: +MC@!!?\EJ7EC#&FLVLA2.<;;E.V8J!G@(VQ@G]8KM3&N9V>H`\>F:ZU*!/+&F +M]5*CEBXI(=!B'KRTKN7JZ#;Z*$396N'._BN4K;&/CBGY*,"4=!<,[ZZ4R;E* +M-MQ*GJN@"X8\MS[H#B%DOVL$HZ.'NEGF;45'(R8=;+"`>; +MH!>_075:098A);:5/M*-`5UR8UW+I1)FB/YU0LJ^PYO]XX]J`'7OH +MM>>D=ULIEHMXD)`R9NR`*8?:W-&!L7(E=5>NE.6M#T9XTPB@F3=L#>@EA0$# +ME34U:;U/$E/Q/FJEJ@GG/`)N);>,:-*MN&J1>(< +M,@<;[07R/+3.=PQZE6?BJ1`-^%ASOUA74BUR*_CC]Q6*R8J-Y277N\7Y^%Q> +M[A-/0N*]>'M=?1`&)0MY[*#U7",*R15!MA'62:.Q%2&)Y/64,0$&:(5J'O5< +MI?@**]A8G&_0KF2LU:6P:H<7(FFP/E".?<4@\"DP"H+8L8*[`"36(=S?VX>J +M^=8]DP[*:"Q$#X%C??$*.HSD(##BT'@N2QA<(27*HVT0"[E"4I(G(*N+B0+@ +MG,"83S^`7M0*=WOM$'(I>+M:/Y.,8N\\T;%2$"MW"5#=&L"(>Q%F4T@SLC?? +MO:@.+8?B;`FA7$UF04Z7SFC\9I\F'V]F&8W>L'UJ+C6,Z,^T!#Y.[A@[F;RE +MCYOL]B,[:>3&^"#X,WL'IT\I.\G?QIUQ1C_ZZ)%IOU!F]Q4O`/WA)"4[H[>] +M(V?41G0G:9X^]4Y37(92#T9'CN(FV9H6Z@Z5;97OYGN`IQ;.\95P,;N!:D,$ +M9\4@A?:#&K_Y]8)=W<]FS.0/L.8<:[A#1,%,U>K"`\'W81SD,$H&#ZU^[%GZ +M^9N66(1W;JS=I7O^0657EM==.KD(0MQO);8&UM#Y$E@9*UL!>P7V'9Y,@M"$ +M$4_P=1*B81Z^ML(&1F.,)"(>0>-T(+&`(U?`9.B4+@!JR7T0@.L^B*.X$F`< +M[`#H#-C+-0YL8-EU*$=8#=@J::Q%X$:VQ'#2Y"6$D0L]$ARQ)%+D!Z('Q5H- +M!]?&-"YEE8'Y`7'TRK$`]L#U"+&3=0/S#(`OVT*$N11AH*Q>MQ.3U[3Y:?!` +MDG^8+0ZBE'K_8`V:HFBM8T/'H=Z]:LC@B0) +M(V6>96PRFU]?,)90-F'RQ632K\94D,!0Q?VUQ&5P<)#=WF:?IG<=%L(7PQH0!-)\7WB\^PZ!;?/DR.B-TK^]OWV7L_72679#1[G\$,HB`_`M02P,$%``" +M``@`@UI/'TRAU:2`!0``+PT``!D```!-15-#2$%#2"]-04Y504PO34%.7SDN +M2%1-E5?K;]LV$/_.OX+H`B0V%*5NL`U+7`-NY@[!$C>(DV++HPTMGVUN$JF2 +ME%_#\K?O>)1M.7:WSI_$XSU_]Z)9TTF70NL2;#(6R?B$2R6=%*FTPDFMN-&% +MDPIL\R@P-L>-UE=9\(Y5?\V\U?N]^^&J=][#3SP::+'OI$K28@#\52:Q4_T)?\UB-33,])28Q,M!_YL`T$JQRW`8'U!=(3*'9"HN'^,N.=*0=58 +M\X@0>8G+8@W,7>E@?5$&=+?T\*YTL;XH0[I;^EB5(>=WRH2;I4SI":7LYT[O +M[/K\ZN;\0]=GC=V,89ECWG2NM9[E#GN`UL;3#E=.\#_Z.D81T +M\Y(I1J7"<6DCDAQ(,=(*X4$F(\%R8<#K107/C8AC=,2FA\/#+59D>1UO.&E+ +M+ZDP@I,1D295$A_*-*TZZZWXXXR.;"K=F'O^7:\.-KZ<))$X;R_%,R"80&;X5*?(\'BXG.\A1FNXQ&&U;'8H)FM7>_>NH4=OCA95JY/T0Z4@;]#KC?6'!0\Y_584;[UN>BM$(*>]E'YLK +M223/P(TUIDVQIFSU`#-29("IQG2VEVKL"??.MHW#UN1G6!T%)H]?&3TR(D.1 +M4?-(8A8F.HV?W["'WD/O.'YS>'@<'\<4IO3UE&'5A$6"&*P<##^/+1\BXEMH^NY8+3.T +M2TA1*=@-/DJUP(*802@!KY.N?!R%W=9,!9`;/2@2"%Z(#%[DS,*7`A3>'Q0J +M!6MW&$9$,.X4%XJ/>2"'0S`(%S>%PI9;G_,`N:59R?J%HWB7]TF`;)AJQ!E+ +M(=>TI^;6@1?15LXZPT<3D190YI2A +M%4&-Z)&]##0SD:-QT\W>W'Y;*!E7V^? +MAK5?7^`7;?GZ[#3L^_H"OZXZUY>\GLM3QGE,/U8.P';ME/.C.F_SMV_#-"[W +M>/V(+3<]\:RY7BSSP$FK=4,9Q/#I)EP2**O+>_EX_\>C!Z8$%XL3*Q(,%@RG +MH>6EEFMR@7(HM=@I%KAG:ZERA,]*6[-55`'?P$*^;K!`N""#JPLT^)].EC*+ +M67!R6V;+P^53"Y/[[O:7WK<\L9Z>IMK\:??W.4QP9VYM#J6QG;\4.,Y"L?NQ +MAN6<6AW>37WKW:89BRTST>JY"T4FE(KX7P^0\8_83QI[ST$R5O*+;]K"]RRZ +MGVBE@-;MQDMD($?2V;\CWB6U",F[`BNZ\/I[#GF$P:%[T/CI^T8-IW3\?/S# +M"6-/3VTUITT_'6NOVF*8QK]2?`N!HR$?-H_UFLK6QN[8,.O?C0RO$UT8"_X] +MC8/!XA+Q3T2.#1KO[X<_'Q]NK\\Z_/WY1>>$(//#/DXB7[@Z]Q^+RA=DVLSQ +M\T'!-/696&#-^$O"F?+T#U!+`P04``(`"`!X6D\?Z![<53T"``#/!```&0`` +M`$U%4T-(04-(+TU!3E5!3"]-04Y?."Y(5$V-4TV/VC`0O?M7C+:7)4I9]0II +MI(BF$A)?6MA5RP5Y$T-<.3:R';Y^?<(\NM8/&4F:R@ +M63&`-F(GJVEF(5.B*J4!I4&KHR$`6ZU***G5/&,F>KF6B(IO\7^G();4*]K' +MR]^S^6(Y7F*(6\UB\H7+3%0Y@R>?<^H73^0]'8%;P8[9#3(\3Y,5!$D(7'K& +MC:S*$!PJ./2Z:&RB@\9]%QV]>-I[\DO+OJX+!I>&?OV0?]V4[":X#M8/6UC_ +MTT/\(UV.7L>+U7@^S@87TRWG[:`C

YM,7'6K%)B2"A$Z!@D4 +M)#LV%=3''PP-?* +ME@N!U8[<%OZ5DJ&1#-5GR*FEOAZB?'<-]8,'":IW#-]34-E6J!_EJM(\YY8K +M204PB3(RXU1M:Q"J&502?XC<.0(W&IQ"N1?LA#.H+)PUI])!0``?`T``!D```!- +M15-#2$%#2"]-04Y504PO34%.7S&4Y7\RU-KVD?>G+2GK[Z^07BOZ1'+<=. +M-=I'+DF>ILJJSI6QCW1S]7J@QR%95J^%T4 +M+,]5>M"`]F$[_G9KJ.:YPZ[8Q4C9*"H54+139FE;=%9<*V\IYOSVJ'TD.D`] +MXPLA)WA9:7CVT5L+$SG:1Q3".87$^!.D-GV6R6BZ!YHNS4>:#5O7$RI2HO"VE0>1#:)SR!T]P1";T1 +M^B*T1!D<"6J&4`,,31#)'T8@K'"R)V^M*&!;[M%[`=!.8>24-*!PIM' +MI0/(%B[!`3RH^4;N9AB`A%-,D_IVWP>@:E\6Y8D>[I2SW7MX]-(\/.[AJEQ[ +M%E),6$@4GQ]%A1["5=M7D?.DG)+"0X +M^@71*4H+U0(B!N<<#CX$3]Y4$UG8J3*NXC%0&9@+N]P$CTE/0:B,A2V?0;U] +MA--LZ4L(%)!S/`=FT38QA,4TGT!)^U"OV6%)/[&5SM9P2V\?CJ-6*+.M4X>M +MV\=:LK=3;U.P-[/OF5X[(N=CMF80QW6/WR:!50^M<$<39JZA'UIP74C7%V'9 +M(J^9PDK1!B\"2,&2G*.D0",(:5@!'1-:=.R:?EA=V^Z*K\81EMS",('?5',68YY855`6;2@XWHHC]+X +M2!8GS]*& +MRX+UQ`$E2EZI_%9N"./,9%DD'%.25%'RJ9O%;L[W_^Z>7Y[UW8SW\KKOGV9W +M0[^C9IUHK6.ZH*T/51=J'I$NB%N$^1>U/M3:NN_S?I]VST87IY220/A.#J0+0$H<6?YC)W9R7=Q<]?KT +MR^"L?^J'@CL7IQ%=U8])=L>PS\2IT\6I0?X#4$L#!!0``@`(`&-:3Q_!LF=7 +MW0,``)T(```9````34530TA!0T@O34%.54%,+TU!3E\V+DA438U5;6\B-Q#^ +MOK]BFDH)09O-D6\-%"GEN`HI(5%(HI:J2LPRL#XM-F=[8#UOSSQ^QNXYZ7+LWZ%-,Y%FUS!'ZXS>@9Y]Q=19$&H."X,(Q1I6N-)FU[L, +M,5$OZ_3_CSNY18>_WKH_^7-\_S`936A)GX;2_2Q5FA=SA).5<$:62782;;2< +MP^CE]07LMJ^V7RI!X1.7ITL%\?5>I=,HW'9+X?L3D-O+6F![Q-*XZG +M!PR]-YN=-KJ=-KH]QOW>Q#UM`)\V@'^/VXOB\W`R>!P]/(WNQUX7T5.&T'.N +MGR0!W3EIS_7!Z,))A:0V@R`5+$3J0.0YK$1JM(5M)M,,#-HB=]Z>DLU&3H/+ +MOB*DVI!IK=5\3[\H5.JD5C%8'R(<.^U52/ICMXBSLJD24FU*&#@N +M%C02H!=<_P>UI`7"93!'89%[LF5B@QRZ$7F!?-P! +ML:&:FLY-&RBL9Z8"';`)5J2/>WN;"[5D[M::Q(7F[`S61L]R7"5!'M67]>T? +M.UMB7BGM8$8D*2>I6;JI-FA2O4)NC,0AHE2KC3=K)7+(*4++7U>"QQNG7+F-H[[H1CV@2E?`KS?,2 +M7:OSZ;P;[>BS[$+]NVS#CADM0>EMP%^Q"U80V'4N4H3V952IL#SOUI&EY\V' +MO7B&O1.G\SLG3`G:$[BXJ*C>>5(\(]Z$-$K61^PN^AO\ZY>_"5YDHH5F4O+:M^?LI<:)9!4T-\)5+X:!6;.[=:81(,P@M4A +M'90]+3OQ:7D5^ROIM!S'![<2,8O?"DD"1CZ1PP2MLN,9*#M$FP_K?ABNV'!5 +M&X(.2`FUQY@]QK5'53',ARN,HE;#X%3M_(BP^CJ40:2J6,W04%2T?Y5]"%T6 +M_.[2,WAS.[F_!HBJA%Z51ZG8];?GW_EYCCX?S=5^Z%AW2&-$6_5\+63IKP=% +MLTUFZ?R&/YF$J]\_/PZ&\&5T.[SF?L)]DZ0QO375DI%PW7\`4$L#!!0``@`( +M`%=:3Q^2'0F/CP(```0&```9````34530TA!0T@O34%.54%,+TU!3E\U+DA4 +M38U4[VO;,!#]KK_B2#^L+<99Z;?4!$:70J!K2M-]&.O85/MQ_ +MW^EDN_DU-A.(;)W>NWOW3IE7OL;I)W1Y)?-J`D^HTJO6:3422GL`*)G@^&I^/8/3LDV`$K5PVEK3M+Y_*QM:/AM5P.FSM"?=T7CR +M_^/+&(3V+VQ]W!"VO9F-N3JJ\^-L>7DWO[V?+VY"U>*^0FAD;HV#S/MI5]() +MR>FG('7!7[<_6H32V.UV)$+6M7E1^HGWE$M`E1&:7J"D.D"2X#4F`42_,1Q[7'LB[>DE_'@X>B=6VJN: +M^9"*,"4O:Z(XX0+<3]6V6"1^FK.\`;E$6K$_`"\6,"11E$Z5O(R#)=+@3CZ^B@U=Z*W0S,C(R +M0./[ACVM@E8A`]F7D1OMI=)AV3?%Y5*7'8R@+,GNR6`!\N)0;S@P@.*ZQ;QK +M[QX*]=[8@DE,+)IA-[7LTTR%N")E<"V;EKMLHEQ*=XT'+1L,G=0&&D,]])74 +MYT!2"M8)[MZV2`FL'';3S4,!90#Z>G[V[4(`I/R(*.%HSIT:V"8P2D;] +M\.R-RC!K.].R^]T%!X;B?SUX+^+N[UZ"?<\$._K!-9LN.=ZTB=(B1.72L2B' +M,DIVI&#K'`D7H!`[DAR19ML$"6EJB(J41J>5%L?WUG2,F2O6X#!+') +MX9P9GC.'F3OI2K&X$S8M>%I<@O:N]@Z(6"14# +MN39X5R`5?!8R+2#CCE-AM:$#&95*7RO!5=#31L!&NP(*7W$%7&6L0EU*127S +MC&]*<86HE-'."-X(.FY]GLM48I>(%"&IV9QJ%QHIP-3,JTP8ZS`GUA(R#*N8 +M$1CDWE#22ALQB]W%^E,L9A-K0`36MD[=)LE;+A41-0EMAS3MQM&Z01#LPR:, +M+16(+2=I='RT,%1PD%8J+-7WC@0INCR*P>[,+H3@-W86>X#Q$NZ&TV]I([7= +M;BBO>FOUM8QG9V$5AZ9=QADY]!/`FFYGVVY$0@E!_/2RX:4(%+*8O9.O=1G= +M;H?"6I23[2$:1+23B!:5]/;F54"M>9LY3!Q_>.KSK +MU&@;.V'.<&5+E#;&H!)37I:VY0TMA8M!H\-L^B&J0A/4@C7)1$ +M)C;^_9W.U-[4VI(&HAD<=1^YH?1C=)13ZKOU>CMDJSFL;X?Q^S[/?GG"WKX_ +MLV\.[E("`<"?YX5.Q)BFCLQU6UAJAA3&W4*#U1X;M)-I)Q;>R\A7@M'@1U-5P([6W[*=' +M!T2!X.K8>AJL=DXY\B*K6`,QS:%!_6N#&3'D4Y0E_46Q!EL8I%'D*66Y&[I< +M-.7V?+OJ7_R+:8>X)(N/`PW3"S;PH"N*2I*$W$W'-^7#JW^2-E+F,(9QF*Q$;(5#O36$$ +M.N2-=\>3-(.=]G@3.U!"9!@12P["/KC:5?<8AW]V5BM8WCX_7`*<]>?9N8B'GE[H4:TE-Z.])9GHI[F'L>U1LQ8?#H6TK%@0QA/V3C`[4-PKX4[1%&2*4G#%G!?+5-90)]"UH(U`OM +M*G-M:R2K?.O\TKLX.>^?7?:'`RH%[#(1=ED]@&,I<8F`0L7"I#.IILNY"58& +MGF;:.OS#G!8*)4/&LL6B%ONL4GD3E&C\,4MYJ?"KM)#*L>%F1DMFN!E!:0>. +MHTRND;$P%IQFUIDB0-NY#NT^+):N\R.).I!$PPFTCC1P1VI6[;>)+M(8Q@+:LC/AUK4/9*?% +M_ODRGD!_`C-=((I-D&&@/"G0$SR^Y_])A@Q +M$6A'3)X;BU3?T2=TB[(>99&Y)%1,N1.L#.#"*TK7^(GR%*H%`+#"6?^= +M]I&\AI]]P9;7>U2KY7581/Z@-3*\&JZF9/O$Z`QH"Q$YFL=-LW]8`C_&G3\# +M//>X\]?!;L"E&KQ`7?6=+;)%N@>;&SNP^1O`O=V-5]D-,JBB-"@_!.=>C0;# +MD^'@MY!-C))O&XN0=\2EOC,R%96-@:I.F?44">%9YJ;=1:0VHG]1X@[WN:CB +M5.6I?7LGL<<1\^7BL1\J"B%H1*2^`R9/AZML$;?N9XK2#H+T-.3\K:N';T6> +MJY;[.\C'9X!]"NR_8;6T"^#0$Y7`E'_E]X<3R(@](/2^];XB`B^P?W,[@:=T +MC&=IZ%VP5%'5PGN7"2I.>Z>CJ][Y<$$*D7$!ZPXN^O^=/'!H)C)D7%ONDM5# +MV!_:$;>A_9JDFON3W_=5S%.6H6GGWJ+>^-I]U+ZCH;W28TCH_8U>^]$WJ]Q]?9$?/7'7QXFB?\"-O9 +MEG_H8HF\H8L.[L)>F&X=TZV2;*B!),\?X5\;,OS;VX,Z@X?7O^X^6H\Q:AXO +M!EY+$[]3CXL(WD2C[^`#6=$E[54>!.D/URO+OQ8RNJE:#ZD4=JNYT3$VGB0Z +M'Z'?\\+5%L??_7[G5C1G_A?'LQQ"T\H(= +M-6%>C7T$?0_^/U!+`P04``(`"``X6D\?&GI)&((#```;"0``&@```$U%4T-( +M04-(+TU!3E5!3"]-04Y?,S`N2%1-M59-;^)($+W[5Y1F.03AF(]C($BC#+M" +MRD`49J19"25JVTW&]_HRR\>+O +MV?QN,5W@5WS4?.S](624YC&'#\6:62UV0?+!JXMAZ!]^$:L\3#EHSE(?J@>Q +M9D_M%URDY/>+P]/1/R1_.HY7V5"PT#3B61R_Q/O^X;6*P1'(Y.'[H'5JWP<) +MN6FD$8O-;]#X5]O&;+[+&N.I>B7&J.LF0'/Y-%G6QQ#N7;&1M>,J&5?+ +MCB%FEH&Q.H]LCBG;1$2))PS$?(5,8F"FVAN[SS@&*RS`#X![7!!LXN-R#`'@ +M9TUK6+\ID['K2IL$&=,6U.J8`A3#D@4VI'`1:%X&*%-8X]9.2*;WGDL_X,3: +MX0+OEEMH%7`-NX[8MP*G9*UCB74K[7;9[7!97W-\7=22V+T6$[;")HYQV9)J +MT-,1KYH3'``4J@B=$G"W4KQIW%J&3(,C#I>`U!L2Z99.\BZ+QK>D^SK!/A?/ +MUTO:VA^[AT%G_S#XB;DS96FQ&*KI!(T5UC!LQ5-<$05LHT0,:L/U*E5;$"LL +MLWMN@=+X98]?,"5*%6ZK51Y"<"GE$V1*2`NI6./0&NGAF>-=X3F]H5@\]CO% +MXZ#QG>CLSR5=GDLB&SB7!.>2R!9.U.MW2>J/TD$FCXOI[*\2P;5&-5`'S83! +M&R&-BNM>8V4REG-TNB6=W^WP.#C3P_G2Z8*YP1#?5`;.=,+YGU.E)O_1"OW#WE)/G8`>I[*%* +M$W5RSE/F9?2:/V!)_+N[6$;*P+XCED9(V+<;52"S/2U51O\?#=X8@1.BZH>G +M@#8>U49<6U76Q\*'UF9/+5##R!P'Z\,H*^4J^>JN>OSG=C;=KOM(_KX4RT0H>:S +MB5^>D%\@LGVP\FW"=2DT0@ZFW>IW>J(UK./4U=EM/^CYO:#7'M:F2#]%YE_O +M;R;PY_1V%``` +M&0```$U%4T-(04-(+TU!3E5!3"]-04Y?,RY(5$VE6-MNVS@0?>=7$-T"M;.J +MXJ#8E]8-X*0N-D!N:-IBUPB0TC)ML]5M)=J._?4[,R0ERI+3;+9@DY`)[^$KF7!Z\DT>C$V'2/UG;ERCE>.V=-'FP`;1.WLA='DJVE +M'T?3-?.;V-]T$##>_+<7TXF=>.+Y:U:HG?%7F*FDC;GG;8V5&+!?][:-;'E8 +M&R+:7CXW7KNT_4T!>7A,:FQI+7C:J/+09''RR]2WW/6D4KMK5_D/8JF]K9/J\)Q>_H_7'>B6 +M$Z>9R4]%+V\\7--78W-HICKI>2%P"D4EGRH=:GKJ/U +MH6_JTX#&7`?SQY+&$,,AUVY\LXZ9N\94+M(9S=XU3#FCMB3`Q6Q.7LZ$%GQ> +M9`G/4OM6ZF(5Z54AN9B(1G[:&-H99,`X0:45B64"!,D"TBE2RJEE +MWB<[P`\I5Y0/@%.0#]`RY)<5O3(G +MCZJ@!$@35W![-Q0U%BV4-'356OX^B6ZSK4R-7$3K[-U^SAHIX-,XBWX@E)^!D-VI1,6B +MB+0:6Q*$`U7VB5D;-=(2R\?F/K!K2+;1O]==7U#'$*8JJE*`R$NJ-HIV]W0)&)L* +M63?$SS,H1*@\#JE3A01F1"KB;)&M2GB&')N%@=H8C2QM>("UBG +M7=8BTP&!!%+RJ=0;";5/91%ARH'9-32HK`"H$2^S51%9:^P=@M<%I&;HVQPU +M!WL"2M=^J_8HUO,DVB=-`/.OLV*F4H@-\K)?W'U7LSK+>2SG&NRAY10H91PV +MCJ"3^):NDBE]@W@W%BT96"`TBK)XE:3V2SIH+,$(*^3$EQ8%[#9UK1^.LU&U +MUA'6".I@!+R.P`9^$L#9S;$C'R.9:Z;,/A&)4N(^X: +M#T_\":QS@JU0>RQ='UZ!Y.+@&633SN0][#H8Q'1+ +M0NB;LTU;0VT\YC``KNH;/;$0H-Q]U+!%Q^X9?+CN7/'B3LO/GMD@:)<\02DQ +MM+\@AK8'U<$8.>Z/@+,`QPH(CK_QGI=8BIK,,[6AT8D,H1QG.ML^C`,YO +MP>CU:8)_\'^6:BQS-ZK:LG\VHWW)QA>&(0&N#R!N@S<&#PW-H;:$>=+?OY!* +MZQ&8T^PC,WL/SGF6FAVO%";G)$)`9Q9$]\][RI\-Q[ST>7=S5MNKF%P*O`N6.[`0)8W7SZ= +MC_G'B\OQ6](WIG0'7">JFV(LVEY8HBYA$>B3E +M*$[\WWY[3RB/[I9[#R.QM]U_K]:S4!G\@Q^"1FZ(Z +M2V1\7T8@T(^7+L2@K@B1%"/5H0:0BS\4#XVMXDP54@HY1M*)KQI]( +MSM9\CWZ(GJOH>7G][FG_8Z1*"/E*O,2%LN*"5$?BD3/\5^JGAOG?H_T` +M190G/@P@E`XAR97`$Q;8-B?1<#)D`;1.*MM+D1KX(+$@,!&I]4&:FUHT"9R +MU?]JXM24ZB'T`>#0BA2;G+;H;53=6G0!)-6EY`I%?QYF;AAI6FD_6&:JS)S^ +MA392.*X<)\F%KA,U5(`\:4Z+L7\=PA"_GRUNQ]CMB>+$EBB.]XI=V!U=U#AL[0T3 +MY^?[CPM_DQFF*TOOC5"*K5C.]*.CS8E;IR"/6,`LIK#5/7'KY9`1=9A\A1^8 +MSJ#2.VIJ(&1")=P:;DT;GCP9RU_O/X;6>+^_=,@6M_>?;T+\83H+Q]:YO5]B +MJV01_P=02P,$%``"``@`&5I/'P7E:&5B`P``E`<``!H```!-15-#2$%#2"]- +M04Y504PO34%.7S(X+DA43:5574_C.!1]]Z^XFJDT;0EI`V@>:*C$L-E1M9V" +M**QV.LQ6)C'$FF!W;2>4(O[[7#M)4TIG7C926]<^]_B>^Y70<).Q8<8%HPIB +M^7#+!35<"AWVRB,2IL'N<]PG[@D7P^G7R?G%=#3%)?Y5:/:>BSC+$P;O'JA1 +M?.FG[\C?T1E`MY@CG:5J&"WW:XVW[Y[D,C\-F-`ZPT"6X_#R]QT-@DM +MN%V?U)Q!PQ:\Y=EB+`X:-"Y]WT>:R?5XW"%ASVG:5K9JI,TJ-MMF6.#Q; +M9&SY&W7XS!J%F[Q.XJS1.%N+7+/^1N5L+7*-KE7.MF4._XBF9Y>CBZO1^<2F +ME%RE#!1>BG6@(31FV`CM8*68(5"1N(/5FQ-[76X8&.0H"XEL%!*T;G3^,'_F +M)_V7?Y_%?O!"Y[R8\Q8\IDPQ:+DUU\`3)@R_XRR!1VY24GN!4>3?&Q]:=#?> +M.4=?X?U2%M-Y9JR%-E(AF@N'1;4.Y:$C/$XM(%:,&D1(9:WX"I=4$\%BIC55 +M3SZ92*>3&L<@2J_0T$H/^3!CXMZD-[VPQX<@[ZJ(:*-]0D[+6Z/Y:#(=75V7 +MIDPIO.N19QG4:^O?7>T?G)S`5@CN$$_%DXL.+[@BE-A="6'T%M9L"IBB00A#8;JOYPC5#.#U]Q#OD!.-%;T +M"56APPS0M\1F`T.EF,F5T%59<'A=#39BN&]CBOUQ7792[NV?[^7[DQ%%L[8[0)'FUN7J+6VT!'?^GZ\_N14B: +MU^/Y]>59!'^.QM%QR<]BN?!C#U;5REF71C\!4$L#!!0``@`(``]:3Q_9N;H@ +M-@<``)03```:````34530TA!0T@O34%.54%,+TU!3E\R-RY(5$VU6&UOVS80 +M_LY?<>N,Q78=)QF&`4T<`UGF;0'2I(C;HNNR.K1%V^PD414I6W)??OON2$J6 +M':CW?W/'<\NF>D"47_J="3.9_,C^%<18F*16R64@M0B4BYD2K6 +MO0,GR7KSH_[#0CC)-C^]I#_\\^KZV?!BB(_XFJ*2[V4\";-``#R*N$EEWIT_ +M8B\'YT"?]F(T4?$"FC30SCM@OPO_K3+3JHLF)/MUHA%/`)J!RL:A@&9[&K?\ +M2\LOR.L+O1P`+@<6B?MXK"I`7OLMVBL;N^8$80]%[D/GWS!VK\N= +M7Z^MJZ\EIYM;0L7#TM;OSXJ7AL#*>E4*UYSJ_SH8GM][G_]F-CUQ[)SDTX8%9*%#@F&6BB4J+&(521[JCMO1"E6CT,B;IE5Y*T\//[YY?QN(&>3D +MK@3S1C8($M8H'A`L/F),G&!W)[C$URUL5YNC21(6UK!I%D\H.#8@CMM>!MTD +M@4E9[BS<))57\S.Y$'5$:18MJ2+*#4B,@A_>[R_$7_)O],CMD_N!UAJ!5`"G +MOU`KU)EJJJL^2\LD&3E'-@K90LD`VIVRGC'8_+CI:3Q*>,HCO:O>^1QLCW9F +MN]=?)?WV!O=WV%45?'Y:RC\4D[6*^]&1&D3,T4,-D4(54[1%4A`R.H>0?211 +MXMEEORCDGAT6>HTSKN5%1>6>[&/AUM)DMP>]`]FWA+54R.'T%-98[D@//!=* +MJJ3"9&GLDAN'983%%AF3%GY_SP^V9D_'$E,+XRAKSXJ*5F-'*CM8.5;J7?`P +MH[F:LBZ[4C89D6];VJ2NJ9HB1>D-O9[*5!OOL[/4IZK4S.Y``<^<<;CS",/A +MCL(F8OJ#]'Y'@ENO_;YYA>8IV$5E\'9%3\8[HR?C_R=Z7J_UC6D9R9"G5`+4 +M/30]<^Z9N3XEZLAS:H*P.-+,8#2\>#T8NAF1IAAN.65H3&&S.N&:.+<2J0*L +MNR*F],:"6!TANTJ9/3[OU[+Z<*T8LTF].>L`6O`'#WC$TZ!3+]2U,E8J+;Y8 +MM4IXVX5_<`J(53P,'1([^;AI+J7QNTPB$F@F`1!EH9%8CV4\JUD"8XP:"R2? +MV2"Y3A'/2X7QKD:))I(./`PO%>.85A'ZY82:;N2)+2(E$;]8".`+A:#"R#8M +M.T"JCS^($MC^F5!9&UV/0ZG0^X!=G(\N%CUJ\[YK?0:S$JJ#_!LPLQGS#3"Y +M=*/SRM=A<0^W`.\8J1QCI#',KFL0"ZFPPE"YGZ4\F7MT)BH+`X_+-`NMJ2B, +MS4@@J8#C]AT:9"+G=!S]=U`IP@>^OA2;:-^O6QN8VNS7]?2_^GTS^^N9-N>: +M<9?^KKPU*1#N]H111K,IM!8!27!B842,"M`J7+@9`;K01D1$:P3'W;N@\6I% +M2/MFTK:54F_T(JV=!QA='$I/Z%EO9K-:^3Y4C0U'1P)B7Z91S(*7Y,C"$5I4"T=QCR3/ZQ]ZPQI_G2"U=R +MZ"R6_;-2A:9]SEUDT+R;[J>A"&9BB2JP!B?=3T='/^_O'_WX$S2/GCPY;#U0 +M4_!FLZ.BK$?=J>E(D45EWFV5D.H$W@BP[S)CU\=3FW=WAP?=WEZ''GB^MT<' +MQ]T=>8RQQ=?2.,2:(",-&"-4H#-IJ"6KX157;3-ICK-H+.SAAC>QP:NSI\\N +M!_9.=A9CU(U(8V0%=M%+;H][5R5)3^/V0W[[870KXZE!;C?'F0&-@.&]]GBK +M)<:6A.Z([=4)L]=?\!?@$W:#&82OL4JC$T:W+RLG7":$75\A0=['A.ROZ5#5U8+$4H.4IS?$;E'7?[/F$';<``J*7- +M+J1-^\!NN*:I%:SMB@L*%]BEK^]R)JF*YK2VW/^%+JM!>;971SL52\Q$%\#" +M7BJ7^!^O58WMH"V%G,V-K@6#%C>!UAR>X%+(X\?0LIU_-5Z>,KBZ +MIL=^I\F-QF(9HI[: +MG*XFRQ2U$Z%^EZX-(8>O7]R<#^"WB\N!=PCW2[J3#JS\DQ6V:?$O4$L#!!0` +M`@`(``5:3Q\&B&.G!`,``)('```:````34530TA!0T@O34%.54%,+TU!3E\R +M-2Y(5$V556UOVC`0_NY?<6J_``U!Y>/((E4=E9`HK4H[;7Q!)G$62\[+;).& +M_/J=G03"2[:Y +MX`'5/$N!IB'0,.1&\$:UK1??^I^Q0CAI'B_WES\73\_+V1*/*$KFDVN>!F(; +M,KA*J):\=.,K\GUZ#^89J&*="-T+L^U&,%`.&,V@;'ZSK>X?L,4:@_:LHKAM +M$,7X`RAZO8P^"75JI[:;OX;P1I;4*;7JP&W5>!M4-;<@2W+!2A-QU;);'1QV +MX2;CU3[Z:A_^`WC#\9+%6=`S8T/T'['V7/UOT^7]R^SY=?:T,(TEKS$#B1B> +M,@6>UG[3QSX.D?;M@)C;ZN@V9S+*9`(:C>L!(R>#E44=9>WWX-!HFGDTFO)( +M0R13Z$L!E0QR00,6`D\M$-.T4/="VG7)S[/NWH:AZL1N[&ZMDK0FQ=C*SC[1 +M.AW@"D]Z*]/_3:=IZ<4Z=A2*Z2-GH#/8,&(B"_2&Q<,!V/"T+FN=\8URFS0O +MAS8#<1ZWL)M4B+;S=),5A\0)O/ +M'0/&/00I>V]G(HLL?9KG,LLEIQKGB%?,F`22H1BZ^VA[YIT\>^\Q0U$:GV)G +M8%E@K`!MTDSWNT1<$*T89#C6MLP*$KK#+K1SCJ8>]Y&RXGKKC3C2G4II +M)LC,J*1$IPA!V""50/\4Z +M1Z>P<]-[OH_5H`,9G"3=U.NX.!B.R_S8,U-X[50W&S+!N[/>6%U1@ +M483%-ZNJ1NXLMO[@2Z>RTN%K*YQWQS!U"KQNMJ']DWMZ>[F?PL-L/OU2-X4% +M6>X&#E3-R?;$KLH_4$L#!!0``@`(`/I93Q_6(^O&*4Y!,LU;7,#:LDE +MKH3$EV*(6BYHL1=L86RZNR8)O[XS:V,#2M)3+2'MQYLW;][LT-.)3H4[$BJ, +M>1AW0`D-,G]6P+,(PCPM=IF"?`T[KF42"M5KEQ&]^*O[;RR"6/GU]F[P>SR9 +M!H,`E[B5PF6?DBQ,BTC`C0EY<>(;-O)F`&`A]Q(I[VAK>38DF8:M#4]^'ZR\ +MT*US'&IX']=KFU37"8]-QH6ALHZGE(LKKD5#=@ZEK!]`Z[SN@Q_T'P?3V6`R +MIM+9+!9H6Z&33"CH:>V>$K?07.T:-^GX>'V^R@^"&J1`(\6!IX5`NQEM;K>W +M.JYZ0"V@>*\,TSFL1!.A3M>HP``<(^@LH'0&5`Z[/$K6B8@@42"%+F0F(N>B +M@%H_N?&Q3FAT(IB$_U>1@TL"NAW/AT.;DF3HL;GUEW16`H24N30D/%%$43%L +MZ_A,;+A.L#;$;:3@6DAD0RKE91&B!^@@E]2EY\^Y3$2FT1\" +ML`9@UZ17_3NU%B6LN:J+1#1[X[56:,>,N/_+&TV'?C/AU91Z74:3@2N]VW<9 +M@&,^UK9`A3PU0N&>#/-@]0K?G"]@M1EBX3ML*G6>?6\_4;M:7:8.RUVJ[Q!G +M(XA^='@&+$^J&31_/KX/WC"8=`!,%9NW9VYS8449.9D_]GWX.1CZ'8/!IY?O +MG="&8[4R6#/:["]02P,$%``"``@`\5E/'VRDPX6F`P``;`D``!H```!-15-# +M2$%#2"]-04Y504PO34%.7S(S+DA439U6;6_:2!#^OK]BU$.G"W*)[FN@2$[J +M2D@04"#57>ZJ:C&;>B5C^]9K8OSK.[,OM@DTBLZ*A#T[^\P\,\_.9J*E3L5T +M(=OT9WK3-F"#UG6AK6[C>O](FSS`[D +M_Z;[Y-H0>DVKZ7@].42*WE!XZ"?PY"&?.LS>#DJA.NJK>X6=UE/@V5,ANJV$"A2;`B,TR*+C2,JY2K@(3[$)ZM)G,TGQ^ +MU`F%(%0R8G.MERR9=RSD1]3M/_+;I0T^]B:I2AC\FVSS>B(MC)Q^6H4#>$D$ +M,A^L!HAI@ENR7,L\\RQV>,B4W(H=;(_,QFQQVV)?*FJ<[PL\)Q="AZO!R/5* +ME%6J*7J))PECR.R4:Z'R@T2)20T)1Z_J^5G&4F0:RH+'MFN8.+-`6.>S6L'] +MXWQ.YU;G.91[GJ;XALEEFF,PW26!KQG%P2U*%"FB[]CVV)Y]WUQ>8$Z%DAQ' +M0"D;87HK)"[AR."EZ$,:*%VI3.R0\%KN)78_/0:^7"3UW`R5()+"B"%*\%3ZSH*S+E*1>WZ7Z*P +M9N<=>Z?H`Y<@9.+%JP;'2XP!-9Y&Q\#+N3NC4K]?]CB8H[_"Q6H>=3>BF>\T +MX,?N!J()/]3[8NRN@V&#WXTQV,N/[KCA[9@!C,S#KH>M6&HB]P-+"+@!AM>, +M?CZ!JS3>(G6`EJLQ:]J%QJTTP=-7JA4N(B#F3Q01\'=H"*@VWEZ]Z(\`08W. +M/>42"ID;BU$>]WM!E\>)+A#KUD8V\Q[WA,'"!0[M@IF=N'`;A&AT=YSYAR** +M()ROES<`9F@ZD6`1O$9R#&7BE&/J3G?3>%],UOE:Q.7CPUT$7V;SZ,:YY,4H +M#H`(T9MQ-3I?9R(*2C'-8"8D6AS8'^2RT$3R2*[[+$@MI`K$S&_?\-\;;?O@_ +M:(0Q=XW3\'FD[MKCETI8'1S%YH: +MV,A*;.,>I82Y?9PL/MQ-Y_?3VQO*E-UO!=?H"*3@8VO#,J\`R;4A?AHL1`D8 +M8;P>O-PJOA3<(KJ@FE4JP-7:Z0S\%O3LD9V0WCT>;1"F#UT7015:]0*&:V$S +M+<6JRZ;K4]W-PVQ&?B16EPNME2;I1DBA(TN0<^E1:?+DBGXH<^M[^?*0OP_* +M9#?P+!@)\6-.6,93",J`,`JK%#>[*$G:/KQ3.RV(B57.8G2.NEAI+6+K*"22 +M$!5'4BI+B)6B?"`$B7J;C7L0GD^6VBI/-E:[-+.8JBM:/A6YLU?X]\7!8)$G +M"MM8I3%JJ"?T5R;PL4)&Q.N9LM-,R3[6@JK7YOLMQ-MZ#Q0\G"'AL4/&+@.(E.M@HU#V7E/ZXP +M,A(VX#$1:]PBFZV-L%'W_*EQ/B@WN#BR9XI&JG^H&!6*+/'>:';ZP?>T@50* +M+6KCDY.XUV`M#9!WD6JURK`6Z*61-JI]:?)/X\\1CVD:I3'RC0/2,-,?WU_/9Y/CLO=KUF]KMZ=3&([P(.FZBZ&<7]%> +MW0C;[+\-1JQBUNA#6<['&XB]W(6SUV;#AR,FR_\RA$D#&F*+$K +MHI.^\3B:8@)57"',S;!UZ$Z'YU.0(VC)><0`_T-".4=#R@+Z790[2XUGQKIY +MD3?=,$`UX_5#A)RVCB^#H%U1#0.DPA\N_A2]?;C[,.&?IK/)9=[1*NW&CGEW +MWK`_4$L#!!0``@`(`-Q93Q\0GWR\J0(``/D'```:````34530TA!0T@O34%. +M54%,+TU!3E\R,2Y(5$VM55UOFS`4??>ON.KRT#!*U#XV%`EUF10I_5!#JPU- +MJ5QPAC7`$3:,\.MW[;@A_5";5?4+<'U\?.[QY=I77.4LN&`RR6B2G4)!5<7; +MHZ.&)4I44-2YXJN<)U1Q4?JC#=S/CH-W@(@@_?!7P?SGY=7U?#K'5_RL6$"^ +M\#+)ZY3!P8;+RP[(W>0<]'"*YK[(U>%%&($3NJ#C3FN?HE;#'MD4^R(WG#1- +M#\UD^#'K^#'M +MN.?KT=:B/=&]3?$VIWB;5/Q&5I"(8I6S5N?UAI!/I-YZ%GR;S,]OIM?1].I2 +MEQB),@858GC))/A*!=:R(1:Q"H"6J8E::VQT*:H"!F$[T/-D$"ZB]NRP743A +M@]$Y,X@\`O#2DN*WA\UZJZ%Z7T;VCPS$Z'-3A +M?(Z._I!?-61G0FLA@^;^&+Z"A+"Y/S&JH`\M(C#175UN+TR2CSCTBK3N(]J< +MCTN;+I\$@$NXO)W-`-N=$@)D0?,9:52*M$^7JCQ(XLDJ"_+QC +MJ89J2"*J"K6`#GJF4.6.!:F`4BCX*ZH_X/,`:257]:^1/^+!&-=33>D^%5;4 +M4L$#(RE?+EG%2J6WTHAV:].^OX`QA]AD$HK*Q/+_"F9?;JICD4K!#5&F^H)-,XSUPKDQ_AQ?5LTM\JNH?H7A..'YNT;G0. +MGKKN&&-RPY`*@.:KC(ZQTWAF$)R#,[`&A6[KWNFC'HX1.G)@,QMZ+3@C8OW2 +M(-V#QCM-JHW=Z<3^#[ +M=#8YW1P956+E)2YT]LT8;KHC^0=02P,$%``"``@`TUE/']ZROXN+`@``Z`4` +M`!H```!-15-#2$%#2"]-04Y504PO34%.7S(P+DA437U444^C0!!^OOT5$\\' +MO51,?:R5A/.HUT2M$4WN#+D&82EK8+'+TBJE__UF=XM"J_($WWP[W\XW,PPE +MDRFUKV@1)D&8#"`+I&`OP'.1%<-C$QTF?;N+(T`VS_#9]OY>3VZ\L8>O^"FH +M3;XS'J9E1&'/G+.2/7)+@Q0`LJG*T3^X,QY]$8I$_OH6&QUIF +M6ZS:4:L:N8>MK%5+\+.8EGS8T;1_N=[Y[?CF;CRY5B63NX06%$1>2L9I`6&> +M/9>2=JRT%.F=,I32;FYVB#9+&P(>:;C:PIML,NED)'FLZ8YA,=XF](^.%.>4 +MM(1TI2TMG]-EBI=I:;8IN[)$Z\)7NOL^9I"O^XU\6Z/MZ<MI_\S/@I?IDU^4V((ZF*[8T[KN^?-Y&40-R3AKF$PS +MG]Z9?L-:C=9G?C$77KEX6 +ML[-JJ0#7"D<4+/V09\&XC`_VZMJIT10X@RT('=@%1PK:K*;^%[DN.)?>9``( +M8[<6G6WJP3O6FG8#5Q]QJQVR*>GG_877+#]L#6C+H0(-?H5\046,TP`L_F*P +MU"BIMT#```7"```&0```$U%4T-(04-( +M+TU!3E5!3"]-04Y?,BY(5$VE55%OVS80?M>O.&0O29$HV&MJ&$@Z;S#0Q863 +M8"M0H*"ID\6%(C62BF,4_>_]CI)<-TBQAQF!0QU/=]]]]]UYEDRR//^3HVZ4 +M;JYHUZA$R5/ER3OB$'R870Y.L^;7^:O7L!?XS+KYW[Y1V.>`P\+WXQ +M3MN^8B(Z:54*YKEL3HK%>KWX>WE_>O96CM778S!C +M%?^-1FU\^#]PKN5]X[9D'#TX\TQQ'Q.W$<[*"4"T2&54V@<>\-3&YB!5WW9< +MD231RM&&D4_9?12@-?+QLVH[R^>TV=-IW+<;;XT^0\&;?KOE$,OBAAOU9'P? +M1`#.NXL?("!%[T"/<8)T8N=[7U]CAU!X8)>HLTIGE)%1P0]44^#4!U=T'B20 +MJ5'!R!#<@S)QB.7[;8-_.;Y41ZVO3&U0,>J1<)D5E70S0BE:I8,OB_OQ[B52 +M@3G%ZGJ@2CG,AK?&.>F!!Q1J%5HQM3?Z(K=`>Y>"MZ3L3NWC6$"4X9$(,:F0 +MRF+EF'`M8?J8>YJD(A1?>VO]+EZ-F-YZ(L(S))9S3'*3I-GX]!GVT3J\>//P1UZKQ5\"5F0) +MYH`D,H%+T,+@3BO4V_8Q91CJD65$\\(&E>+=`E0T%1?#_%'=.RW=QKN]LU@V +MPT#B4GB>;LFT+5<&1:%]@2\PG]DQ%S"*:BA@`\UP(%4G?$^ACO),8U`.'=J9 +M`1;]+-#.H-#`.+*L2T7#`O!N&B+]6.P:HYO!$U7[)X0-)B74CJ&/_2;RO[VL +METDN4FYF^@!*0,;R2*M0TL9FLJ1SLG&&A,*B'W8:./BG[5XVSGJW_6X>]HIW +M8$VDKM"HO-WS-A\S")'A(*N#S(<9]'6A_<74WW)L_BN+ZAP(:QE@)NM]-\@[ +M_Z00^-@3JVCL?I3@ZF'];D&_+]\OKG*LZ7I47, +MX*3D]I(3$@:3"P!G$3^4B=IVP0E<*!^N;F<=,@YF@*"LQIAW`['W/42FY4.6 +MZGU$^!92R^P(LM>UJ@^U;QKQ=Y;,V60/567:=S7=7<.S16749CS`A&^#:78< +M7"DTU;X83/LWP^O9\&IB"DYF"0,I"LUS!CVM_:;`'6RR]B$2V;+03(%&Y+;) +M(![MP@([S.+*/<00!&68Z3S&E6&2*30!\-RF0$D6XY%0Z`2H+#.;/I:Q2LLB +MT@5&>:\%9@?Z&M_95)4;#Y0H+60)(.]I>9VG[E6=B/ZNI/@17W2'LBC/"$ZH/JVPI&F-$TAJ8KNMX&=6R5#K9G +M=M<*6H8[9CF2QO@Z=UIO]:X^=E5)'X7,RB(LI8BQYQ@9SF9W;^B7G".,;)ZECN^B:BN27>XVU< +M9#QDA"%WQM#$I2,0N\;!K;2Q7*$PXPKY*Y-]:4QFO6SML[OJD>]BQ9Z9=&$M +M"JM`:9ZFAJDQ:EAAR:60Z+/4"J0+\=R(=]&^>Z?"E&!R.QH!AF@A0&4V4)BC +MJ"E6I3E0KN'+@6L3@TM\@[M`9'F`I618!K/HVCUP5<)Q/.#@R5GLV6DY^!&, +MKT<#.RG+^5[]%G#0FAGK],\(@&!TR?80 +M!&[H]BV@O&J8%U;`VGCO`>B^N=NV5UQL2$/^],[87-H27+^TBP3*>MV?F\'D/.EZ"2:1V`UQ#(1O8[7["WV^F_KX"'S3R_K3_X^'W^;C";X +MBO\:T6>_2C5/BDA`+>4VX;/VHL;0&=#33&_(5_W/T>D0FG'6`LS(0+.I>"H: +M536*6U&CD^:@5/?:WX='7GOY4IM.FJM-[4@7LT2@>O12.YQ$F_J]CD/S-J:K +MD&WS_GU05;T7D:]>@W45<#7OMW!=O09LKM,L$2N`>Z<.U3S"T?T;T/K'P\G1 +MQ>C;=#0^IP:RZ4+D`HPNK%0B!R.P[UQ%<&>D%8$VU].S:R#`'1>..)&WT5+F +M(!3'2I)=7B0V)\K,!%C#59YI8T6$_]H[(53)0/)=TI)\/,6&GK7]4-<&TM+V +M7<@\\V#E8SM@N/`"0E+0MC!)( +M`\J*/%*U?&P\SH4E/)F6RC)\(5,*$)71EMQ(@@]D!CIV&CYBFQUJNZ@(GH*] +M$FM!6?,DT7-.%4M%JLT:>`Y*B$A$;390(%:<.EM&*?*GU[)^F*&[M4_%HB`# +M'X%B99UV4EL;KLF4U[+?_W2YJUV&#:Z*G6JIE:HP&_',#YY>DI--@#(Z8/Z-M7?P)*JV]UJJ%/MAC +M>=$<]SRAW84.A"Y;1;*\2HY*JP+1B*.=W&+.*:MP'=[A^JNL1!YOD*W]G-OR +M@]P\7:!"EP]R0\9RY?5W^I%,G?33P^.UE:G(]SZ5:.NR+=K73AT'5E*DBOE8 +MC?\27O0!O+`$L%]SF4NM0!7I3'B\48F7O<`+_T,OMGW`'.L8";Q*1%C(BQGN +M:+CCZQPP3TK)KC,W`%(+W211#A@"IQ(:_BGR"U.),R'1Y%4/[%E29@VVR["^->*`K/3Z<)^[NK_3]*Z,W.ELG9>#J^&)\.*B:_[^_OK]XQ +M^3[X<7.\&05%&.-F/_9Z5EC< +M&=CQTI-SLMEL;"=GM[>)M,B?'4Q$^QQ-"[Y2ULC09(OQ& +M,')&^W*&,]?G-1E?7AP-@;;2UT`_]VTV;\%]^>I2=,G_"U!+`P04``(`"`"L +M64\?...L-2L(``!X%0``&@```$U%4T-(04-(+TU!3E5!3"]-04Y?,33Q29;H,`"+BW1-AN)5$G* +MCEOT?OL]0U)OMA/40!#+FC?.RS,SG#GI2G']0=A\P_/-6_;@N),YVVGS9&N> +M"Y9KY8PNF=&-DTK8V45@F6VFUW^#&%1)]YG5UP^_W-U_?+A]P%<\&G&=_$.J +MO&P*P;ZJN#/R.=M\E4CE&/LP_[!X>+QY7'R:_WBVU;)@YUMN4D8OW;X6DT!6 +MB6IA8?W[P]55=P\>37TY?#ER@@Q>.DE=B^+IJK/?KA]/V?GJ_J0TV[T+LB>)+,+ +M[UBX^/OYP[M/MQ\?;^_OR.')?5D(P[;"6*F597K%VLBSLVTVS:9+QE7!P+Z5 +MNK$3MN$%X_!()2G46L$ES&VX2Z1C.VZ9L%8H)WE9[IFL:FVM7):".=VE@ML( +MUEA!NNQANG!C^-XF>%VPG70;"._L634J)XTV2QXWTK*<*U8*F`/9M='04EFV +MVPA#VC2K&O#`&]K`$,L@G%!6;D4GF93"YJ5W +M`^.E$T;!>%#P&C1D(&G1K!`XN\ZY$\-S.7]L`5?J52+@[WUWGA1&2[#3>9:" +M_=Y(L(KG.AJP%#F/[B(13E8B'L;I9*",PD0$IO^)'N.!$*B@M;%\+;*$3@.A +MG4_IG%N)FN.(XIZ4<V8)"&XCS-9X+FR;"Y<$P9I$Y)3B]+?`IG=]M7O-OB"#2A;=0 +MD\R!##EKBE&G"(-$3O[-@(.H^+$)QG7Y'1RQ=C%.?OUUS5D +MUFSZYLWX#%'K^45"J7/&)/N.?7N%?S.F\.^;;]C$X\3`"D@DD;T,``W0!4E; +MD&%#51`[AH'6GH$'AO2]3'#&BB=GYJ!FY(SQZ0CT@D^L<-8'+F^,0?$.)`7I +M(%T*$\LN/*"\$)XEY0MJ7/I"H*)9$]W'D$LA'WUYU$:.`Q:.;0*$M,T!#O70 +M4$#4Z?`AM00K(K5$F3=V`?>5\4O;&PC)RH6R.2H8N[(D;+D!SU%HY"POKC9"]$ +MU>=(']4^2PBNRA>QMJ4BIQ]YA!1`I)>8>NMX:5&/ZC!GD@/.+'G0:8OZ4C5] +M/"@.1[9TYTV35S(U92BS+TKL2@3H!)W8+099O=%-622AU($K/PE1>SC;Z6"B +M[W:#+'G9*':FE:#V,$S*J,;[!`%"9'T#Z2@N(\6D!?:"A+P"/B]CR)\>18[` +MZ0A;3I!=#LDN(]E?!\!RZ6')0XM6;PAU41SM(=[8,;(<@%GX@/4)_FVM.6** +M<)0D/^C0(VIT#E3^S@`Z$)0.`2+8'V9I&DN'JH$GL5@H?`V%A^:/#I"">RF= +M5[%UC>`%"I8!9+)DUI3D_UDIKP]PI`]]*Y;B&C(DQ+W6!'?&6]R.*-[3!7>< +MA:;7&(&YH5>P[Z1))6E&DH1UP2*:#-NFV.(439JHX[SD`2C'LKPONN)M+/F1 +M>SNS#/.KE7^(-DFC!U[C7PKDWZA*A]3M<3O'$(C5W$;[2>EH.&_K==DX[Y23 +M1=O-V(-2>HW`2S("`Y()L\U,7O.BP%'MEXO9!2R-,U)K;/!L,!/1OJ!P$W:2 +M$O)MC"2\6Q'L$_L+)XEH$AI>Q7.CHRZJVLIS/?[R<;Y`503Z.(=NJ$6'D(07 +MZ-,R`*>"TFZHHT"'G+S!H/;,:?RAEQ(H2_5P@!D_S]^Q\UAKSRG;`Q@;-PD_ +MX_DV3:WX +M4QJ9(LZ,?->2>-=`^^2$Y&J[J$I'<)*ED3Z..7'HW?4H0[$Q#R=%4*A8J_ +MRY22_NOGN]1?"URUB8EC$,AM>4E'QY9W0K#//1+3R>QN,JY.4EZ>I#S>?`8L +M=R=9HI%WVB^8Y8PD)1D<3106OVS +M6_@/.BEP3C<^9H0,KU8C^B?FSM_BK1>H1&S?UL>6I>9E;W:P5/_,5,:WH_)_4Y[T-VE/@ABPNQXDWI +MPNT.R?O7M__QJTYXHEL56R'3J?Q&>UV%%LS7@%T)4,,+P<,J,W9G@DKW*\&& +MJW5HCD&39^L&]1OG1%4[/UFU%M*UQ'@D#`VG(XACI_70*[6G_' +MU+C__.G=G-%-W=M6"RG)@JD^!_X/4$L#!!0``@`(`*%93Q\/H454Y@L``!LC +M```:````34530TA!0T@O34%.54%,+TU!3E\Q-BY(5$V=6GMSTT@2__OT*>:R +M5,7..<8)>]P2YZ@*8-A4Y55.6`IVM[RR-+9GD26O1DHP%/O9KQ\SHY%DYP*I +M`J)1]TQW3_>O'^*X4$4BGY]+'2W":'$DXG4:+E4DEG*9Y6NATEF6+\-"9>GQ +M8Z8-CA<'S^\C@]>!_W.\>G[]_N+RZOKT&GZ%QQPV^4&E45+&4NP`6ZX^]1<[ +MP6VF8MQQ@MMUNH%*"^&>)UG:P84B+^4DRR>S,-&R2:,TDN$^W?INDYE*9.?U +MZ=E([,U6/8%LB=+%)"V7'FE<+E<37-]*FF3IO-IUNBZD%BS7>B61I,E0%Q"6 +M;L/\80QA4<"5L#@^"3.DR*][`NXM%WMP&U+_^GLO$)M^D+ZS-\LETG0[W9XX +M'YU/3L;CD_=T=1-=+N%%=322M@_VE='TVL@HX\X6@Y*!-JB;)?%$J\_2Z"+O +MZ*G)6(GP$.[-RF\1;.M%Q&HV,V];Y-OD\7CNN8%*BN/'%`,8&:]&UR_'IU;HQ<=%\?R7T4N(\^)Y3^#3BY.+ +M5_P8X./YR8WW\FHT/O<>3^NLIS>CL?=X?>68`WX>7[[SWG^PW"),8UZQ#-T^ +M&D5$H`J]\`'A9OQVU!TRHY8%V$O,DG`N[A8*-52YC&"1+,.&`',%>$(LJP4Z +M$BR@/BN(;6=ZL+4NLEQN-K4U<+$("Z'`>K'L5L9V.\KX'NE?GYQ=._'A$E(6 +ME33(9K,^>8,5J,[-0-=EUEQ6S+H(BU(#.SVQD(&O`>Z..V=B+@NPUURF,@\3 +ML5+D!Y83]Y'U;3QGFJZ='P5-/VJK2M@+4.H"@,7F2UKE$!MX<8!!RQ"$-6:` +MI@6$FTICA0IK(RO2D4WH3#@`9!KB7\%GF6=..$L&-DSC,(\;,4?O+X<0SP#R(F.LPK9`6CI%P&O +M/;PT9_<%9]C:$J"L"J>)U(834>K[.!'"OH\3X*IB?';8YCQH<@K#>5IC_98S +M$5*_CY/0]CLY_7OY%LX/GIZ'@Q^_P4(?:J[PT#,S\,0CSX,.GSUM_BZ/[ +MD^&0(A$/L9%8,;F4R!G3Y<.^$!:W'%KT^WV7#*K206?B+LL_DB*XKPJ3P(0L +MY0+M*]'O(B)ANC.LQ8;<4]7'#0S/;E6,9PJ`:AFP,D6%;SU#"'OK4A5TVRA5 +M+*?E?(YV6Y7Y*M.(BYB:'E;DB(U%3C;]D[(^O`\#4CLJ$ZB1T;=Z"-9UTW&% +M:M1AF&NG!$!<0,TBJW`^W(#N5?+!F@7H%,+L`Z7.P7T@_1DHUB2I@5&RXJRS +M\X+\&.P"GK%[+?XK;*W94.;F_=5H`C20.+I#Z^!;2PE3";,%`K^6@#=3F6_, +MK1@G82X;2DBT`MJY'[S5\AX["F?'^ZP(OC#"%?>*X&$1:LPUH=99I.AH6J9, +M2$>2^A`1OH>B4P=ZB8$+MI1SF7,"_N,/Y+#$N[M(B*J[Z\#&RI9![$&ZA/U` +MAEJY7*N/A2PBW)YAI(KNHBH-VG*2_-IF3GI7X>``_CS>X]P=0WY&=;%K%GN/ +MF;3*@0<>Z131I4%9Y;Q#IES)?%D6'&26J,+N)]YVIDJP1%4F^Y&)C&5;="YO +M_=O006W%Y[F[=L15JGKJG6P0U:B20TM4T5LK_6]`,&:E2E&20RW#B!7*@VM,J40"&+,%$T0-YT,)9P^#4^JM%1O +MF\BC(0K*3RI1Z*AXVA"\75(EUB#NL$$"L%R7`=YU*II2`Z%E(SE9+J-PMXWT0KN@@7#6U17JERT +MSZ@?8",R;^RRI6WRIRD&[2,PU%1R8P&8%,8QSA(H1K4K\P/N(SQ\XG(`P6N: +M85&P;`8;F>;C6PJ4> +MG,U(T=CDFKM<"YE+8%GJ1E8EQ +M]*D,C!F78&MH3^?@T+:;)[_L;SBK7B"8TRA-FB-M>$*!F19JMN:3@WHO;N0P +MT=Q_*`+XU0Z5)%D:0'Z/I-;0Y]JT#:[#\?RHLW_0?204Z61*9?0P:,957.G5 +M#T[8TJ/)Y2^C\;LQ9$!3&.0Y7-R=@C($1,U#A;HI,W%9R4C-E(S;9@FHYDD@ +MM<5K8`009BVQR"3XJ6$/UZ?IFL#,W%9]!-9KS;^"]OS+M#]:&A.OL]*:V2^B +MO4%MUTWP@M_@[`2VL53^_-20X952;#H`V=3.,-K:H5``$)S.<237<$J.)Q\K:-U7A6G5U1R)1_\Z>,3>:YP3_#%D^2Q5C[+'HWU# +M:-(($SJB>KK4=5M[;MI0TKV!T/ZSU&:Z!A4`EE\TUFRZ]4;GW[)KS=N"+8UF +M;8[X?WJC!V)<'1H!X;#DX)YT"F5)FJ+QH"@(L8V?PZ4"G2D+(,RA*%(($MBV +M\=PR^+F"/ODI1(3$&UW0=PI87JKYHO#K*OFID*FGA!DE0JD0,+*@OFD6H]/* +M>(XQ"N0@R6KA^B%(A"-S5L5>`=R1N+A\->J)T:LW(^)^,SZY^AGSX@^<_,3Y +M^\G9Z?6-.'`K5.HC&[17]47:I4G).QX&IGSCSV[+]<1\>8-N_(L0.[C?3D_L +MX!;X+W'M"/%U:!DIOW>0TWZ/(]:4'L$`YM]Y3K]XC-4G.^`MP&/TKT]^'YK& +M2^%P1QF#HQ-I5#Y80HQW`$V[P1E;5 +MGI6\9\7H#MM[A^"EX#(T?O+W;LVVS0%=5H22NC_OQ\K&EC/.$]()?KK8WS=? +M,-!U&A.*8>TK'%TR57F(X@:$!K@WO=FC_7PSL5?LI<.`'E.XH8O1NPXN&V4A +M9W=P'5Z\/3L377,>Y?<.=.ZC\]X.;;O3I2H.6HW=PJ&>5=$SC(SOG_KT3?;%VS?T/Q6"<\\3.=US[YFLO7[/^_)'^W'!TN%*&]== +MVL2EJ+V4R_::GN8?+8#C-*D;($@NH`"$`H(25)H59NS,E7TU8]3U!,MBFGS! +MSD\4;M!(_0"4O'30;R(J<^S]$G]"">Z+YTVQM@0+!&0,[*;LI`+_C\=H)$[. +MKB]Q"&_:00PK7ZMZA^C6^$MILV\O/UYI'T +MQ"J;R^115B+C(KN%@ENCWH%OM\HJ70(OMU#4N57[7`E.ILG8^TRRWY)KT`AC +MS3/9)ZN_GY;/J_D*7W%I9,)^4J7(ZZV$+SYW)LA;D_>M2=R%4N(KH=3+5=#0C]#%/I?OU-#`K=]2\OML-7V9/Z_GRR<: +M$UMG$G9U*6B@%4RL37Q+-Z@%FT3.MDIE2LS1P1JFS+?*=H6(`ZRRW%H@]"&R.%!3)&<,R4R!#%G*.1MC:EW,9L +MB6MS5)7L!NM7W(+[=$:!3QKF@,_6A*ULK.'"=DA][W0".Z.+0:/_*TY7JE`Y +M-_FIH9/T'KAK#B3Y747"I2+9#]A+OR$C$:C/2"0./P@,A/"F`R1OR`%#/V$D +MMTA1P\90+T;75I6AZJK;7Y!+SP9\HP]RJ(`*D[/`QDF5WX;$!C(V)S]IP9%1 +MGR^T5P[5A^?&AYI0.B7(TIHP@^;;U=+J%&DS!.J]-.X."10.@W94E?&#O*`U +M]L3Y\07:/V+V*5[W\F&')]@@?=+LM"DPQ40E6&2E;#T9JX3P'!6!>_>D:X>N +M4::.0KB_AY:5R]%='IR]?=X(L3_-)H([.;$-9:`YRX6N2RO-GAMD3O`2CMK\ +MVZGWGS%5?(=>H>)6KJR4V%JI+?6Z5;N=-#@^HE,JVGM=36C3V1\Q^U,?Y4&: +M3S9;T\"Y9STJ'+?AM)FY'^3LZ_QI-5^_^DJD,22.73%S-YN_OYN+$N]#ND%' +MTSOV(M$=@.?[C-\Q@-@];`KWX$>81@_1(^GZY@Y@/`+ZDO[R`*,Q\Q,EP)0^ +M-D\#^M6!PH1=@BC]0`:0,\>ICT:X[T:+7;1P=[L_6+,9I(O5\A;`[='#I>(. +M%\='=6DZ]QR9'^JGL-;D"5XM7U^F,_ACOIC=^H3Z_XM1^Z`^AT'[MLDB4TBX:4-2TTR8A#9-BSU6"#];KHC&#F+GDOX.$7,) +M"`L4T="*Z#'502?:Y5CXP9@$0>`T28:L.>EE9`J +M9W31YB';:9BW-1J1DP@CQ>7."KL%@K.NF +M=:'D/O^.\N^T;-?`50%C.GWA"J::JR@HMN6RQ;X'(NA;(@W`.DKGIH!2:L)3 +M&VBT4`[QN>]5RMW_;U,5#U#H=BTQ0`Q@W3K2*ZA/G3D" +MZG3K1"/":P2RG=I@X=59=QP">D_"A`@-:P.OD"-VFB$&3G2]<6C\*%Z7B,Y8 +M&-EHGJ4P!E$W$FM4O8B#C@$]%IVO[`Z2Z3+0]55OKJ??R6CIE)SXFLWM]/'? +M.)G$:.C\5_B&?58GBW*!6WO<2U+D0I.J)A +MJKHU.=*NH,(M>I=O:;2,DKG2E&`.?PDB:/-V^HW1.5KK`R0H89=H2.FNX^S^ +MZ6$\@=MT.KD*I/8+505:@3C[`U!+`P04``(`"`""64\?S;2&FLH&``#T$``` +M&@```$U%4T-(04-(+TU!3E5!3"]-04Y?,3,N2%1-G5C;LP!(4?)EVNJ)!!:[ +MB[-G+]2^53:5@R-IXIF(9Z_XJ33J6N57/!%6<&/+*K95*\Y[DV1< +MD@79<0N]8<3X]D_EEN=R,4XG4?-:W,+>%]+)2KKLJ/A +M.13VLB#&.[0`HXU4MJ'V9'1Z!/%B6:MU"WA?2]%RESGSO#=O]#KSRRWK]-+V +ME4N5%7N4QJN7L0<#]_I=[R1=0\[D6\W^]'_/C3X6&C/FMKYYOJ<;V- +M]_PA8PZ7WA"VPM.]IAI@[KD)+3^DW<.(X]#?/-]K8?[(91[!:@W5O4CM[SI> +M;K/S>DW/"\>4WG4-9N?B<:9<>`)>-P2\>(P!U]G#N/WK$%VL8W3Q6)"N_Q_= +M+M887CP&(J7\^]'9N].#D_.#C\>4]6R$\L+UE-N9-)*7NK(JEX8;:0VM\8XH +M"E'*W':Y2Q>(;I87;C6?2*82R*A8I/1N9\)R/;%"D?>3%:\,U:5]:P?]_OA* +MV@[="`YV4;^PQLYGE3='(NX*;H.7$B:"CDN<2:&01)K8+:,Z8/[`3!A&`LN= +M`1;]FOR[\F[11A!O['J3+BCWF)Q-59I>3DHI?I!80[%AY./O*>4/*L,%JTUX +M`T]O;B^MRJ2YN7U:[^1>.O"7.1>F.DWU@B`JJQ3HSW2:8+'D(DU#<+B8Z#DD +MJSRV2N>&RV4L"\M(BE2O"U^-Z1\SF/[[W-"#F7*RQ'/(WO!63O>BEOWS$8"1? +MB^T,,OGUQ;>OOWQK=&_Q%4"D7N^V<)_]KA>$8W17WZ]K??X6[+<'PN%1=<&E +M.QN=`0TD2:*F4TGIA:#$HC*2%;+,*BM\D!/-VJCQ!;$V%]!7E +M1-E2E"NN(>+W^^P@-U:*)")KW#8.O[" +M,'!M\K@=KL8FP!\BBV+G$HGC]/J=6!/K8D4Y=K>$U72D.\XU[I@P@%9H8]0D +M10WTN1:1;8H<9NIKM+-Q5,E'^>/Z<3Y5, +MR9\\5,B%LC/HDE2+-UU[[1*\51D]-'42'#0K6S,?5]8%@;P3RZ;B16PQ4S`2 +M3/N:*W`$P(I,5^`AT,EDID$F5\514$%-!"Z`"6\[6"88&*5FEWL'86S3A5#4 +M;RXG4UXVDZF&:\3HI`Z.#-9N?V+G.KB2KOBTE))71=A$GT5STKFL:T[H)"15 +M)UC3NCQ>+(C\=CH:U2*9B$N-S&!?=,7-3%<(@D\O6-2>^W.15KZV-66NL@:4 +M\%"%9ECW0JHS=Z"?5,`^;\X`?Y5560M`J!".(\:52B"I% +MJ2QX%G%I"ADKA\MDU5QNBW4U`*&EA.NWQXEMH,(`+-R0L`-Z9BHG_UBJC.-! +MH3&72`QSX#TT*(%D,%&[*1F!;+"K0OI62JV`=#:]@42;DY0NM.C4B]`)2$.? +MO8,@^!'&O"V_OV;1MSQZAO'F&>8:&FN>+8^CC!K^YHM]S9W]IH=3H,3?FQYO"ERW(@$HYUC;:7/DN_?"6_:=Q@CQ56> +M*(JV:0MD4;V=H298"K1[8,1"Q!]JC2LLB2PD%%"QRCG:)K5P?I=KL#+7Z1R4 +M<<-'Z)#0"GW]K@M)4\L=L;?RYS%V*%\<\BJ;P#:H[B>%FC9)WW]"COX<'IT< +MCMPLZ4'?[5&C$"F8`SJIN9L0%[K\80H1$^%+L3*\MXLP]WFV&M5YT6/1D?CL_/A^?AT]`&[YU]. +M1F.H[-ZC:#ZF[M!Q,_-R6^"V&:#IQF\_?7`?S"R$OQ[-8IUE"-ZK_UCRZDK7 +MJL2A_JX+Q@KU:H%)%`F&-\!)Y?#1(L=;76.K4-9X-MFET5492\S+\L;[WX\C?KU^G"137$^7_?CFLLPN +M70N[!3N`>S^^!;3_`%!+`P04``(`"`!W64\?9_%A1QL"``#H`P``&@```$U% +M4T-(04-(+TU!3E5!3"]-04Y?,3(N2%1-?5-A:]LP$/VN7W%T7YHL%GLJ$-P/#=PH5U3HE+@P`ZIJ2JR0S$K8D4_U +MQK8E%@))5A[-7HN=*LO7K4'^G5W'SB6#H1%USB4CX+4$TNL,%YX`9XSW,&`B +MEM6`-`?0.W`%6@1#%E2-=@(>3I>`!&7!H%4G4N8T;'$@@-#&D#KP3TSM0#F0 +M&BW4VD'!#QA`EE<(4I$SZX5P"[V46?_?7FB?N`F)R/>)"DKDQ@5IESVR5%WP +MEJ12+;IA?5"6[[VP@KM0K^*JAJ8UC;;(?"-;J^K]7^TD,GDI="GI26)'L@E+ +M*8,T0$MS('O55M67R>;$8_69\(,:) +M.#1W>?S%E9XZ#-?33L2XV,,\3>%^D:]N`=C+GQ]1:/YA0[J&O;B8R*:?^O#0 +M.\]7SX_S%#YGB_1V@*'0320")C2$_0102P,$%``"``@`;5E/'W6;ISL^`P`` +M`P<``!H```!-15-#2$%#2"]-04Y504PO34%.7S$Q+DA4375476_;.!!\YZ]8 +MM`%:%X*;>TU<`[E4.?C@VD&<]",(JM`2(_%`DP)%U;:*^^^W7$J*K>0,V!:Y +MY,[LSHXF3CHEIE]$E18\+HF'T-X4OPQ'01PA_G/I)RN?BR6 +MUZO9"A]Q:<64O94Z574FX,V&.RMWX^(-RTR]5@(0(/%)WG^-+^'#+@+ZWX_8 +MY"-='29HGC.D9E,JL8.F2W'?Y;A_D63Z.5Y=WLRN;V?+A>?%;@MQ7!N<['[> +M[N$3/%3U)I&PP^\^D2=@GF#BW'2'Q;LI<)W1 +MCGH%D_^5,&K/AO_4Z']Z4;>%3`OJ;.T$$3PB5H',M;%2YQ1[DK9R09_34*_0 +M.$BB&K,K[(,_TE9"AY)!)WWG*(WB.1WP5/J^^8W[Y'*Y^#L(];[M[.W-74P[ +M(W\Y=+&%1;*T/)#CET@=7O1]]]GKG#M4%D5G)S0;O^5#CD6>_GL\(P=C<,X, +MYK1;B?*U4K_"<['LF4+'].IBOCJD.H1\#6U,;H^_7WRYGL=DJC`!7CG2\,/^ +MG`4=&[]J<'DCN$+JF7$)KGH'^YW$QP'&]&'M&?1%)\0NVH_.61,"C8_T&F'Z +MQ@?;R:"74!P#UK0\`V`D:"++)&G5C(+&*/+S'CG;D5=M/PLX'93MS[N_5OUK +M@Z=IO:D5=Q*-@?W0QD%><\NU$RB8,[`6D!GM!Q(X%#(O:"Q%*BN\PES!-1'P +MS6CY<.4*4^=%&$1J,+A]*3K5@JLZ4YMG/-AXNI32H=78M`_$)[(=.0CENL?2.<3,.,KI9W-Y](X6V2G&Q. +M+_\VGKRYO+C$1WPU6/AU7J9%E2DAQ,%:.I-_'JX.DKQT>,"J>O09GV9EM1X( +M&&3$O455IK-2KE4_2M[,(-(+;_-"#41G&7TI\E+QMT2T?\*:DO5%2>M(,FJW +MRI'ZV:*02S:G5+?\I=\8.N-%TCDXK-=6TE)9J/+.YAT;[I&:C3-^!3EO1__" +M*-7;9R))Y+9MA,KV"H:8].(6O^'6D_L<'<3IQ>CR^?3BS=7%9$Q12ZY6N17X +M[W:E3!-M?"2'+%4&XX5;*6&WUJGU$/)*I+(HQ'MXC6)PXMRICVP,3[,O\LF= +MDG8H6W4QI@>U +MZL&#^E!\`C8IT\J*4CMAE*M,.4R2=R%E^42^VNV6PC+PQV +M)K]I9ZUCCZ%'>PSU]EGQLS)ZF#0^=9I-"^J#'1N#X%JA*W:?LE8N592T+H,D +MRR$ALCR5#F="P"2$2Q].L9)8G::5,2H;^$KF8",H_HQDK,MU*7*7=`4I\I1R +M0B^"LF``!4U4P(?>`XHOR65J(:O"]8?).>349[G><.$ZD>JJR$2A]2 +M!"\>.&7=T3`]&'`QBT>/GPB;_PS=V$W//ZH4Q\YT^:U#UCC8F9=WRZVV?-&K +MW>S/%+Q!AG:<<0MGM%*;P$5\^$"^#-:P,[_]5DB7D%7_?O1XT&SC)1=1QON1 +MRR/:[6YU;7OO!K^HGF"X\\&WJB]NO?-3O=X@7/-"(04F94J*N%06VN"\'`_K +MHP];$7[4M2Z=T04_EY:2&5&@[?%_(K/,(#C"RINF;.?58J$,9Q<>DO&0<=(X +MGUNH!0ZQ1(BA4*:/*7#'L;.G@D./O9L,HV/$UXX +M3"X6N]M2XA,XLW(_56UV)V]RNR-),"ZO7"O'` +M@3;0EZ=5`4C-%RC!5!DG\YA/7"]VX%5#1^*3/;9!B&O\6ABY7).S$$SOUC54 +MQ)/9BH#&5]%"%X6^Q;ZQ2K!G3_1(RU,?BEXX8[\OOGHJ'HA^\@N7!0OR;D_% +M:/9Z]%KTQ?U[*-BU-EMO[0#)L17W[M=EA/=[#]H2^44@2D/QA1^HPJKZ#3FO +M]Z!_G'Q)ZN>TH?R$>JBX,*2K,:C,"B0B0_3':KV)6W2:\>A\]N?KUV^@,M0R +M)UP$()RZS*3)@DK@[5P9;E[+',F(,,-ST6VCV?7X+^/)NW$P]@&95I6?2GT; +M0]>K2J1DUB=31K/+B[^/+FM@.2+Q=HV&"F?19Y/K\8M:]J$7S=1GQF@8.M<5 +MM366I3@T/W]H1:27J3[J3*>^UKU-P93QRV;-'SE*"!!'QI,J+_=F4]1MMZ47W0^F;X^NXJ+_A3/"]S-UDZ=!^?CZU:O&\A](FA]Y1(R@Y0_YU^NSZ2B*/KYC +MO/U719V7):=GXY>UX!$',N@+_C:R7*IH[N7%U?7#(,M1U&6QA;V'\$9%!XRZ +M>;DOLY\*2H/[Y9/RV +MD>60,H2:I2+D3PTMX$8F\Z)VT=79M/;]T??1]US]5+`WLJA43)F7X[/H^B.. +MZJ+0G@VHSZG:L/GAI+`[EL71HX@!!$W*E+)H9^)H6/&KIUW#E+3DQI@;DVQ@2.ED#-0%Z#5*(N`?> +M@20R,PBD*/1:C\ISM9(WN:Y,0BU^I=JH1BX.:GR#U,!_'QH6SCWA()SRO(_( +ME=4>'8D=28(N0:BNR3?Y(BE52C3+;(==!&2MMJN64GD?_IW/J'DR\I&?"*Q% +M#3/B\##R-?;L^8Q[*N$>"2&Y-=<@BR/KX"!88W/BPUM%;K3O')=94T4+]CO1)PH3A\K(BQQ^ADT +MC3T>J@Y8X!Y,HSR'3G8Y-)YS.GC2"^"T@/SM789]S#LPG,3P)MRRFZ0AQD'E +MK\"ZD(38FRE+/'O-HO#"5IL-\35E`R.!@3A+B#BQE1W.W7#R]FL\#BGDYQ0B +MBR4<`1S*DD#PT.>86:V5+"E_F(7MS+G-C%O/MZ(>8GF`;=%`SDG?@_F0<7&@ +M-"NF03!J:10XI:%T+V$8)@9B9:%WTP"4T*'H!66R`WDH(RVM&[X?/OM^8]`4 +MS%6NO2TL;8@F1()9M8?8;UU?[M,5SEJK@L'2&$]O=_>R:!\8+?O+L.33&T`I(0BNL3PHBC-?7VGX.5<[1\^^'-@Y&@<:X"1AJ(- +M?\X5K>>JB+QOM`*VCV;C9,$'H%$0_\@R[M7=BB?G +M`8\1__NH7M]9U+3N@B:Z+08AC!E0?PL(6*&`"JY)#^/QIB!PXPAK7S.90?/> +MSORE@_]P9X`7[SU)_7^,;`$.NT2;?)F7Y"^J.H::.S%N8D_#92?<'ID():P? +M\:U')J*3ZQQ\#EH##,7[B'X+B4#I?U7KO=0JW.Z=7LT-_!5) +M:'K$0"JBG*R"1[5H5U(_P;:QBY(F'J&-3%5;7/3RQ1UO[9ZF/PAX;IF>W;7: +M'[!]31)KM;E#JZ/G5U1EN#2SK69-,HE'!I6]7X&U%._G`*=/N_#EO4_D_-92 +M!.!++KA#FA?V6;)S5W?'H'CAT\4"=/K&M-^WB.$H*!_4_FZAB*8ZQ_RJAO&> +MB5M"%2X)4#2^Y0#0P`O/#D_7--7B=UEKB`O]Q##8 +MNS`7)R`ZO_Z*#Z=/O9I^O=#/:SL+B:]S)_8X5RIP2'3P#>"8B`?K14/-4_'- +M-\V8/$.```8S8N+]I&V?)];[MLFMK53#5X@A47RL0\2YYO+2$_GHTW=GTW$< +M8'<41E[;#5"GDW=CXJ^#H85$_O%/\11#_0%.#>*5YB:M:SAV_BR_' +MX88Y+*-,Q,('QTGBKR["K0-5;&]'2!RW'WWW7?!4?4WQU?X;[M::?FL)_7!= +M'$=_=P[;6C5X.`C?!EP;_>.@9,@__*4%4N&T,Z`FAFO0[QY)]>%Q'/%@W^(N +M[+3MI6N0Y$;GF?@-K<%A'74TGK;^[K74=.WVJXYV-GO8-`UK+4MC(SI +M0W^_&8T$W#1Y(D22[%ZY#?9=N`U:MX)W(:$F[J'=T![/KE_RWX>2L79^-@[# +MDN4+P;UMHYF/^'*37A,`+J1)%D:O!5W+%.BXP^2%FE?+I0I_LRB5RN+=9[AN +M'5#",6=W=#'+-W<28W3ZB=4.V0V3Z^GSD2`W/XGE%"Z"V?+_`%!+`P04``(` +M"`!564\?H`H9,4(%``"3#```&0```$U%4T-(04-(+TU!3E5!3"]-04Y?,"Y( +M5$V55]MNXS80?:Z^@G`?:@=*TNY3D34,N%OMUH!S09P4V\*`04DCFPE-"B1E +MQPWVWSL<4H[L3;I=/T49`. +M5[^,#L_Q(,'?L![-_KJZOIE-9O@G?AH8)3\*5R_STF7-,UX0PO +M(`3UAA&&+@P[J=1"\35$IXN/-UE_D`S/*5&?_N_9[,/MY.9N&Z:T*$)^NN"HE +MGB=&-TXHKZ5*2@BUF$,OC6VX/+KM?110-@;LV7^%LM7FT3(I'@%-"7O!_-VE +MU#F7R88;P7,9=-&0X\8%W3Z&['8U,!(]K.M%WE0D&C!AF>4;*,EM")""]3=? +M1SC81+WXC:J3"K,,*;&M<)%N#.F2@R%3D3U[7<.%A3+U_E1"R;[!FO_CC2N- +M=LRAUXZ3SFTI60Y1D)"RS]@B4PZUN26!-F(I5%NNE.6-"T9X70/2S&FV0O22 +M0J.!RN@U:;U>/`IAG'QY!0&JQQ-X\/`E'Q/FJEEX/++@$70MGF98EVW#9 +M>.(<,L6BL:QGT)L_@J8`:?:RXFZ\J(>>Y`?[X?85BHF)#,>)J-S\? +MGHO1/O$D)-Z)M]/5!V%0LIC'#EO/UE`(+@FR#1@KM/*MB$DD;Z?L$V"(5JCF +M4<]5DB]]!6OCYQNV*QEK5`E&[OR%2!I?'RS'OF(8^`09A4'L<.K:`*2O0[B_ +MMX]5UPMU..X1<"MXL5R\DH]A;3R26$F/E-D&J&XT8<0=A-H4T +M(WOSW:OJV'+^.%M@*%?C:3BG2VE_Q`M'OCU.R +M,WC?$5DM-]!*TCQ]ZDA3OPR%Z@V.',5-LM4-UATKVTC7SO<`SQJLY4NP,;N> +M;$($9T4OQ?;#&K_[]8)=W4^G3.00#OU^*WUK^!I:5R(K8V4K9"_XOO.2 +M<3C48<03?.T)T3`/7ULP@=$^1CHB'F'CM""Q@".7R&3LE#8`:LE]$(CK/HBC +MN!)D'.X`[`S0]ASH4."(Y9$BOQ` +M]*!8JW[O6NO:IJS2.#\PCDXYYL@>O!XAMF)=XSQ#X,NF@#"7(@R4U=MV8O** +M-C\-'DSR#[WU@RBEWC]8@[HH&F-9WW*L=Z<:(OC<&NU'E/@'!B]+N,TR]C&U +M^+Z7`7OY[VS6:66_64?'=!QJWG2DO+4JN?'#+1/TC%(;GW/(U;X!M$ +MQ20Z)`DC999E;#R=75\PEE`V8?+%9-*OQE0XP:'J]]?"+X,#079[FWV>W+58 +M@"N"F]_N/]&;F9XAK!15A?0.[V--#P(B'4(0!ZQ07RW9Y.@!1"JX98&F,>$7 +MGB$V;KBC=PCCV%!26QGWM+I*4CL*[]Y8(U1I6^L5P506A]L#@G@ +MJU_'49[[FTB:Y[ES\V<<=/,O7P9GA.[U_>V'C'V<3+,+,MK^CT`&"9!_`5!+ +M`P04``(`"``G64\?\3?OO&H#``"?!P``&@```$U%4T-(04-(+TU!3E5!3"]- +M04XM,C-E);US[W^)[[E=!PD['A&=-Q2N/T"#(N&%40 +MRX=;+JCA4NBP5X)(F`;#G>>X3\HG7`RG7R;G%]/1%)?X5Z'=>R[B+$\8O'N@ +M1O&EG[XC_T2G`-UBCGR6J\V%`>&!W7:[VGS]YD$B\]N,`:TW"&P]#B]ST]DD +MM.!V?5)S!@U;\)9GB[$X:-"X]'T?:2;7XW&'A#VG:5O9JI$VCBZN1N<3 +MFU)RE3)0>"D6@H;0F&$CM(.E8H9`1>(.5F].['6Y86"0HZPDLE%)T+K1^.<3#C(E[D][TPAX?@KRK(J*-]@DY*6^-YJ/)='1U +M79HRI?"N1YYE<(N>4JZM?W>U?W!\#%LAN$,\%4\N.KS@BI.A=&5'$)O9<&JB"42A#08JA\Y1ZAF!J^YAWR!G&BL +MZ!.J0H<9H&^)S0:&2C&3*Z&KLN#PNAILQ'#?QA3O4=#BQX%WX-TDTN@6Y)CP +M#*@3[TIZG0!,7)RRI,ZE3F6>)6#H]Y)RD=&860E2L#HQ+AC?'<,?_RM!V&7% +M(7X^>-AL==RQJZ)_3\XNQE$S,MTTPWFV_!KT<52XSG8-V[7V721PC3\@EXQF +M%DE+8#K`IO?=0VS^VX`YAOX`?T(([._>'G3(,UHLL5#P#)$#:[[Q!UZ(EU77)>YN&?[^Y]S8RBV=L*.JHE36J>]C]UV$>P=H./VZW"O +M^-"!;H\4\Q53LFV'VF#S)E=0;IQ9N6CN]ST7L[1WB,O=X\S&HSRW8:VL=D-+ +M[P?U;',OJRB"D_'T_`C`E8HNY@]97=5>U06X0Y/DU>;J+6ZU!73\?UY_[.5E`^1MA(_CM&5X%IFIQO%8M&B;8)G7AI-`+26&&NF!84ZE"!U&_S:!$]+ +M<3,1)+7`,_V"1J_D?LV+01+<`C=-J]#CF\J@9?S(#@@G*[U''0-1(L$1:;%P +M2#(971?,,W#>!NZ#19?(+\F\(O?&.KBRR%24ZO&`1*%%L<@*SM>_I1R/89KS +M.WBB="IDF4)JKH+`_XJ%`1"=9HWDI%H9GN"QI*OII\65DS])=@K,3=O%_Z8" +MLW\A?2['26WH--S2'N'KV +M,L%VMT_;VSN*Y-@KKI5A(B*)(85++5_CF6,;4QJ;GP[WS%'^;[9QM1IV*+F] +MU,,82:W1QN&R1H2D(^5S7N4\DJI^)R\P(.E2;D$LH[=,N]8X%.D&$R^&NIS$ +MYU+TX1JI(\.9NFVL3X,;BVTT:G^25(Z+CA_!>$G;T\;T$BH6@T5X)'-&O6), +M7X3CW6`=&JRX'1GE`G8NRSO^9 +M"O-HH[0R#]HCKT-LETN:4XYBF!I +MNX.4(8KEQ3#()9/W#C*)\R(T/PAFI0D.EI1M-+3EW!QXC?R8S,JUT1^B4>UZ +MWT[W&VR,[>+#R[AX*9L=??2'"MG1%<6.:5FA\V25@_7__<[5S"ZH8C6)P"-B +M&^^-$OZ"?E3(U$-572[^,U[,AI,?R-QL+NCW(SKCYLV]X#Z,N/DLFC;5;X;] +M=\3.;'H&_@502P,$%``"``@`'%E/'Q=YUF7T$0``&5,``!L```!-15-#2$%# +M2"]-04Y504PO1DY)3D1%6"Y(5$VM7&USV[@1_IY?@0^:UKZ+FXD_=M)T%,?. +M96HWCFQ?VYM,.)0$2;CP[0A2EM3VOW<7)$``7)!,VYE[D<1]=O&RV%WL+OWF +M450)?WO'Y6H7KW9_9#=UMJI$GC&1K?GAS:OF^8LW/[U^ZS^"GUZ\^)BQ:L?9 +M&AB4HL#'DBUYDC^_9&EE%SRK.)KMCRR55R(*DY8PJN*E_+E +MBSU?57DI\1F`>0D4DNO'+,[63*[B)&XHMB7GWPBZ/[QX`2.][$:*.&MH,.;+ +MMV_N8=AOEF^7\/`2QGAV_N;5\BV[RK,]+RN&/S=#/[`J!W0&_)OOB$3@.MK` +M`%K<>QXG2;Z**\[.0%15YL=SFTD'VG(M:ZX12"8R48DX$2"&A%5EG,FB13ZJ +M+WF(%I98G/3(%NH+27C[_G83XX*WI.^09@:_?GV:)D+%:,@LB\V2OF3_@ +M9S:;'_ZTG+%:BFS;"'*9R`[^1`E\"DI[FB;LJ2=)R/U:PWY^S_(-6XJ+M8BW +M>0;ZYJS#N[_/7C)=E7K*S-%Z5^;E-#LKE(K+C*":ZN;]V0)LDA['#JA6YR"H- +ME+R2\"C>:O#53\YRO%>J?[7+$RZ_'#M_QS9Y"=O24K\G]OW]X4_'V4OX_XSIC6RIKQ>+^;M/BT=]KI8YG&`X +M]_X,T1A9JP2PZ[]_U*CK@Y@"4H_UT<(=@+UP]N`EDYRS-U7UEO%]!$^0&+Y9 +M#"(XYE445U5L%&&NOK",/S-\B`JKF$H?9=L<`<:P7(SV726,RWJ"NS\30S#N:7NSAC+C+P#ZH'UD1 +MEW'*T2NUQ+M=58)LGWPVOT=[^;SCX"5G]S,FP-VQG_):PZ#/H9MQH6!@M".41Z'Y!XVYN'C55%L$FKXW*9,`&?ZA7 +M2NG;B,$03]4NK2XB4]KB&5"@*Z.XS(I_0YANR*,'X@46"6>[R-8&(1,DW +M(S#V+*H=V$`X$#R%@,AF,W\\:-/'*U`-U`PPE#CDCX_7BV;`<#A@">J2.T@7 +M.!7VSH9!A+;*L[7`8PYK/8W#:ML%4+_66XQJMF6\%C`S.;ADJVW&!Z"H0AEZ +MAH3QWVKE=*0+-V?@P\.PH+PX&D'%T9N4T@XS,^D#+_7ZH"<&,X"_H?9-9K*N +M4QV\O8>/@T"T9I[Q4SPLTW\#'S'0U$'G^90](B+/*:@4IM+B/MPMKH=7.8FS +MU2G7]+?-MRF(2P]BGY*K.@%CS7['_B9@X/5V!\$_/U1@7WUU2.1OVC_ +M#`I.MRM->_?A:IC6B:BO=G&VY0Q_D1./ARQ<8_(`W\V%PMB(OER#LTW*$'C( +MK,C"G%*7Q=4'4K1U-`/TH\<3F<@`CP=2J*UN+J)1/@KC*IV+6L92K#RM(M&7 +M]#`)U1MDUBF@RTBI(X6PU-!%**5T$?LH7FM/.%_CI;'B6[#1GA/<]XR=2]C1 +M^6;)I:,,T3XB0C@/1H5O",SKJD-^4E_&)7[\.;I97%\'#5^<^3P\5[X?-IP^ +MV(]P6WRTA[VQF<0F[@[NPOA5OS=X!VS+-!Q&I4[;GI'X9Q]-VRS-!J@#?*AD +MQ,"T&W)[YAHS/G-9+_5)JI=-U$[3^HF/H9R'E_'0I,[E%GZK"W#BFNA)?1EF +M2]QP;]L;[NVLS6J!'0!74R>Q$?1(P;X^C@.?,*;C4F_HM:Q$JA22F6"/976Z +M!'"36B&R*E[VQEP9+,K&_V#$+59PG\9L'5_CG0`UGA5BGV,&PO`;2>^08Z"6 +M8(Y+H&`T*O4,ITY*ZL?Q-_Y9'VYP9VSV>:;-,+JXV><%O8L(7#C`Q51@=8G) +M*^^2::<=U3$E$H]W7H+F+E^+C8!5IG,T[`R^U6#OCF:/9O,?WWN9E)=P4F3% +MXS4>,+@XG)N%\UT),:*TYT?:*8S&M2E/V^R$RE1T.X373DR&;.)4)"K4KHY% +MMU\`6QXK$RC\%;1JP,*A)\"A +MAH69]A]2H]16+CF>RGBUJE.P+15?_]D'&^1C76;2$2F/$F_?>?8JWVQL +M')VE`M':X*LU9?JY+=-='G\3,VJ]M.=?$WK1L!M4C&&>%B]9Q95]+M0>2+44 +MF.C$DPG_E'P+PG@)PWG.RV\0[Z^XS\0+7Z0=O\ASAC00X@;A:5Q^ZZ[WL"?P +M71DG'W%W?1<]/,X?H\7U!^-[F^'UA!"+IX3)7?YL2[RJRQ*N(19P6^9U80P' +M/Q1^"JBU'?`DSP`J3)HWI4)/VUCZ&DU'G%U5QZ._&PDT-=*;^G!XJ3%^6)F. +M196^BYH23?IF>2R&[,D08-TK5UGT8JE'HCKZ,H:W9#C,1+3*]QF\*KYY$I(\ +MUD;A%CYJ_H'201JEB1[/79U4`D(1K5765-.JM`B-\LWF[R!B,ZSP;ONZ1_/E +M7_,O_XI>SQK;ZXT6(;"W^=*'88'T!G[GF:BENC6'\6`E`E*_P*/J2(N&\R*M +M1)ZEZ$G"7O^^V^;A8S$2TZ=1D2='?WCF=.##+$_M8UN89+J5YVWB\D*%J\1D +MRBXX^L`SS,P`JI"\7N<7^`QT2Q60&GML1%FPA:+"+LRX4;3.X=^K6Q,Y8F;3X]GH(+LCK8J4_I8?'U\9X[% +MGB8YN`1=Q-W1'+]LT:K,#S\>NT-VXF7>4OX"'_T]^O37Z'JQ^*3#[&M5B-KA +MOG'_KC]4(DJY5-$@H>`:?8BLRLP]+U.\W>"Q;8I%E`(IC!L@%PIH!_M`Y`?( +M%M%XE`QXPO/9+"CWARCJH-NXOJS[OX]Y01OO+?]AV!: +MXA;)+0DYQS&!/1_I+:AVE!9B?.^&_:3BL7>=)#4G((IZ%3DX=O=P/>Y5]>PQ +M>#J-?$[_`R-VMLJQZ':P)M#SRL?`^D[0V1$/!4S(K!.M!Q/L,SU0JP!K&PO\ +MF;844FPS(Z)2%R0$X,_JF@.?R1$&+#?,)Q;*>;8.KD.0>_==*A#8__]J]S\O +MKMP6FWY:I,D;M45Y+TWT>3$"-G1CZ:0P\`&SFD449<3W<:]=@HLMS^#W&I12V4\UR0$F,`*:1]MP.,;$Z2+!X+K; +M&WM=F^FJAA!OTL``6W*PHZ@K=U=EGK`EW\5[D=>E+BB[?4,6@ZXI18\`6U(F +MB;>CN@?50GEQT6+2]I*TLI5:V@$X2I.<-^4^'*%Y:(VO\/OHVFJ6/*8IQU!4 +M-8QNT"]S?1Z$([+PNNF&&#CI=UEX*=$6.=BTAB!"&MV]IHB/J0FRX6,.*\;D +MD"!VEN5^TUT.YO++1>-)S@USU*TH7D&T+NW`HBZTBC7/P-Y7.]U6(^UBH%NML-D%X.TN)%#W0RRT%;N\6,,.U, +M3]CT:$Z?LA];NP,8C:Z!`Q%=NTRH^!IQ5*SBKP`M<2A.#LYT2JP;AD*(DYA[ +M;F,_9F?BY:_G,Z47Q\:2T/B/]`D366/WJ]'#%I&M6>XB8TK$"X0-WJL]M?+[ +MO<.MMPY4G)!/S]-+-TJ0/=;20C^2<"=2&&(0A2_/2LDU=C[K((22R2$M\Z)A +MX$!'P_1.@TMQBV72"C1;"(83#H`\"!TQ>080]QT*#>0^%*YB!TNA%0.55]^H +MCE6ET[:E\UFDO-SJ5;G#SZQZSH-S=%(:#]WA/ +M)PU0DJE,F[RI'#4O1;C07D;(`S8FS3/,B#P4756RP-T@AT=,Z;L,2K0G$DUL +M=OCZ.`^?!#]3=+8$-5OG#&8!@5N:[]%X)HF;\"/E[[WKKW2\V8S,1#:.0-PM3KPE`%M1\@O5]M_V>GLG'2?]WTB'_]"O +M1I"U]J?6V+7WP"=U#ZR+@FH[\!N6W#8,[%,R:0U\\P:"'76`@_V]_18#'\>XC$3+_28'+W_B"`C97L'V83G$D:%\[- +M5Z^^N@*KDN4SKEC_XHO00[_:>=`KH6QF1RNR'JW(`K2#V?8O<5+L8H8Y=S4U +M;05F!VP",8GX/9WY5Q;9(2%%?7ULA,&''QU(L(9V:&IHS6)["X68RP#FU@%=/(,7C5-.MH.]4TNE-N1.BHT"2:#`;Z@_$+U898Q8H5P$BB>7.WQ/W +M^&`K=DY*RTOCC.&CU,(,W"+M5\6HA833;\A43;9C1:YCOU[E$)SBI9UJPJ08 +M_(*;R9GRPZ`!X-Z2VB0`3JZ3U*DTM]9X`I7XM?>FA$NK2==B;]X1V\,9";%T +MNR^0H-]U<7(]XP)[Q%QVC0G'=B.&<9OM]DZ>FVR;8#P\G!(:3;Y9Y68:?V]2 +MC1KDO6'5&&G[):1*OY.F8']LWIKR<]8G[Q6K"6SF]P$V?JYTB$N38R?8]-^T +M"K/1*/?=*;W'PGZ'RFS4I$U&8]:[G)^$%<1I`_OZU8F8QNV<[%_]`0/*IG]5 +M2PWTL9Z2?.M-!WZ)2U'MC-8$6FNG2KA]FI/%@!^L*[[FW`_7::X=EC)0[Q@;I-\5J>J]S0-']BMG+7L]'\[,VF09[,,CXF_5R +M5Q-_DWJELNXJY$SCKC:3NKWTD-JWFO1\6GZ\.W6SJ7@T*,5/$W<"0LFG$]5V-0!3]K9+5)[ZC5CTZF5\VU/#"\K9 +M1_W0CXC\VK/H]6*=>CT#5Y:1GMX[H/A,])/!"O_)ZT"XF@`(QA#LN^320_\> +M'EZSP54@>FY47O4:V$COCPR$D%:R_!0\'^V>A\Z'WQ>`D+803\VK7Y+ORO&T +MXO9+Z&WY/$">$D=0NK5S+XB6OW5WT]]J]0>/\KS"!!,\^.?IW\0A&;`)G@L@ +MP](G$SL_=9%M(!E[H@+&I^GP?2!>=._3IWZ.UB7LZ$(A4S"+>MH/!4T#Z=I? +M?IX6-I%9V--^6M@42L>>]E/#IMY*#D1-_F).CYIZ4J8N*1TV_9^RLZ?_2WKV +M]'WYV=!BA@]^NR+>P0]X7DE7BWS/NP]>-:A40#@)BP!,\O8A9(37CLJ+\/K) +M5XOV\N*"G<'_3>[UG/6Q1)C7PDV8UW"1=5'RM$Y])H-AG[]50V$?33LI[.NI +M5)(LNG*..@QQ5%HC!/>W_YQR'%=]>N/MW_PW8[[==B2Z7G9@O6G& +M9A(E^R@Z^4NH=\!CK?+'AK"?05;D'36LBR%NLMR93V)M#IE:[&T28.S5N;(E +MM[;2,ZP-PIZA!XH/A34B3Q\1=H`^KAP``%9&```:```````` +M``$`(````!4W``!-15-#2$%#2"]-04Y504PO4D5!1$U%+E185%!+`0(4`!0` +M`@`(`/%=3Q\U*(SO@B4``"-E```<``````````$`(````/M3``!-15-#2$%# +M2"]-04Y504PO34530TA&05$N5%A44$L!`A0`%``"``@`5F)/'T%/"!I)!P`` +M3A(``!P``````````0`@````MWD``$U%4T-(04-(+TU!3E5!3"]-15-#2$%# +M2"Y(5$U02P$"%``4``(`"`#<74\?286]:WD&```$#@``'``````````!`"`` +M```Z@0``34530TA!0T@O34%.54%,+TU%4T-(,3)!+E185%!+`0(4`!0``@`( +M`+1>3Q\!.&:XR@4``&KP``$U%4T-(04-(+TU!3E5!3"]-04Y? +M,S`N2%1-4$L!`A0`%``"``@`+EI/'U,2@-FV!@``GA0``!D``````````0`@ +M````-,```$U%4T-(04-(+TU!3E5!3"]-04Y?,RY(5$U02P$"%``4``(`"``D +M6D\?<95ZY;,#``"C"0``&@`````````!`"`````AQP``34530TA!0T@O34%. +M54%,+TU!3E\R.2Y(5$U02P$"%``4``(`"``96D\?!>5H96(#``"4!P``&@`` +M```````!`"`````,RP``34530TA!0T@O34%.54%,+TU!3E\R."Y(5$U02P$" +M%``4``(`"``/6D\?V;FZ(#8'``"4$P``&@`````````!`"````"FS@``3453 +M0TA!0T@O34%.54%,+TU!3E\R-RY(5$U02P$"%``4``(`"``%6D\?!HACIP0# +M``"2!P``&@`````````!`"`````4U@``34530TA!0T@O34%.54%,+TU!3E\R +M-2Y(5$U02P$"%``4``(`"`#Z64\?UB'(KST"``!0!0``&@`````````!`"`` +M``!0V0``34530TA!0T@O34%.54%,+TU!3E\R-"Y(5$U02P$"%``4``(`"`#Q +M64\?;*3#A:8#``!L"0``&@`````````!`"````#%VP``34530TA!0T@O34%. +M54%,+TU!3E\R,RY(5$U02P$"%``4``(`"`#G64\?\XNO+40#``#W!P``&@`` +M```````!`"````"CWP``34530TA!0T@O34%.54%,+TU!3E\R,BY(5$U02P$" +M%``4``(`"`#<64\?$)]\O*D"``#Y!P``&@`````````!`"`````?XP``3453 +M0TA!0T@O34%.54%,+TU!3E\R,2Y(5$U02P$"%``4``(`"`#364\?WK*_BXL" +M``#H!0``&@`````````!`"``````Y@``34530TA!0T@O34%.54%,+TU!3E\R +M,"Y(5$U02P$"%``4``(`"`#*64\?I(7^/>T#```7"```&0`````````!`"`` +M``##Z```34530TA!0T@O34%.54%,+TU!3E\R+DA435!+`0(4`!0``@`(`,%9 +M3Q]JDBX]!`,```4(```:``````````$`(````.?L``!-15-#2$%#2"]-04Y5 +M04PO34%.7S$Y+DA435!+`0(4`!0``@`(`+593Q_W^<^X=P0```4+```:```` +M``````$`(````"/P``!-15-#2$%#2"]-04Y504PO34%.7S$X+DA435!+`0(4 +M`!0``@`(`*Q93Q\XXZPU*P@``'@5```:``````````$`(````-+T``!-15-# +M2$%#2"]-04Y504PO34%.7S$W+DA435!+`0(4`!0``@`(`*%93Q\/H454Y@L` +M`!LC```:``````````$`(````#7]``!-15-#2$%#2"]-04Y504PO34%.7S$V +M+DA435!+`0(4`!0``@`(`)593Q]$B)ESD0,``($*```:``````````$`(``` +M`%,)`0!-15-#2$%#2"]-04Y504PO34%.7S$U+DA435!+`0(4`!0``@`(`(M9 +M3Q\KWL?/@0(``(0$```:``````````$`(````!P-`0!-15-#2$%#2"]-04Y5 +M04PO34%.7S$T+DA435!+`0(4`!0``@`(`()93Q_-M(::R@8``/00```:```` +M``````$`(````-4/`0!-15-#2$%#2"]-04Y504PO34%.7S$S+DA435!+`0(4 +M`!0``@`(`'=93Q]G\6%'&P(``.@#```:``````````$`(````-<6`0!-15-# +M2$%#2"]-04Y504PO34%.7S$R+DA435!+`0(4`!0``@`(`&U93Q]UFZ<[/@,` +M``,'```:``````````$`(````"H9`0!-15-#2$%#2"]-04Y504PO34%.7S$Q +M+DA435!+`0(4`!0``@`(`&)93Q]D;)Y<^`H``$$;```9``````````$`(``` +M`*`<`0!-15-#2$%#2"]-04Y504PO34%.7S$N2%1-4$L!`A0`%``"``@`55E/ +M'Z`*&3%"!0``DPP``!D``````````0`@````SR=9E]!$``!E3 +M```;``````````$`(````(skt*#GY4*RqB+Q& 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 e2NOe_`v*a~XT!P9.%@@7!@X7!AXF* 85!P@N!PX''@<. Q4$ P4& +M!0,.)00#!0X#! ,%!@0.!3[__________Q\, $"% <$' 8%;/W]W0@1!1(' +M!O?W]X>UTNG^<-:MS+TRO[+[^4[?_??SKWC+IW!_>:\?V%Z%UP\_3,2(8S-A +M_O9UOUUGSMO_:N8G]<.Z[0^U*\5;^)$4L3+_Z>W/OWFV\K>PVR#&9HCN_C?_ +M;ON_3E<<_R?P)#RW=M09[O!MS;UE?/G/TOW=E/>MXZ37L +M2CM;&,!\EY"(;RQQ7W:6]DIO]GMZYF!I8>?NZJR\/![P1PK](/[K\[8,ZY;! +MJR>Z/T2-OYFB0INQ^Z^;6[>[5'58,N>%X!TN@FOEKO[TT"YGX0R4%DOX#C@\]IO^T +M"($W[!NB7HM)BD](DL3$_#N"3(BM)<;$)M92'BTF%^WL,Z77%L=WUQY7_LSQ +M#MGQ9;$/DU!/:42($#XM=6R$3PV77-GY')][1=V10L7088CCV,34$L#! H ! ,1Q*R-3<>_V*P "P ( +M1DE,14Q)4U12B@0ATJ2( C-IV)1ADV8.'05MPHQ!D\9-&1=H((9)"+',G(D2 +MT;B(N$8!4$L#! H ! & $E,%2$=+M'EN0< +D4 ) 34%#2$E.12Y( +M4H\%!O]/ PX/!P@/" <5%P46!T87!A<&. \+!0<%!@06!P8/"046!08/)08' +M"!<(#P@?!0\$!A4#!08%! \'! 4$ P4/) 4&!Q8(__________]/'@$"0P0# +M! 4$)18'!@P%!P@'%@=-" T'" T(#0@7_5T8 0(3% ,$%@46!P0%%P4'!A47 +M!@;Y_]].3S5_?M_7W]4V6? +M?VU?7GVZ2[3]+-_E_=J;CGV;X7M_C;:D_;GTZGMUK_]Y*E:K/^Z^^5<>^:E[ +MK89?UU=_\WRXZM&WN/P;;&7W>3JV[9CVN]+/ '7[Q=]VK_7W6L8/.@7Q^.#[ +M.HC]N?G9OLB(>=D1\3C^O?4[MR'-1&3! OS\P6#:->?MMRRC4/\ +M+SBT(Q(KT?->)]M[E5?>YVF)'FB']9>E\M:]./_N$7\E[*]WU8YH3;<>O'*W +M\D]8]]BWS/ND'9J;%SYL+GII!7NUMVI'7UDG_S.^((];HP-TB1'7\^=BOI6[ +M,N!W?1F1LL(7A"O(#?]SLG]FEC+ TXZ8C(_=(_R)9ODYS8/4/2WCQ&;9I/U]9JIH.>*GZV +M6ZR%>X;I=1)#H,8".=L=U-(+W6_GI;32PW3S5$N@G79ZJQ$F)?5,2D_I)\F6 +MA$9*4K.1?J:9EE#]=K^=ZB^6V.XT.\T0B:=LF*8W6LUV0J\I-8X1NZ_UK3BC +M2;JOT_T L0R^2"'5/MJS42\9WW!I58CHN3*MUA*ZA+ZUME?A0R"3,P(44V.< +MWQ1C4_!<>S%'N21C7)R/N)?Q0YV]'YG3',4VXMXT&,EC+N/R3_D))_7;KI,NRW5OZQ76YV[:O<51\UTD>*B&I +MW>EV4=-DU-Q0L](P@P?W5)&27*NBQN58XU283Y ,7D-/;$',4VV_R);7)-.N!V?9].&ZR5Z^O&[GUO+SFS@A +M'";CGP#,U]JQU(AY*?H']0-ZR_W5XEJ?<)H8@_@;8&9'51O^@^D.YCV@-QQS +MZZ/1=(<#V\EXVCFD3[*$CH(A,0J?V_*1Z1@.H@2<%P6^)N&AW17)LT)?4HNN+TG0Z4M"PB%]B6NX&-BF+CF*ZZ*$"B0X +ME+S;BR%(2#2>2K1@5Z\B4ZJ_M-SINH4*^#VP'[%,RD>\AO"@!+(QU1*=I(C: +MP)%=-;M;/2@]D"L9($>T,&B# +MTB&\+# S%9<(X6#7P+=T+=26Y)#O,]7==Y50__JQ8L3OAP!07);84 +MXL0_9Q]1?*;5(::$)BVMV^DW_WC,(^+IG80PW9/T.:2UVTE*;;BV; @: X/= +M;:1UFSXBJCIU&+/3#$)48%$0:'UNBG!NNB])NS5)#30%=UNJM>HQD$ ;M&*0 +MPG_[:6$6>)KF78_9-0)_Z3:,EF3-$,E]@?*"PFK6%GS(R@UIK@EM4^6A2*1K +M\S!%#ZJE>7=RYW);7#WTEZOV;[7ZW[)<-MV:$%IWO.KBSJ?O_?)UP)URGJV%>0EREC<=V:DY^3DY<5X9G!=]$X;@<': .[ +M<@/YOSVQ-.\H-V#$,A8+9U#,$^I4$5DP$J3A>@+H]H^H00/<1Y0L"J]8XZ/H;Q(6R%IHH6&$A4$L# +M! H !@ & '):,R#1[MF(?(0! 3? 0 $ 34%)3"2?"?]/"?7U]=4&!0H/ +M#@T)'PT+'PT.# L?' H,__________^?%P !) 46!Q97!A4W"@@G& D("0X) +M+O]_!R T!105% 4$%00E!#4&!28E!B4&!085!A46%085!@46!7:M "O !6@$ +M+" #[ !]@!70 !&# #$!/B "(D!8@"X@ T0$B#D%9$ #K !W"K "- )\0)P" +M&J /,$X!&6 $+!N0 1&P8H!F0 1LOPG8;C_;K&;;1<#V\_DZX+F !F@&-, ' +MB QH@'X6L #QDE_"#\"'S4>V.^E3/QVPZ'Z[/^V7A]-R?]KM=N%[P (D! @+ +M6("X &V $1 !$> "[ !AIP ?8 9HG@(B( ,T @S);\ >B]/JM-\?&3Z[!RQ +M1( /B !=P-K9X "M@DP!]0 /, =Y'CZ:0 +MSXOB$_-QP)?S\>ULLPS8^; ^'#P?XB- /,U%#- &N #-@ S0!N@"7( 9$#*/ +M*S^@+H_O>![;W4V>I7Z?]C5YE.3!B;P!1H M\JY%'F:_%7F*_-?]7N05.LX" +MUG=X/&#- !>@&2 FH ':@$W$#N!1P,L!#3 #S( ,$!?0<]WRG[2SF7O $^=R0 ;X &U ZQ9 +MP-J5D0\&Z +M"[ #(J !=D"<,P%60 ;8 6: ^( &6.=V@!V@&> "] $^P X0-PO8,D!"@ ^( +M@&<#(B #(L (,&OUG\@>X %OCT0!S_(/]7@*F\(']%3ZP +MO\(']E?XP/X*'YCB!Y-A*P$-L /$!42 3BN[.VSGJX 'W+7S2\ #W@\P Q8@ +M+, %&";I &$!\T@S? /L !<0 0N0$-" !21X']!+P (B0!?0 !]@!2S !Y@! +M"\B !9@!$6 %^ Q,'] !*Q?2KLVN?X 'Z"U^08\0$) C?J !62 ^ #QX.F +M!NA/ :L'+$ 7D $B XKP!^@#%A !+F !1H 94,>O?PH?(") AY-F_@;X@,#[ +M7*4/$!T@+& !#W !XJT^1_KL%'"69, "Q 4T($Q^YS] 1( +L +$6'T#C [ +M0!]0B7B "S"/ 2+P$G81__ !9H NP 58[*_DYP'BF;\!#[ #,D CH %FP (: +M( [VT\##*4 7$ $: =J G4<@7XW/+J:/>Z4#[ !Q 0W0TWW.F YH@,V4\H"Q +MO %F@ O0@/PYOP&FQ0_T>8 ^H 'B S+ "- &1, "1 ;X@ :(""C390%&0 2X +M (V #(@ KQT-T 8("UB -B #C [0#- )W(MTT<#IO5HP (D!&2 *?P'/$!T +M@!7@ L0%6 $9H!%@TCT6D&P)I_ST8O\'B,:\92X[!03,#_^]P'^I'PVP FKZ +M9/Q='F=Y+* !H@+6ZN=/ 1KB,4EQ6WP>(#X@ T09?F$.-D C( /T 0U8@ ^( +M@-K_ 4: '9 !(AG/@ R0H'0-\&27!8AFCP;,X@_P 1&0 =H 'Z 98,)<%N # +M[ #- &V $: '_P,R8(QG@!C;K]7'!CBW;X#EW8*=Q)]R?<0 H0$^0+3"80$1 +MH,,K!^@"4ND.T 9H10]#_OP2L G^0=8 29_R0/$!WCK;T $+.!JY0#Q 4: +MENP9H!G@ HP ;8#>97/43P,6T KP K(@ A(PL,X?X?' ZH?#C"%(QZP (T +M%Z W>13L4/K2 &'J7_UK@!7@)'^]-\ *:$!*?T\!ZP=H56_>+\L3\C*(2Q4V +M=?Y<_E"55>>3+-] S4T#] $^P.(Z UR %2#L%+"D\C/ JSP6H _P)BMF.$ S +MH*9K0 2("*C)'G"QS\Z[I=^CD(NC;$[RR6' Q[P;H NH"0W4-'-1W.L*D_2 +M(]E_@KT&B/!_ S0I7_>5TF7(99?O^K0*V(/V8#3N@ RP C0#= $^H#;^N_GG +M ?=Y!A@!1D"%JT([^1\@(: !XF3?U68C_%$!+V\^E>__?P@&!\%'\#Z>;?.1 +M5C 6.:6RBV#P7NH$@\&)P1_<;M;;0Z;_/V0&Q>WF?5IOWI> EZ_I_7K]">]V +M&O^UT]]L)^GP+'F<[JO303QP5RQ\>^G+KO4M?[KWWNX\+U4VB6QEGWY.)L> +MET_+<2H>661VCT=O^K\/@N]?[UYI!R8#CY5_H7O+E?>E]')YSO^FA]AE6(]D +M8\UM-E2O)&OS@)>;Q=!F73Z_+^W49/\?34N]7G9^;'8>TTA^FY]])X&3P[#? +MS9[KR=5J_E[>0]/[?- IM\OM>,#+X=_N_FYM8L=H,1G?[>J54BNQ>@^3V6KX +M&.OM:K'F(UO=CMNKSOI^;)1JB_KZE;XL-K'HWOVMW2;-;_PT'K:G]5DU?XN4 +M#KGB;.B4W\D)R.PY/Z]II+I7+I96VQ#WS,Y-Y]*C;HI'J; +M?2HP%,D.:KU,:AQ?M:?W2*E2JXSOHT-S7+R5'JE> +M/N#EU6P=3VZK\?F\'KR'U\5P)/[\##/16C,ZO0=[W_&Z?6F76K7H[%QKSO?K +M4R=1C.R*H>"F5 IX.9\_.[LLO%!;#V;;]OC=?-R+I\S[W)E?(G^ +M!X'!1K :C\0:Q_LR%]J\3IUJ;7Q>)-^)2B8>3ZT"7N[MCY]W-7=]I0>K<'3ZKA]377#W8SHTCW%MTU+[/KO=Z\3_Z+@)?_E?.J +MG5KE>JWON;>,QY>_4*]1S[7GPWVKDPZUBN-XX+35F#P3D\9D-3QG0YM*+G[, +MW8N-4,#+K4C@]E-=K#;?>.Q?++]JH=V_UMS/@I]<(QZI9/[Y8.65+TUR@_$H +MG?[\ T/=]+S7#@X+*_O__#W74[]R99MM93/)T:#ZW[>^C_8G70A'Q\'U\?/M +MS+>%;#^WW;8#>XUCM);(!KN-WS,Z_]E_1[?%\?*Y[5;5\6?<[\ZFN\_,NE=T=&L%?\W7:' [3@)CYR:>3'<#6Z7]]; )K%TOZ<+^]MHV/H'[32O]K]]._W\YOJ@.K,N=[/T: +MSVZKH_5M-EJW*HU6*[^J3^J/U^,]NSP2S=26ZGS?)Y?U?WP+M6>%\'X[7ZXR +MJUDYX.7491^L3 O!86;0#)ZOU48Q]YFE:\O@9Q*S^2UZ#[7\_X.7@,#QZM'+96KDZJ Y>P^<\\=V,AO=;%[D<^#STDO-; +M9-AOO(_W_>)\_SZ>]5W^_!X]MP,NSW#$S:K\WO]+BOFU,Y_7=];U^=7:= +MYWP["JRCB_C:N%XF"2ZGC^Y]*O>&H.M_MRY[(XMLNM +MSOX\'P2\7,Z'0L'7;'J]3S+3>_0W_]4;B^LC]',R=J__[^=?J_#?7;_E2#?VWWVJ^_7DM +MUX=7OS]Z[>?)7J6_:8TKB6 L5J[TBUGO,S#XVWYFM7-QG+ZV_YG@X+/XO&;! +MU^O1&8S[^W(C=8[\_I5V[74=1-;366O=2AU:M^_KD#@%O#S:A?[+;'/RF 6? +MP]4CVQSM(JM?[#K+;'^S[?MZF%Z"J6XFN2Q4P_OC.+$L)M_'\>48V.]^ EZ. +M=J++P%>B%W@\;F/!:VB4#<;B\U#@\5FZ':/#7"2\RIZS@?]L=!D)/VO]9.S8 +MN+YKYVOX% MX>9(_#,>QY?[=CX\RD^._L8U/"]%CNEQ\'F*A]+%S+62&L> J +M\9VL[OE_L??,S6;!1?3PW[V=]]^OOA_\>_%R=?(Y'"KE_G&<+R6"O51B-ENV +MOZUCJUC^97NQ>V-1&VQ"B4>]VA]F@OO!5ZN<_@Y#R^+J/@SG/YG9:_Q07I4,GM-Q?BX?!-)0)[#W/D=!HO)F/$^5(_C@LV?_-5#+^&GX.PV.V +M]@S,1ZZ3<#\QZ><7TTZAD\J?3O=2,_M)WLJWT>*QW/V/P7/\V1FL7]_Z..#E +M=:L3N"@]OY?:*G?I/3[56J+?VMWNAU(H6WWL]XO)X'Q;3@K]QZ=_KP1OC4$T +M.(G'VKET :;O6PX]9LT&L-'8]+; +M=V.5=>FY:IQ/B^3]>_@WTP$O9]O#^C%Z'@8&-O/KQ&8P/0T2CJVCTW7EW;I:N35[%YFRU9/9)NQ=KSI>G83W3C +MM^!AUPS.TY'^:_/X?_.I8_^U"_JLZVLB>[XL\J]6]Q*OQ^_UXVD5N/A'9O7+ +MX;[R:W?G3&+_2/4KZ]IBMPH%"_E3;=KLUL?KS[>=G ;_O\,_OEB??[UU;?"_ +M#=ZE]*:1*4Y6[=5>J'A/K0:OY:)XKE[BX4[FD,A5=[O8?U:_+V*'1K\@F*]>FL?F.]&>?8ZAU+\]BW0"7EX^@K7&X9D)SAK%R&\QV]]V\\GN^-DL +M$IO%;-)O]1:ET*A5'2,XWEY$]13TW'6F+]";7ZT#]ZRF_ABF\X49AMQ:76Z*J8?WV\\WSBL.Z5:(]J> +M?O*56;!362TCM5IYUXQ7XU[UL3:*Y[[[0N]UN#]O+I'4-[=[O +M:.%9_3Z^Z?>FO\O>8K-4Z5@9'JN#]B9C%SJ%I_M,)5;^#T*%:6V4*1PFFU_UZ)0R:Q7N>3M$#E6>KGG*1EYG[JS7C#7JBV"[4WI$-ZWS[7K8-!;SKK9 +M1BXRZ[:"1M[.>5$);BJIUGS^SD]"AT.G? TO?HU&N%-YQ#:T?WW7B68ZNU;F +M70LF6H55+5O]'M.OW: M'L[OG]%S4;"/[2^??GK6JS;OF<C7(!%??X%]JWQ<>S]>Q +M_SUP0S_4AA.@F\Y>/W\347O2_JN_\@T9]/OJ-;=;$N +M:)5;WUHG.'I\HH-XY1I.KN[+?S93J>Y"JT5]/D@>._7\:5L-!HNET2A2F2\R +M^>/C-[Q.,M^IZUS)' K9=ONW/M13]_\W]NE_=MOO?G#[]4>'XW=3BO5:N_ZI +MNY[/CI79LKO;W-_E1V;0NN:$O<-7K#$K5\Z5S/Q9NGYS[^/NW)J.CK?U8S)- +M+(.QY^.;*6S^N^EB&HJ]-NE/;W"=#R?%=R\;\/)BVOYO4I?G,9YMSP#]K@\=N%/Q'YHW5Z_"*MF^EP)3W6>N7W\_(\AA= +M?0:17K?P>+6/V8LO6)]LK]4OO9Z)EFJYE%I?SJ7([C/.M^OYBV5V$ +M,L5"^1Z^=;J;$1?Y+10<+ >#9?S?GK\&R_HO_%RVDIU/_/D*]H./Z_;WM-!(AD-W[^]^^M4CJ[KUCJ=_W<%F +M'\MT/O_G9W::K)[QA]P;*XZKF6RV%CA9-AJ;9?P4W)Y_P7:S78L4L]UIL1I9 +MG/>OQ+H1VS62Z7UP\53*9ZZJ8V<8_ +MV7OOE0UNMJ_U8?'KQ%*Q6>=<.D:WE64B%RI$F];E8CQV6G8+[]PUFCN^CZ=< +M\#TXM2*/S+6=?L=BV]ALV/D0O.W\MS0]]G:;_RMT*$Y?XT%>[(S."O]YJ9A? +M#]82^79W. L-HX=(8'\0?V9.S\<[FRW\JM7N.G;,KRK#WP(XW I<%(^_^#7@ +MY7DX%PXWWM/B/_J)*62?C>SRD!J'&HG(/7'+EL?;:N']F$\2X5 HWZDFHM]R +MZ0 <#"\B0=N\PKPZ!;^#=*IWB;R3[6\S\)]*#%O'Z2@8FAPODUAB/7C]YNU\ +M,Q8IEM[;R+0_"7ST0=*N\S"QB\>:NU;S'QT?YY/B)GX.G-6JO\&GD(YWQKOC +M8'[<5][91R[VOJU?T^EBE5W].N'3TG@]%X*7RO.XF$<_N]AT>[^$=JV(<;0= +M#AX^FWFC7\HOP_?*YO:8I9?A0FY5:L?&Z6FF60_,N1,K)$?90O1Q"C_ZB_.H +MNIT_ _N?P^@:;/XRT\ES$6D>$O5-JH)QY^=?N-=K\\ +MR%>6G40_%C_-*H7.>;#ZGPSBR6RSD +M8T/11&Z;GZ[*F78BV5Z>U]W893!:!*OC[[4>C@1;W6TXT\S;7K?0JT[T]NK%K_3:/C3JAZS"5#3SEFLM+-U9/K0,C +M]TOULK[/G? +M57E0'DTOI_3W,/\W+I7_J)?N13*UW&0ED6[VHH?#9[7]=I/18>Q8WA^*O5?U +M]VCT__FTPF!:N]WW66[=6\^S\'5 +M[U*]>E)_$YMJ=)K.E@,+B?2E]]_DL<&?O?,B&$^NYHWYNY(.SH_WP?(ED7IH +MYP[3YO,VJE8*YVXGL/!=I:^/X.^6Z(3ZF4LYMVCGYN?\MA)JA9J=^[[7W_?G +MSTL\=1;V#K>K3SJ?' XWI\+E5CHFM?Y0YY*/G^:O5&46;787C6@F%&[,KH&+ +M8?,:C[\SD_>D.!KH_>UD,7';IF:-:#CR+=4[R6KK^8DVELEH*51/1;/IY: D +MKGU&QN-R=+*,97+AV>EQ292R.[=HL)0)'M^GWOWT;U0_^TYILQ91?]/];;3Y +M';SWN79CL@LV@].Z-FFXNXKM[O_\86^C/CW%SM2RF+WN@_GPZ17?EZ_]>W-W +M[V]1J'XJ_T./A_ +M9DB"U<8S%VS7RXWL<3_=1 ^%9&/WG#='Y\+V&+M_0Z/4X?O)#L+==:#I>/XG +M;LU9\=S.'9.=T;K='OYZK] []Y>GS;T_*'22YK$_%2^#P +MUJV^ @_?^/@5?7ZZ=O%'^+_IP#C_@V9]$YVU$M_<_=F8E"8I1^4QN @_IHE3 +MKY;M3!/S^';Q>)Q+@8UQ>WZ9S*MV\7@\X6G7_RNZT- +M[JE#KU>\'TN[R+=>?Z>3U51GD9MELK]R)O"_W9>J,,9)8]&<['[5XZ.32P@5 +M)YW'LO&I/5NSTKZ_^"5/G5FE>-F<#X7C9[KI5M>/\"E3V<\?V6[U'1SU@^E$ +M8#3<"V6G:SGBSS_5SR;#VQI=]C=;%P,OAU4R'=^]][_Y<]$+WCJY3Z&<:9SK +MF_NE,^E]S\'U)9-O=&Y]J?W?:%QSQWTXTYH]$IW%87-Y%#N!AUPN>9ZL,F36 +M3V87O'97T^ZU7[H7=I5Q[C/LQR;Q1-FW.!D>-H]"X!JPC69'E61QO(CG$_UW +M.M=L+!+=12S?K@4_;U=WX#Z6'?9SK>=]FAU6Q^NGCC)1'^RV]7DB%?CH%GY4 +M?3=XK1WFT\;K]LL4FX'/W2DPO4P>3J5J\',8C[OQQ:;QO@Z;AXP<<18MFTZ] +M]\]E_QQK_%OA^C\QVR5BY_+\GUTTJI7O\Q!8F\Q?P\)]OXQ)6%.E6*U:?"T[ +M NWA-YM,KN?D,]^-Q(KU6&28NH;SD\VC5?AU:X=]*S;O]&_[:7!?K>R6Y46O +M_&K\9\50?'[0419FM7AT7&H7E^W5_S!KA@,WN>ESUXT<0I/%NSAJ7\?]7"<_ +MWN9O&F>\7TG<'Z3)>S_RE$@/$ZOC8CC>5^:)=6B8G@U*N\]BMR^6MY'-;#ZI +M+SJ=X*9]^PU2^5\IT?PUXMM#X*$?.87?>O\Q'U] +MJS1_!.YBT6RGM$RD_XOUO#=(%7Z1UJFW7*,X_>F/5[5U)##X?#8:X\@@L!F[+Z_#4**TV9Y^A7S@ +MOA0/!1ZVZ_(RF-S^VD ]=$\5KXCE,K]*=YS=_7=KF0ZO6>)$\7"_![^Y^"B^FA>4I>3YO +M]OM++25N[?1GT7Z]L8W^]\/D9S3])P'U]\Q@EU2/=A;S\W+]7[[?OU0Q^!EC +M9P,_K>:K''KN6_?78)+K/@[1_/5;G79>\7HR?OZ^P]EQ;S"XJ$>WF1*R-?_K +M#W:=8/32+NP'U=>A''SL.KMZ,3J=3VOM966^?60S>4S_+/X=!GLK><3J_K>7!=O&>2[=9YVK]4\H5&J="O5"ZU=B31C'>2D5\A=3/4KW;+ +MX+MSWSUG:G>JOEN7F_5LJG^;#CK99N9^^!VVH4WH_5G-<\'I,YG[=1>9='8; +M:T;[S] \F^B/4I76L"R1/@Z*I\DU>JED.\%3+7RN]!JIYG/UV>7>]?_F?-VW +M5IAU+%;*-//M8^9WN0?%H[G%++LS\EX'M> FL#KM]Q[_X3S:V9UFW\0A-XJF +MMM]ZK3>]I3^6YGBEU3J=HZ5B% =]5MDW>OUJ-N^]9HWP9U>^Q7R,7&-R^'K?SKYA.';KKQZ"Y294?N\\\4*-O+)[96ZMX +MNN2SCX:$,)@6Y9X&IWSM-+J_U[%4XA"*_#[O?W8T//8+K?EA>[\_ZJUC7F5< +M#ZZ9T;BW*YZZ^?BS\@D>%J/@<=./#D/523Z\7)X:I7DJ/)QW$XMGB?XQ\:JOTN%::X^,.@^6 +M_ZE&_9J*O'Z1=KW5Z'4E27N1\20^_$=>B13Z// GKF8?DM.TIO#+_TI +MWG++_S9\^*5>HUTUU6U6WY=P??/7^V.C>J[Y?T2FD^@P.^Y<-[_^)8](6&\5 +M;\'-._,LO%;!+?:YNQX'P?DBW;V<%I-%,G>[^!:#M_C^O*U6#_J +MZ_+\=WN.OX7ZKM@)G9J!\_]W$+DD4IU?N1Y*E NC\?YYKX]ZGM+?HU?JK)NU +M0REU/BZ*LW"N4#O''Z=U+?G(%S*78SS=;L4W_<(IFDD6][G'OK=^]H^Y_J-C +M.HX"4Z].JU+?KR:;33*7&64:H=IB\FPWR['2/#ZH? [/;WJY&1VNOURA=?X= +M!HE5(MW=IE)Z?SM]/B^CH?WR]]]\N\?SNOC)';[W*C>'J-+=9],O=*NLH]'<9#=?$KK3?N1[WX:G\S@D1J%J\%ZH9D[$H@? +MQ?KX?>XM^N%%/MRY)"9A#^-]>$V4G??M^'/\-)O+TGN]?@P_C];PEIZ64\]O +MI-2K-=ZYS"VT6UU#F5-Z]/V6__5>M?W]+'K3Z:\=U>BF7HM0HIWKOMZ[R_XS +MF1^R\>HH';N47\?MJ)A,=DNO5?TPW2W6EW0P5EF]CH7;^+?\KU2*;^_N_.P$5A/-\?YPJTU2]^6K==NE+Z/\_OR[_X+A78R +MLMUQ8SQ:=0[UZ>3V?@XNVVQC>F@^WO=8/O;' +M7OZRS<0+<>G@Z7+X]";%>G2=*IYFU7.T64P73X&A 3SJ[?$I7KZO9SWWS:QO +MBTYZ=FAV"[?O\-E_WA:IL/E=6=2:ST0-J[6FODT3K<]R7@Q\K1;K3+,Q#4<; +MS6M[UWTL([MF[IT?1:/K6#:Z&]>[@?+\.V\$K=6Q>6XW->1=)'Q;G +M6R*1'[8RN7N[.GG.2P+JRW:,\A^_[VLK='V>CF^S?>Z%5KC6*-7W ^RMXW;;_]J/WF,=ZG<>HR$+?B(;JS=RZ^WUL\YDPNU:NKB>S2;"Q&A-GV\=U+_$)[>Z54G;,$0[WWX$;.M)],C%;_+^AQ3O5ZC:. +M@=?3_URLB62K$X!XV-<^]'U+Q]9]UAZ]>A#<66K3K4=^[\ER^CK&JO]??/8_ +M;=[+0?)$AGY)/TY&WL:PV.P,\]O9^1DZ30>Q/S(O'['1VN3_4W3L\Y[ +MWVC="H5_,/DJGNO[S6!7:U63P\HA1U?.[#?MXN ?BUIK#D*?Q+65WV[[@\:M +M6MZ?XL=,J59[CZJW>#Z&-[TV4]Z$-;3KWQS='ROL_;_0/F^Y@[! +MR[>WFK][N5GE_/]N]G7S8O[^R8^[[?YJTKOG[ZO%9)?>32/[6Z?4>&\"(RO# +MY.P^_Z=ZK^D@]+SVZIEJZ-)HIPJ78N.3F_UV]4FD<$@LQJ'(=;0OW)8SD/!S +MEXJVO]'[7N]OC%J'X:-=Z*VV^6-D_&O')JM:?!T/U6J1\NB>C)(3-A?5VF:_ +MJI6^E]GKTAJW9OM(N/.2YP\^L?/LGRA73_'=\+8I]':52WKQGY4SPQ3QZ,N$ +M0ASTLM-.>[A99&#>;.!L/3^=WZP/J?ZGM//E_^_Q-M7'*3CMOO#XU>!LWQB-;_'$K0-"N2AF9J'8:EMTB^YNL?9K>0R?;OMH +M9%.?A@.+H>/,E)Y8[Z_Q\'G6FU3CY?8QP6=M)(KY5FH<&(T$FY?=2JAX#CSN +M$HO-,C Y^Z_OWURZW&QM*K?R/W/<97JI-FZTLLL?ELG2.KXZ3Z__X^F8N?6& +MA7S/^QS?[JUV;O\+'3O9[,EIKJS?^V6P=?Q^6XM98&%Y+22__TKI'1@834\O +M^5UP4MSO?KE4XZ\RID?]ZK%4_X\'Z]SP_7A$Q_5Z:EE>38?Y=3]<_29GR^2Q +M>$V.1[UHS_PL%";YPN'_*LV.,O.W&QF>NZ%DJ)K;ED.+]K[W6];^\=SATM[O +M7F#U; +MC7ZQ&1Q5?Y-[[CEM30OG?G?SRD:3C?ZZ76IMW_-1OEE)CMYPZ_K8J ^MM>G$ +MY;DX1?O5QO9ZFB:_O.]DLLGE2IM]5!SSK/-W7[FC$_O1:9TVC\##OWP*_$\& +M]9DLO=UX3W[5>+I2*E0ZA>$WDE@M3^M5\77K@G,+V]$H$\\?^=>^V*L$W[-GZKZM'AIA'66DWSY>B]W^K.W:W*6C_3B=]!0<_NKO7_*= +MR"<7MK%Z<]C(#&;C<'W_22Q^>N;OLAL8>,QD>^UW)QXN1N>!Y]-S +M%8I.]GO?=YFH/$NIYS[26[1^W](^_^KGQ_-V(;(K7 (K 2]/_\%C(G9:G)[K +M5GX]3WUKR5/C47FNIMM"-C(\?%/G<3/SRT=[UGUE/(C49JO=*SP>_+:J\+/& +MJG>-3G7Q+\]!-MS/2:*]GA.AYS(YSF;OYVMA]@W\!.X+H5*^,@X<=I[91"%P +M<)W%_:W-R[*P6X^&WV%S/DAU\Y/'H/CL_)>%7+00?[S+D^JNF!L'4Z>YW9ML +M'$O90BC6J<6?K:$7.]CME>+W0[)6[?U^*_3B9/S/!/NG0OY>^NV#L<8XN3EO +M9^/6]%0Z)5K+47ES;N\'BV$B)A]OIN^W=C_YNTV2N69UV4721A;C\*_X/&XX +M_)MWIWQ;[K_%7KQ0KK^.T>CGU!C2*G/]VL_?F4\M& +MWO'Z-7MH]X??%V5^?6_#>&N7__K6O%0RG^5P,UM/!^;&0V692QUN95MO]',+ +M?[>-SX2!?YK^N[_FF[_RJG[=%98K%SE[7$A5;Z$ +M3K-9^]'][(KW6C"^2Z3RP5@\DJ]64N%8_:A=[D8?\<#+N=YMS_A=-Q$?IW +M)JMKM1NK)E)]\WM6[8]VS^WA-.\G3Y%OJ_*\/I:!TZ75?HY-8LUB-?!5:F^N +ME>+UL<619@]#@6A^&)G5M,K!RO6]C_S]< S>O5S];O>2WH\_H^OYD +MJZ_/)RE '^]7:?KU7H[GKIGQ,Q1/EARQ)\=S[CA'_M/!6#VJ,0_W +M[^%WN1P6O['G.-3/CCZEX3Z7#C\K#/I()M28G+K[QG#V6D_+FWFW-3K%U<45 +MR_[Z3!3ZW^9@F/D^GMEB+E/RN%#]5PN[*>9 +M1NFQ"[6;C]K@GZ^-]Y%"6*!]1D.MWCF3WHF$,^W68C'/K';U=.I<#2>2K2P& +M>]$:#M?/;21=>._[J6/@]IR-[Y:K9LEU3IZ_Y7[VMMUF/YWT*-9O%G^5Q"J: +MZW9+D]/]W*U6FKOU8GB_U2*%?R)]_I=[DT8F/FG%?S7_6CA_2HE=^'BX_!Z+(^7G>C5?FP_\?ZHWSLKXNX:B?W +MZ?)TL8E,?W=#^.8G'PQO4Y%G\1__QH?)[O@QK&Z.MW(CEV_/DJG]=?5(?V+I +M;;]GFW\/=^7P/K2MM?KI?:P0;IUFR\<_6=]*HM$:IV.W9_Y?J<436_*X7EL +M^:X7IZ/\N!U^5?:EXKWQ9^(^:]' P7O8=DQG<[UI;KWH-G*%Z_Y5C;6#@:7S +MH-J:+>/5S?T?W'5W_V3O](ALRMUI,+PH_ZJM:CHW?93N\O'(<)#H5@Z_^/<< +MG4?^@^FN/R@S@]^/J]JV5GGO;__SJQT8CV]6DW)^$:T?%L]U/)I:Q=8C9?^B +M=:]_3]M?>GP+K@>#\GFZ:@1?X4MO$IW%@_M^]MJIW1^1[6$XNQZ'N?,PG5D_ +MTL%[^.AOG7RTZ.]6^<,V,%-.G%LOK?*P\.U:1./-1#0^>D[+BUTF607#;??*M1[#P6"Y=PR7^E\B@X=/+'*>YAY=DL'I.E]Z]Y:$0>D_;J%9NE0ZE6 +MJ3XJ;M*#P-.JEGN\"^O"*K69#'[1T[QQG:_\K<'/Z;W[G6_OQ*,T#"1;U[/R +M?S7X%9?A?.'?: <;[\!IXME(C$?UU"<]3+\:@_,NM3T&QCRSBV1I6%YO6[/: +MN/#/[?7$H?%^,M%^K77XU<>!'.=<:V8[+8'D5'Q7;B4WYG. +M)A%8.X3UVVSK^KP&.ZGY85,K/&JY\3!Y6[8W.3KI,?;\.3K'R\9EV(TL,D.N +M^U0)5>K#77_3'G;UV^-M<%R=>IOKISZN7 ]3B7-[4>D<%M[Z^6+T'(_2C_+G&4O$@]5G +M_O4KY:OOZ_66C35GO<+R=ND'#H_ETND_7E5_Q5!H&)YLDZEU0IS[GX;BH(BA +M47+Z".R_K]GK,OTOGEO1WS9VC#RW@\.F%:H.8Z?$=9LZW0J]:Z%6#TQT[<'- +M;^CS%!@\+U:38V"^>8DLR_7$/I.8-Q;=0?-6CSW2O\!XYM0]99*M\:F^>F4. +M>VUA>Y,8V?''P^*\NABD.Y7&>=/VGY\4SFN@UV)^G9O>[ +MZ0<#P]-J9S_Y-AG+A]DP..Z\IU.Q,SU.EF[S6F_V;\;_X_&D5$Z.1M/MJ>]V +M3AZST*V83383\67@K-_J)#>3TJIPK=XRC<$A;-D/9[?<[;B+?9>9V.B47\ +M[_FL-'[N6I7DO5-9W">-0F$;GDYOEW8O%K;* KS'1J766(<_C5J\&&KG;//U +MU_L2&JQOJ\[_NWCUX]VR03PZ+N;7V>^IUS[F_O%J8]?HAF_)6"=S3.VB[?]O +MGAC-=AW']./=+)^;OWI^F>F.8K5:K]M(!0;JHX_RT^2]?SS&DO7KT7IL;++C +MS" 9J73.F_7]T$WN+/M>YAK>;%ZU""ISF"N,YI=IK/2?!.Y6V\>S&VM'FN]$ +MZ-++M!^GYB;PDFN%.IE8X[-6= OAI_./:[#]&Q3CHYV'DW]H])ZOX7C+:"M]@RL/3+!NZSJ6)@TMR8 +M&3W[D9$K/Q7\]P.3WRG[./SL QO=[[70J\P:Q>2P/AP_\XDQU'\N5I;#2F"1 +MXS_V;/.%T-G#/8K%QH%C7\1$,]:]W;K[UO(:?JS+[?APZU'N]M^=2OTWP-^X.7DENXG(L*2+7X_F+^?3Z[U-K_/U;2TW +M3#2OJ?1QD%WFG\=5J/E\#-71U^?]ICKG8&=_X55P][X%WF.QEH/]-9G-BZEJ +MX'>1K76B[=6[VY[U]O-5Y[OY5.*7FW'0K[UTCH_$J_(+I5N[ZB";&+=*^NEMMSX^MZJA?BF?:YR*)'?[T%W<1J'\<&G'[P?>CL]' +M9WA:WU?#;K #%K3'#N]WUSCMVSFU\MEWZUDZS1:W57\9?(V=@B>QC\# +M:_/;VR:B/TS*:_GUO=W*J_/_VO@\G*V?UF:@DGYU\IUP:#$O7Q^;2.W]7M4F +MY7(O%ME*HP[+WXFO=&5>^RL2)YNI: E^UM,E')AM8?V87UU'\%0^52I/# +M:YGM=.>C4'#_FC%'H]U-NZV@OC5_J4;N\FO=[8.J]WG^#*;ZIZZAWCV +MTRI-9LEJ;[5*/P^;U#>RZ7PBU5JY?7V,"H'W^WW\G76O[5.H4NB71^O[P_W- +M1&V@L\]RGG,BHMTK/[=A K%6J%ZR+5" R\_%^;_WVW>I>>S7?U +MF/W^<\E?WI1\:+W[F7EJ>JHEEK_)9E;- +MSM/3QG$7/L8JM6@OG3P?=_?^=W3\?=N'<"OX#=32GJJ;7R?ZBC7N]63EV \F +M%^GHZK0(;C^ARN^\B$>_L^M@D#K?6L=%=%U9?P=S@^BX]]]NI @OC?KJ-[8;NIU2_K^C3;7K4SQ>3H/M\'/O/8^W7]F&45 +MDM%FX]C[1+ +M/SNM?B%W*ZG=?[+HZ7),[$.E;WO:N +MM[D6=C[Y2:Y/O"JA?2V_6*_WST*Z?3^-LKC7K;_R>4:CR1 +M]N+N-$E,TIGV_!AYM6K9\2UZZI]_VURHX#J7'I/ _K1Z>)7NN?>W4>^.]M5V +MO7!Z1J:O]#RPLFV'#M7%.[F/O8YLT>ZC'UXO>[/(-Q45*C:;TV5XU;A?]Z7/ +M9?L*+L+K;W61^SU^_TO)\ Z_CI_@\SK=Q3>%8Z@_^*RSROKZZ]1(*21+2;AB +M+MTT\:XX<;?G6WY:B7Y3]=1S?#U4JHL@J/DR'QX.XV%A60L-2NO(?U:,]YH/ +MK_KX'S:>VU-W7&JF,Z=%,[EJ'8KQ62Q^#!2^;]'[,+ 1+NZZJ_CM$BZAT+>M +M_>P9>/HN1V)G^!(>?T_W/[,]V_]ML__4[_$-M]>!HT@G5LJ?T\-VI5J)CBO- +MS>Q0W)3*\=[M_5N^1O6D_9^>#7^G;E+>GTY=_K]?H)KZ$A?&+7WWD=K_O([% +M:XGN^=PX3\_)RR=_,5I+^V;5A:E)?DF/9\#PI06I'HQ.NVV V?/RFH[NK?*3:P6@AT?VAO>9;B\7R0[-PN]X +MD2G=6 WZ]TQO65R7.K_,/MBO3'K!5J0WCX4KD^$T.@NG0Y'BH]BX[X[9YS,0 +M+9N/.H"?&JW>,)H8?=_-C((S]>LU?-]08EAZ112>>[C6*G<#<]G2LCZOY:NGQC>S: +MY>$S%=YUGG$ZS-5@EGE$W^!N3VEVU]G/?*[SR[TCI\5I> +M1K=U\!Y,E/?S4JB5^LY^WWITE:WT1O=NZ3,0D6;BSN+PX=])%]JI^2.SJA6[ +ME>QS- U,G3+EZ62W^E=G%Y'XX#'^SQ[OR?W=Z)QOJ6"TYIE=Y'?9\3W>SJTV +MR>QONTN49ZEF-[I>!%\/9G,WL!X:+]/]US4Z6/_/N]GU/4GW!MEA*' L5$PO +M_;.YTRX8/=V_Z<QV)]%^K]ZN;>Z'T'RV.Y6>U\DJD=B%Z]/?(G^[3P;: +MWM'Z*Y&.1DJ9WK=3V#3WSD8[PU6_4JVN>V^]Z_&>I^[O >-U&22V;G*B]/ 6+MS; 5^ +MG\/QI3'Z]#*E8#YUZIU6[\^F_AN5^,[]9SS)3<*O4^C4O4<'RVBI/YDG[\JSNGQU^JM@ +MXGO[=__N;Z\3;_]GV4?Y-]^^XM-!LY'8M&ZI]>BT.U>NU^4T=6\MCK]":3O: +M]DN;0[21"AV7GVLSNA<[1Z7'>]D;YK*/=^_3N/[F@_3E^%NN&M/U^Y,^=-N[ +M?/NW^2V'_=K[6WQ=N^O8EK[O];8S9?\K=_Y/BXOHZU IG,^+]&'0Z.5BM<&N +M\;Z<,X5LZ-KX/V\_1/.CW[I][M?@-#(^=_NO<$ZH6(O_$YGF-+6+BZI>^:0?T4OV]3PMTQ=PLG6\[LN1IKCN9OVJ0I?S%W?[71Z +M$+K#=>V::5270F; ?::0 +M##QEA,;G3>7LA5G)9QK_[#)V:![/F65SK(;=6L2ZYV^^ES_$;[?: +M==?_13LS)76XMXZN5JE:9GP--WZ=V/]9"S?KBU$EU/Q'!XGL?S;^63.[Z6@I +MO VN&>M/.[!P"CQN>BY.N.CZ%+@M-6ZA6Z>8VE3'*W#DX^T\F6Y3BW8\,HOF +MBYUS\'!ZC1^):.!Q\AK\M[48"*1&/[DV+KOI+=&IK>?S].3=WAQ77NIE-%S/ +M1R>;Z#,\C,5;HUKGW)[MRYE5Z94J+CJ%1N!P*W:&6Z]18+_7.__'LVDB_[V% +MOM5RJ/#K_WZCXJ :R^^*O_+CU;J,3OKYZ'OE=G='\>!\M'&=@YE<.#Y(?G^1 +M\[RS*JQNS^1ZT@LMG]7&875IG!/#:>MR/SSRP?%\L%V55JM*L!!./A?9IY@^ +M.2RVB\5-/O..9N/+<3B^'%WN\TXV75Z#!/?ER+26K39#^77D6*V&1]/-ZCM; +M;N??_OQM8.VT1X&SS6][S?2Z\WMI_EO?@LEB.!09GX;3QW6?7JVQ,0,SGW)S +M5#SNIK7K>'+;5(;G]5E,G[RN6Y%:)S;8-9N%R;3_*M3VH44S,-XICB/!6:J3 +M&>X[D\\U5H@?[X_HZ+0H'$NYZ$\$7NU>[@+7_V;B6,KW=Z-=8UFHYS_A8S(X +M[(8&T<2P- _LA@?7Q'!T#FQ6]\E*_32XG#:K9F;X\M;/[X$M/.JQI9VUU#XB>^E@?QG/[ +G +M_VGX]^E_OI5+MG,+;%4!L=.3R*<9N)D>DK-8)SFX#C.9\:N<295:IT$RT0B= +ME-95?K+O?K>?V':3R1\S]^6T\>]F8\/,<]FI=(ZI:>V2.8VKP_B[-WN>PL5( +M==,O;P^7XS>>,PN7<]UUJ1]?):)7#>C?.!U<(@74X'?]GV5$C);]O';\OBKK#:E7KV0_(VZT\:BV,R% +M)L%$M22$ODR>0N-%J!L\)Y+9R6JP_CR&M=CT$GWGC) ?9:QV'SW??H5E[!]J +MMD.#_+<4FG2"O5D\^PK=;O=*:9PO)*:RA+768[H_A$[?]SS[2+5,QVBA)JBM +M18JE=7B_L'\%0IP8'C+[SGF2Z0<6 +M8_M_Z-*^5I_GW.Q]45K'R?(N,!3_!<[.N4JAY0+Z.:USV<:\4\PNY]-Y]U'Z +MS*Z9>XDI7=O&Z[%]_30%A[R,'AI]);1^3*_I?29>/11"Z] X6Z\VWZ_=K7^Z +M5N_Y^RI4K(=&A=*L5'/EMBJK]/7T' =JT$-V\=_S7PAG$[=5?KE9=4?#9[96 +MC_WGK5$D\DY6(K]4,WSNM3J/<\QH[?:,R >CTZVGMWI*KM8H?7N9N?0;DV?9 +M1?O8M8+Y[J&[;12_V1H$?&4ZUM4?2_?AM;O9+S>DQ>YVU2Y,?(N+P&S@(_OK +M-K>57[/R+?Z'A5$X&!F.!]]G^G0*WB.-1O(:O5\8F95/?K=GGX3Y'/H=0T@7T "H_KT';\7)P&Q4%Q/)Y.4^'FLYA-9./_9/14+%XOILI*^#B? +M1P/K^";WB^#]6@R\W":WY**Z +M7T4QST5Z/]M5:'E[1 ;1S[0O23KH%$?]>JQY+]?ZV5^Y.?U5NIWS:9[H +M9I?74"\3C^1:EVD^,9E\/H5&'!1WEQZVHN?5LULU5O2C=RV/GGO2M-7,QCJ5>;G8_X>VGW3H=&E%KC,4"DO^T:CJ:/IY +M\*L\[?L +MWY?#LGMN%E?G7OE^[QZB\W>[THX>9J-/89,I[(ZY57SU.H\3@UNN'R_L2Z_] +M^]4KM<;;0&_];+_<]6;USZY3S?Y'_T3_LRT^EKOE,G+,=1+3Z>(UCLVJZ5@Y +MU(M=ZZ5;]G9+/,LP;[*A=M]BU^;_N@V,W'?+9RB?7KS^V7B\J;%7[Y'ORVH^ +M'I^-0VV/_.4O]2,O]ZMF7F=K'?WO1SG7[@,O(J'W[[7B9Y6V^V +MD:46:;6'S"WEVHEZ?5R+E-N3\7UV+*[Q3/W^?\?_NVWN')2&GI^V[E#Y] +MJ_5.\5OI!B;BSULO.>Q4UQ,5[$\CN#GTNY'5/3#T@,!NAWZ;P/%R8WJ+]RP1XX_] +MIS:Z/=/91?.]3B\RLZI.?I9:A1??_O>"_]MY7MHA_*#<^D2 +MFQPVWV!IG'P'<_UC,!>,A";5,L=[T>B7RUVJ^7LZ_DDNOZ]VA5GD2K.?&T]/O +MFJE$*JU\L;8JGVK;3K<:[GY&E[90WI]G1P1O)*J5JK= +MV[QD.V[D8RN!S4)@K?KZ)S_38.C:*\1WF>UC4]KU#)'OUTMCEWOO3IG]M'PO +M56L=5W/M&YL4.Y?)]A?PG"'JUODL'Z$&O-O,1881TN?BXO/8ETL +MU2?Y6V#\E\O.!^-W>)@K#=H;%NZ\VOC>B\?:>.+B+"Y6H>C\AJ4/3*\:C77] +M68^OY[5V8::V_]_)=&#E^&Q>D_]%Z#JX3-H/ _AC/N[[5TZ+]7B?YQ +M=!D$V_=F/S*/?%ZKS'V=#,P]"NW1I12N3&^Q9.FRV&=R^_%OE2G]^XMDY6J8 +M#$W'U=]U]0QGEL/&]C0]G>[]YE2=, X:3:6CV>ID7UH44M?D,;E?/-KE;[!3 +M?[8"1_V[7[M<]Q.]PGW<.$5KW4^WO-U.CJW"N5*]W +M2L-39'S/S^*#^&%:;.W%P^W/KE=^?!>A^KY[BC[?P79OGYCTPRC)QN<^7"[B +MO7$MN"AZ_N/Z_GYX%;^AR3'?':]V2BOA>1@$-Z%'N3;^OZ?587@?CJ6GP +MVRA\AY7JM>ZC<-WZ$O=+#Q\&Q]?0$@%ZJ%6?R6"U\_R\AR/_BV\Y/ZLMB+S1JU1:!283$8"AZ=A_'%KU&O)\GQ9RIRGPT=B +MOCF];[=%^9RXM6>9=7#ZROYFH^X^\UXK@LV.3[G(\KWP@/S>[@[M\G$I-O_3 +MW:#3.M;V]?LWE,QN$OOJ<=-Z5$N[8[02;_6'WY5"T[/QX78 +M+7EN3S[Y.W ]:9S.]4GNLK6G'"]BJ9T&EVKN[+I][O6VOE>[_0X#W*W9N[[_4PF[H]HYG;O%A> +MGDZG\*GNQ%Q.XXG>8#<2M1QFLEUBXL!?^G\-%@Z;8/ 1_ 6#VV4G,OPL9\%C +M+3$)!O^K_2 8?!G\%J2?]'N3.3\.F_/CFDG_M^WU?_L+X]/?G^UF4UJ_^YON +MNQB=Y"O)3C$1#_W*AV(MLXO-SF;A;[2LN>;;I=9U_XG,2MGW +M^I"+O%[;]&76;.;.Z5.J-TG.\M?]]SV<9.:S>:R6#"WBQ4NNG"^'Y].QU%Z\ +MS)N!N4,]\MH'?N>=S&X_/+UU_.%_<7L]97?G9[OVZV9/TWES=FHDIN7D>MO: +M/9+U:=3]?;W'OIM7WG0H"%W6]@KWV-A8O)<&I2S(:B +MQ6DNOAY4C]/^,!6<@2I;I6XN.:^K1[/Q=V(?V!V_1K%)*[5M1Z>K"U:T/4MJ +M%5O+26+UGZV+!;W[G%@$WZU'.K^XA4>IZ-XSNUXDPZ]T(W+-EQFII]WSJKZL +M7E_!:G5TR/3OV7FL&OS7IKMP.51>ID*'U/26*KYWX4M[[:WOYTZC>7+=CPT' +MZ7U[NIBE5_'9XOW>]^KI7'ZS/Y4G/-3EW'11765RMV%_]MN7.ZE9[!W2KK/U +M0FDY.VX+I?TUN2M<8J]<87=N+9['\O3'A)P*5T^ISFVZ*,5J11'(R2+!C/W< +MCUY%Y[U:AZ1$1W\WIHG#?KCY!(>'3?K8S-X#SX_!\-F.17^95+[<^*WGY>2M +MO$EU'^G7;5]\#5R<[?IM.:@TOK%PJE9Y=U^Q:7$WG?R\4#.K\2N8[2_ZA?^@ +MK*\%=,\7G<2;[52FEBWM[K%Q^+G3+P;#E\RV +M]>]MS^7RH/XM=:Y1E?O3&*?WSR>ZW=PW-J'5L>X;;Z\2[2JOW%\'?B_ +M?WK;3714:!]6YP8>_+!<7P6^?-B'9JHR6O_BE^!S>:_G:JGIZOQ+R[WO6KIY +MZS;NQ71N7YA"899/_53],ID$MBZ[0BF?:'P/R6@NMPOE=[?0?80FKT6:F].D +MTY*/]V?-UKE6JR3;_7[B4@WV$NW1^1O<'EO5[OO?;6RZLV/9SU=J[KP65@;U?.GY[! +MW?17G'9FG49\\,ZDBO'XJR"1'G_^BY5??K^L)(OG4"4U#OZ+L]PBG(K?O[WV +MOIRL?#?5(?7>CF3&W#D/+_?[.73(OQ4Q3^-Q +ML'^KQ*9TZ,' 3>=Z#)R55YO6]/&N=QJYQS!5V)U^1?VVFB[<5G 0_[U+P$IAY[\NW0>P>_TR.EWM2[NWF8YO: +M\3\*ID^M=V5[O;0BU75TWFYUS^EK4B5>:&33F>@_7JY7PO-3^S@K+.M5UF ] +M:$.=V[1^Z\*J7OREQZ>T++.<6_]#__/P,/S'=J/ ZW5>^%1_./X70W"RK2XC +MG<#5^UH:G^6(U[=8/G&X5+[;W'N0VI3WNV!V/WX4F8O>Z?J95-OKZN(32BXVV=>[/*D5$L]JY=?]/U^# +M2/R\K/ZWJ\-X?;Z\FN=&;W3Z#B:7>5(^GIDU,K'9>K<-7+:WK_#XEKG5WME? +MM=3+S&:7[V82;95#N<RI7B&W +M"U>GM\BV\^DTGZUX>M']CI_ZT/W&K)P+EI?9U>"]KP5./Y5$H[$(JT?_=PKU +M_YS/MO?!;GRXF1SGY>(I7MVL"\77N7S;NM$7M7!O7W\.@M%CN7.([WO7U'M[ +MEJ6>M=[CO/'?#,Q/.X="-C5?]+KA^,_L350OA^FB'XV7P]O_+U$_/4/KZWN0 +MC-ZR]=+J/MY(0IZJCTIF&S@ZGJ[%:G)_3&^!S/]6AN,W/R#W>IX#85FJYBH^CAW?("_37?]]]AL?ZMMXG. +M?7G8#Z[9WW [I'_'5O%' +MIU@H/AN/9.<;>WT&B*\\QM-)MAN>_7N5[7S2_JQ>TT;@,_%"NU"M?:L[AZ3T*"[!G;/__UWBC_*N +MK^M.;RKC?C&=ZAXOX^W_,'48]*_OT:NU/NX7V5#IV;B&6O'6L7Z/ +M;IZU]2AQ.G37IU!X&"GGT^6&>O3:ZNP;N^(MOP^LKI*)9R_6R:5WR4ES,0O_ +M7^?S8'I-?E:W2^A]R+4R]]TOFSI'PKUTM/7ON,H;LW=Q.'GF5[GC<9LN_G_K +M9V?]BMP'X7[Z6KI&AJWI+_:J1?*G1[:S:L7#P5&_DXH^^A_]-A'/+":+3WU\ +M'P2O]L90M+R]'%>9TV#^2:_>[]3J]?L%2\? P:;3VFWJW79HW;H_FK=]1"%9 +M^>J;3PT^R._GLER'_ZO[K3A[5/.;^.E8S)R+_1R:OO*+]?:#]NL1N'N_SO'8 +M?E\?#BW%VW>X?#I]$_]Q>Q)K_,J3P.NDT1EU,MG[)[+_]L^IPS7SGF5:A\RG +M-&M4.M7V-!9YG4OCH]P;&>0+JW%XU W<1G/[0;R?#]LI#_7FOCI)/S;3V K# +M/RFLIJE7<;=N-*^K6^@N4:DO&_E(.E7) +MU0:34?T!CWWBE0H-YL'0Y3GKU7S+]:?Z:]_5X&M,7+@KGTBK:BF5K +MH\?@A0G_OFV"I5E^NKWCDZ\GBT&D>O@]>K#WX?A*#K.;5'(8W.=WI[KI.,V- +MY_.IE#@RZORVBW#B]FG6,XM1:5,KEPJUWVM1S;8WNWXSG:V4^I7 __F^B&R/ +M^\=E?17G]IN%7CQXGKV*]L;6^_Z(G$_3>"S^_\2CJ4P[MNO$YJ'7+]/OU@OS +MW+!__!1KDWAP6VI=S.]T;GAOG8J5W'@4BK^^M5DK/9_\S__/*-D[G9NI>_07 +M'$0W[5WU\YH\][' M_B^VZW*VYJ#/1LISP+S\^/NLKET9N%=9U;L=5[13:WV +M'PX#<]'WX'A_KL/'P.8U-FH? G/C^CIQ^H07?=O:7H^_TU@4DG'V& +MBW=B.'N\AMB^6^C@]!CK/6OUV68\290+N?_R4KQ79X'KA@GLHK\:3;>50B3_ +M*W7FT\W)>I\MJN-XOIAO]\:1;//7^90KPN'[O[PZK\R*J\VF-HB6;:A#Q6TK +M5LS6-[E-[YE_MU;[;ZZ>/N^RLV [=HOMDY%@N[#]IZKS;.0^VT8SC_TH5CN% +MRON\6?B]3=^WM?ESDSO<4MMZ\SE,E$.;WW-;F@V'Z6'M4_]$<\G'+G;I#?^' +M1K?_K"V"C<+EO]G)TJ_CSFJ4_L22Q>9Y-1HWTO_X9_9N1/;#V/1\')T+OVFB +M<U +MJA>ZUV@C.0M.K['3>OF]5X?=6JR47U_.O]/RIW9/,U48\->^?_F]\KO:]EQ- +M%5ZOQK(4B??NP]7ROAGEBH_M[3#*EY/U?S;6[.0?_=JBDYX+(RU>QMMAK/I_ +M?=>9UZPZ^M5G[6HV.LH<*IER/%;8=9[Q4'Q5+J;HL!/K2[][F+26K_5RHE6^ +MYS?5GRWF,# [VT>6C<=F]/\^ZX5B/%HO5BZ;6R$]N!5KH)B;%X8MQZ?5\J'4.V_J)/E>M6)5OB$(4X'YM[O6[O]JBP&_]XW_Z/1;+'12M6IQ8^YKE@[V'B +MKA=;WW_DM?RL70N7O=LL?=OUHH/=]?AK36;!8"6Q64?/G.S\1[<4Z^K[O%Y=B+9S]1C/PN>EJO/CML_.B[LRH/UM_C8U5K^K7E +MYZD!/AX+H^7I/V@G![O_X+5N5;:3S7H;ZY_FV5^_4:G:>+N9;7E>/:U*L4$X +M_/IT0N;&QWZ\@SB<5._=OQ//C_'KM>[=8/[N[_>:*4 +M,FJ[J]FBO1_U T_%:BQ4+>Q=V!:D_#S^FVJS/DMA>RK[[?1;T'T?VBE3N7OT[UHO?^IJKA\:#4BV1R +M@:'3M--ZY-Z9Z'EIV0<>F[GM*?5.#WKK\=RM'#M-"]GF=C,/YX*59#H?J62/ +MQ^\YFVIW(\5#+?UZY!Z'V_=;>D@'KA_I2Z0_R#\KN]KF<6Q7QW5=TL;A%V]/ +M9O]8.ON[MKNUX7'R>1<#*\%_>5ALUKK)<-*WN(R?DHGDN/F/WXO!8++P2X4: +M@_$T']]&XO7T\9-.)&R%RU'JX@Z;OMV+U^VH0S2P#0^"M?.P7:PK)4>20 +MFRT+X=+H$/ZW+H_.\],*KZ^Y:65TVC1[*LG3ZWH)[.\GO4;@9CRM%H^W]CI? +MO.\B?2//[2WR/CG?']G >7AV+NV=S^XZ74K'4+7"6O$0ZW?=K +M?(\&\]=IMNT,L%':C_KM_/+3+#?'"UG5Z_ZE_W% +MY^E-_AJ7X_:VSW]U.9L,AK?H>%\=1Z[9ZZ&9SL0FF5XL?)_5T,GI-5MI&)#):I +MT>AQS*TGV]Z_T+=6UEOI;F)Y"L7R<4WH7V,=N-_/YK?2-+N8!^Y_AW-VE(H\ +M7H](H;+Y7.JS5R:_2D^W\TQH$7WVTM-K:5E-WC,1J\!M?#WZ1 _+^V,K"Y7T2Z\<.W7K_G7,B/HVPI[^9=+&[U2[ 3V?3?XV0RL5;!S205W/]S +M:;+==^/Y?#]3ZO4;$2Q_X/R2OERSB]]C$Q_\.[O!/?-HM6O%_#@?3UQBT,0N +MSG5F,TY$:]%5[)/+I[O+7JJS/Q0.T>_A4PVOWY57\W?O"_7I\'523^_OX]/L +M\/Q6]C]+K^L<*R43_4&I&@F5DO7P,'Q*YLO-XN0P_7U+O?(Y5*LT+Z?T)'5\ +M/-[ORW$W'Z;*F5U@M!N5(OQV-M'P[E4*7%SOPVNZM2JM4_=.J)$UB3YRS>*W +M6![WI_UZ,;VJW]/S5V&YOQ8JMVB4JW?>A]?UKQKK+7ZO>ZO9Z)42Q]2N>LXW +MPK_%.S#62#U#I_/L>YC-5J&G!60XW0[.^LG3MMV6YZ_*G6#J6/PO'XU$^/#8 +M[]KGY/^WJPU[Z?@YNVL&3KNOQ+GX/';?X5UYG"O5.^O*,'!_+)D;]HJ+X7Q: +M.I^[S_)IO3G&TZOL-;P+E9.%2;HYF=8"4^=GJC:/WQ;AR["[N%PWV7=T=9E5 +M'GK_?ILYO_Z/>.9RK-O3I_5V9E^++*O#Z^<5'\YJZ]ZIEMY^.^%SJWF]YP_9 +MWD ',?#[W4]%*?'HX]OSV4L,_JEI]_0>G8;A;W3U6O)X3J\;\>5QV0Z= +MA_%N(YKKE.O-_VF_:>Q72)BEP&AZ7'Z/E?V/ZC+TV9_G_T)R;C.8 +M+FJI1Z<;[TQCB_DXE*JT;^E)NE^KG%+Q?CU=F/Y:H[6KO/-OP$IKX?CC,-NG +M?[GO(%U?M)J!Q7YT6AA7VZWE*%D<2>*.PO?G\CW;?V.Q]_:;T31*HQ:[V]*W +M&IN%B^6$%.QM=^XV*L?0_K"-M8^KW^$:R3PJ]\&MT[Y_XM]R.'TM#,;Y>_;? +MSRHD\XE'Z'D)=F_%9QL&]E&[EV5@ZZ +MOAM.5NOE_E7]'WNY^Q/576M65A6BR5-N%) +M021_3,:RKV.UUPOL3F.%R"8VN#_^Y]NLX'V>E\5C*+=^%J[C^ZGXW:ZVU7HF +M[2 O);JM4# ^.U1*I>*$? +MS\6SBV]@-Y'<99;%33L6N*PW0J%&YA(+SH=TZ[QTG&?'Q6$^_?@F-I;]L-I/ +MC!.G8W!5*\R7YWLO4YE>$O'X_L&8WYTVV>$I-\ZD%K7^-3P_)M?Q=_Y]+G[6 +MR\Y()'N.%*JQV[S3F107M]UFTZQ/Z_-T*5X8!YO=;#H<6QY6^4^OE%]NV\EQ +M*I*MC)_57S=6%^3J*#,,]E*WGMB/0_/+;)GL%L*/VN8T+@PCV>0XW4F\3O/C +M"[7_\IZM+K>C=Z23_ 8?]7SK]:E=FI-+UU7>FL6K@9'5J-[N +M'\:)Y].GRKJ\NYT@H'#\$+YU-+7:NWD1A +M3J[)Z&D3BKP6Q^,@>CPE_[W0^+O,'ZOWP,MYF;O=7[%Z6Y'=RO6/R=8L'%AX +M];O]25B@_;R:T_IU_Q!,!G?-R6JW3JWGWUD[EPO''O?QI7Z>;9*YR6>;2?CG?A[^%&JU +M43Y^CH7RA_E[,,S,-\? 3^@8>5V]JMG-])\-CR>;9FNQO,XBZ7ZTV:BGULEK +MO5]?W->[7Y0 \]?ZM>K/0W34>:56K7GQ?+^G+?OH=#L2@8'9A*"UF0]7 +M.Z%M)S0,# ]S4^$_,# R"_5D<0.7V^&A/6U$=FR\W=/!8G_G)\OFBP23M9NBV8^\+Q;D>7]C4QK%1+N=IE?AK>ML?.*O)85,/1Z>BZ +MR+\C_]-D]MNMA]-59ASKRL?UZ6/HV&HTOY<$OO6(O+O +M=^^1S^*ZV5Y[O\]J$3S"CEVUV.S$W[J[OU*XX[Y0#=X==.!M[__.M[R57 +MX:QK]6PSF8@>QZ5D++_:O)K]7#)X>'>B[]&Y>NRF[?_:>Y\)Y1.IY2TU"&4C +MH7)HURDGHJ7CK[?]#;+S;:2WJ]*T TC2V^\?KKT+_6)Y6%@NO!:8/_QR]U!KK:RS4:] +MSU3VF OT-(\#:\7MO5>[E"NQY>^UK&:NA>S8';6]V79ZL]ND:&0_ME?_P6][ +M/1PZH>!=HU^GLYEEX;8K3ONGPW=T2(^'QV&\7GI%2X&/W3GP\TV^X]'RX?GK +MYNZC=R>TN>_"N4VCM6[(O>_U<'U-Q(?/5[D4_?\G]];B\QVE$Z/=HUR=QMOO +MX%+&.KTT2_'KNKT:7E[UWK0W&!Z"-7?B:RCU'>5"V\B\E%SGA[%PZYX[)5K+ +M0.I[\ACVNN5\OSZ_UK/]R7CXV:8#U]GV*+4H+A(7[?HY650?@==Q=10=S::I +MWF%;/W4FX5"_5!V70JG6,!@/Q\^_:]>GSD[S+S,%(,C(7. +MM5:_*N[MCXN1V_:7/7ME0_GULD0<+M1;K_5OTSC,PM59.W^9[O/M_CR5^/@) +MB\GH<)9,+GZ'UJ3W/U\KY7VM.(J'LJ%WMG1N3_.#UGL[JS^:Y53TF"X\OL,M +MH;96FSX2ROYC[AQ\HNV%QKJPS84/J4@P>X[> I.?W'N_R6P7@:/9Y!_^!K.A +MT+8XWF["N?ME.6PFIL.O;W$13Q_JSWOCMPC;\?,S4("TE+A<7KUC +M_K?ZE<>U>.H. +MZ?0].D]^)MW2H['\GCZS=F56J*R"W]+Z/>BE\[GH-%PY/YK?[JN2>K93S5ZC +M%EL]9MG!T @Y&(O_!N]$.M$^9/77<^HX#EUCN,KC<$/!;9;ZD<.]&'Z_3N7= +MYY,XGUN#R(9OW7!1.J8'J=USWDS%*KM6[M8,['2S[>6A>PAN.[%\]OL,"ETG_YX1 +M?K6*URKA]>,V#T57_5U[LCL$8YER[3@J'K/CYJ^:X)#>?LGQ['Z;;7^5U3Z? +M70;FA9%7\TDDM,YWYO/9)5>[9VO/P$XO<)@)MJJ92'-XCSRWF?OP$&V_]_G1 +M8#Z_-!K5^GGR7\:'XN%<,/S(OR[AT'PP.C>7Y_YAEAB."Y'%J9)KNF>KI7Z] +M7.S/BOMQ\?N[[I.S;ZLTW$;R_:D/XG9Q3X4[B4NCFS@,HOWS_OW/-H+#^261 +M7LZ*P4+P<'G^+MUF=GU[M3>E>VJ;J;73_]O#$=_>O)T/=?*=DVGN++"=2Q\K +ML\1X6:TESYU4+;I\AG>YPW>Z1/(6YY508#\__"U^LU(HJ)-/Y2^GY+3\>XU> +MM=IW<2HFEK' 7N5?WPZBBM%A8]4I9IJG=?A;OBQ^R_6Y4PK7[;FYW5.[;NPG +MP_(P\\DKN9O]XN(4#CWZP68TW<'#K ^9;ZVW"R7NPN +MOOEWP,NW8VVU_$YFW=URV-]>CY-+*(Q+K^W^\?,>=?W'OY?*K'J^JO2'YWJ\ +M#FY/OW3U/WVM)$GCY_GFE\T.FLGY^I%B= +MT2?4'MPCN]STFTN:![R]OP\;^7 +MT_51H1$,38OO=G-=6-YOKV?@-,-??CG8?W,I?GI5A"!^5-^!L^*R_8RDCOO? +M\1!Z_-[MWG?S;+=WCV%^.UM<YXSO]AYY^,&1 Z67K7O +M)S2\%2O!1?3VJ-2ZV4OJ=>XGN]]4J_MY#IK%3W?6VLWWT>;J6XP.7_76+5;P +M/J^OQV5U::0JB^+V<;L7CIW:9[T>3)?S\NI0S-3WWTMSOE<\-5; +MAIRR[7/YUASF;_E&5Q)=[@WF$YOO==GW;_J=/T^2K-.LM48C:(7Q:9 +M<2T]'"]O@6<5];_[_90GJ\:X%?@,A3ZK_V+76*ZC$MB5WC,^2SS@8<>G;K#0 +MGR@1-V+I;3?^ZUQ;FW]G/DNL/QOG^E.8QX;3=G%\[WW:UY(57R?_DZ6OAI-? +ML=*J_,N?6NT<2TS+ST&DT-K5FO\Y!W%@9%DN;]KUV?!8.NZ_JUK@*WP*S_7, +ML]\W==VT"NUR-%9[9Q^/U_U>K7]_\U[_W5MFHN5!9;\]1F:O83;\3?^OP<)A +M$PP^@K_@5V9>;B+#\ZYWB28>[6 PV)T?@L$GQ!_\I-^;S/EQV)P?UTSZOVVO +M_]M?^+Q?G[^[SQP8.;Z1>]\@J*ER\I4=[0)7V,[][O?[BTCS\MQ,\EI^2EP3[%6]57(E0)G]T5RL;W] +MM[71K!)\%8^-S'Q5K$27UW1QOHXOP_7A^*FDUE=7IX'9'U$^5AJTVYO5V$-RO\+!T+GD?SZ-S,MJJ +M50ZJY,W,:-U9%D[)8CV<'7=3L5Q8/#]MQL?3R66PK]=.P7GRN[^NON7L:RK0 +MCBNA)9DYE6^%\K/>N[-\?U:A3'*>;D[GTT>J6OR>7JM4X.H]ZY^7X_W&Q5<[-(K= +MB^?HM-'*5U9)2DII3,_L]#K.)8K+9"1Z*N:;TW9^N Q\?:^Y=O04>K2WR?6A +MOFA.:J7J?Q*J-):M;>CP7N^7T])#H/UT>IG'#=98;Q^CXV'[VZY>!O%BL]@[ +M+]NKS+SL' +M]@[E?671BYVLZG_S]?SF+[M%.9>?U\;)Z:A:[8<6Q5?W]J]H])7?()]('D^S +M4ZYT_<9+_<3/^I@*[\_A$E+@;B1M8 +M=T[T5+BWKH1&P^']\3G^#_M_,9']-Q>[57P7BE?NU7&FO*TTAPET\OTMA*=, +M3Z/OI /8;O&S;%1*I^0OD9DE*^E1LA(?)>(^;;#=/4U^G+B9<7,>'TT@W8EM +M?%*H',?7>2D>74L'+\? 2F2[*\>2Y6FE7RS>3HWLZUQ=/WOWZ>91/E5?C4*M +M. ]YIO>??Z5=F8[32R+$P%G'C/O+;%['PWAAZN\DONGW(S[+.%'G4J7BJW38 +M7<*]ZRU?BT[?JUS_UGTW'PSLX#8PD\HDG/R?O=&P6%^E-JCG(]Y?Q^,J"]/Y,E%.Y +MZW9WJ8_/T<0AG=@5U_]Y_G,,5VZ7WGD6JQ?FH<&UNJVONLOEJ-"/S*_#U3L[ +M_7K5I>FH.]HO(Y=R9%A(-5*O].BME:[.6I<1>]\/MF[]QFG4[YV/P?PM>6RU +M;]]J+_:^'1]J=_?WS6VJJ>NY5:S-"[/XH=A:Q([]4.B<_@2&.J])+,6+'W@? +MI7/99'ERSAX"KX]YR[QX>_^-)HG"\I0,GI7YV +MGD]$@X=':CD]1'NA4FS1B(\/Q\AD]!YWY>.=>2;*%'_O]N%?\G+?/EN)PZF= +MRV?:O?F8 _8?KU12W5SRU-S>IK^NPGGOEG+QY.[]%2JV_HU*_M#?IF^;;#33 +MKEP_Q?@I,^X^4;@3_7(VV]X_ZYE#Y[A*+9OMU^)<*Q]'IW7^W)"/IR_!2BQY +M753V@V S^/N$XZ7S/5SV_9/5S&,_G7<"*\UY I(^^(:Z6^ED?9:LQ.E,7Y^/T6;5_[VLB>(VV5\7JJ1(L+$/S_B>3.45F_WF[4+[E.K]A +MY1P&OWN] SOA9%9\-I>-@>O<[>&YHX5H8"N6?:;#E>SXND]?+N7U8]0;AR+W +M^/^TZJ?RB>RG\YP] L50SZSU=Q2_.S$+@^@S7+R^Z]M4ITJF?_R1Q*'&L_:( +M[5/YQK=3R3:N_='T<1EM2]J8RT>V##B:CD=E?^383,?_Q>6U.RJUGMEJK5Q( +M9KFS\5UO#%\\7L_SXN(Z^ #B/\K9Q'WRRH5"@=&_P][3KG^]TVESSS3V\48T +M61RD+[G!>]=C[#N;8>Q\_ZX/W=8PL\I,%LE0YGB3J/R;6;9[K.EQ+^5O3\CI>M@'UNE>]K(Y_[O5(B4+^-NZQ7J +M&5CF(_5CK/BKCGZGQ7V9V+33Q=FD&,NVX_WWJ1IKG,*?\?ZQ".V.\]7M/9O^ +M!^_S-[&XE]??H-*:.N2NC\*P%,U_=ZM_=?PICY>;5>,4?&UFI6[N_ N-9\%% +M]?=M#]>K=3I64L9_)VN31<:$LO=;5$/[V_];K!2#UV3P.^[=%I-I^Y8(=Q:Y +MT;:?N :N'I?(NY/;CP(+Q_RQ_U2JX[?X2R=_V/;*B67_T!Q_=U;N3KS?"[]1K\[?F]C?AUJB;#IQ5!FV9^;C>7^:_U[P2'[Y?KT/X +MG.S&I^7"^U]\#@*-U.5R.'PLS)J1X.=7V8SGK>EH6FA%O]-92PAO,I&>7!?[ +MY'&;*,?'ZVNJEOR%)Y?.]S'??,]5M.?H_ +MW>.SX_R9W#9$I-]CXYPX)#ZA3"PT6.02V\?Y=QA9_NNO^XTYG?Z' +MEW\GPF6NN:RO'M'@LWI<*B3[JU,R_HA*";CI75XNZTU']?+;C0K +M!+:7U72X]Q"4?YO%4'JX7 R;RW3@IN@JGP0NUZ=Q?%+J7:/EA;NR5NME_^/_ +MNG5H!%?78_'8+7U&AZCEMO#/C<.'1DYEGETDKW<]^#LO/(_^I +MK6J?X>(Z.TXSJW"VU8T^CEN[OM;8Y9ZQJ?%S3\?^__3Y4)N-V_%RIO6 +MJ/B>&*_=]Z&ZNJ2*TW-@?E/*37[CX90T28Z^*[:BV7_[,\.2SSKTY6&^'065 +M#I?U:#>_]V*-UF/S:3H<&J;64-K4\#+,!J97\5"G-(B7FI32XC47^D/\X=.V +M6SV3./.E6&'1S]UC]O^K]ZEL MO]\[^4[<0YE)_MMSG6XC4D_/CN?>>L6*_9L\C]_>Y>1.W#X>VJ'P)XH./?I&0XOI +M]VC$CDW.N4:K-=Y_HX=?Y!>9IJ//[6 :7U1;[UDM]_N/9V5Q[OBUR+-Y6XW3 +MLF&@74!B,J=CFTRX-#Q?1^=H(S;\CAJ3=Y3&L7+^KG;Y9G;;_K_[>G_RFZD$ +M7O/C[?J;6.]/^4)ZL-X>6O%%MOY-/P_U0[B^W]Z279!PI)-)'?_S]^99BP\' +MZ;-._AQOSN*9RFM0[@4_W<8X^4D>;GLUU'[G&APL+K?A)*]"/7E?!=%/Z]1C +M$IZGX\MU=WPP3*ZNGUZYZ@_4I7KH/UO5%:54[]6;]6J2CD8WS=NV7.XTAHEG)_J=;,+]9>\4_N[OG^$_M;Z?:LO6:S_)_[/? +MB&?HC,7[Z[3OW;V$GH41^M!,7#56,9; +MR?TCMH@M)O?"Z]Z/5!/3;=%UCHT_[5*T-CNFNN],IS4;A=K1^6N5ON[*_>_G +MG!DT.MM8\SJ/WK:9WG\:N[=*F<-T5$B&1LY[?5!OCI_!XKOS/5<[6WO\1&K5 +MW=]NP7-GFRTMKYM*I!MIS/?9X AE7D?^QV@NGDC?6Q\_8?]V#[U[P_G32_GH +M)6ZQ3>,]:G_2T5ZQWZCN2H?Q*O"_.;5CD]LQW*KL.Y/%8@.!6!H_7.?2]E:M +MI[NG_34R;W^?K<#3>?:5_;E%MQ@]='[!P'TIM5S$8[?>(UBMMGY/&6'R$2U=[__:H#Q= +M/0(?UV]KGJHW,N5_*77:;33Z>C8Z&\4KG66EL5\=0HGS-51_O5O#S_5CQ_G? +M!8OW8JPRNN5"N_.X*)&?]>^=3RY3\\5[S9TKG=YE5?Q_O>[4;95=C:NW5&?8 +MC<_ZX>4L^L^'IZ53K96[Y//+ROH>'DW;H?_H'BR+]4J;1*&[/&4QMZ;[O +MI=JE3V!I<>F&TLE/.YK<7ZN9P'!\]OBWFY%CL%9-[JO?S[SW[:L9.]7HI7&? +M]_ZQV39RNVWRW>KT>XL=LO7=/W,?EY_59_%SK+_*G6,F?_XU,K^SE3^[:ZP" +MS<+M2^9S'7?KT\7Z>%PH*PO9>O?R#%S]3UZ/Y]J]_FZ'/_&1I3B>2&WR006R@3&2WG>>)TNQU?@LG-H +M;E+M6G[A;9SLEKU/IOUZ.J;7U5ZAO+TUEKGG/E^=+$?#W3^6FX4B@\:_M!@5 +M&[]S=UK,W[:W_#O6O93"W=HIOCN4&V-+\;U0_ZR*XW@TT?[,?XO%XG\L!5^_ +M2V@XRB'@1\O[YGW:"I:ODXPKE5EQWHP^ZPCU +M\+1Z9*N9^_JQW5EF=4HG_Z5+:]D.;8.QW_OT>B>,KOL]:!9NOTG'V +MF6QNO<4IM>G*4 9^LR6BX.K+U,:BN4-['#@?V8J;H +MVW4D5PN2:D]-OHUOI%M9G6=YF;)P3FQ?&;NA6G: +M 7]HWM\N@=M";)+9]-DQO^%5[UA*!-.KSV_=Z@QE9(O;>K;8" RMI?=U-_!W +M:7?VM^/QZO6=CAI50,Y"7./V3XXZDUKCV#[5/[$C_?; +M_'1)=Q<&UL,H.EOO9ZW8?S-\'TJ=0O54E9SW]?:Y-[T5UIW*-IC-S8;APB66 +MJ-&T-AO<=HW7KK7^]1_7XGEF%8P-_KU]8Y0?E"/1462Z+>\F +ME^%S4W_O"I5$N[/[3$;EY.96&VQELWG%X/[7":^.XO"SD+[5N(1N1U& +M]VY0*]_]RVMM6OJ5CZM7JYA>+Z78_[[[[D7IKN:E&A^G Q.7=T.CK +MQ6JI..R5@[5DISH8ESNMR>GP3Q^?Y4KXV%LECJOP,M$XW\C/#L%2=G1&BZ>/QT$LM.U$QY-LOUR: +M%&KGR'A^W$5V\]=TM90D\^VV[UZ;P-[;12*9-^ ?3S8RYCBYJ[U76LYWL>/L?NV/$SOI]5B<9[\O0:# +M9>"G&RM$[I7ZHM5+!=>OZ#FSGC21*4/99+U6$RKV,['G[53-)-ZKN!-R:U_M +M_A.Y]C7V[Y]'N=MT4]SE?YM-Y%EX+(.[D#;L(=2X+D/)K8QT/O749_>^SD^U3Z05?C]SB5EI^,A4=FJ& +M\>JP>>]LJXW$IIGI#ZLXD$#1U;'S_K7?LW(N$3C/;W?';.>5ZY7?@9-@HI@( +M3L654P_R&@AN*/!434W?\?$]5S +M.0C/-H?[I%OXM$;E93,:FY\VQT5()!N?O>[+S.!UJZW.L\DSNUD4[J]1KG9* +MA)*5;#@PU.^]=K.1^%M/II/A4*2T70QE2 ,/L[_S_MWVV[=VO!"JA)>3YF%< +MN( 35Z;)T[-\R)YGD>=[%@N=V-R3_R.6.]_J_PFP>AG7_97]H5:]<(V4VF3] +M;I7XY?Z9TO4W.]T*ZA#9%\N-U_E2?<53BV_U$WHF,YZ2K5VD +MO8CNH]%9I[VMS)[E7*4WRGY6K?EI>XY/]).34>E<295.N\.MP_<>[[W[]QM_ +M1C,K$\I=:[B=!+;JV6T_OTHMSHU@+3#[#..(1[%1=1D8OL:ZG]HAU,N//I]B +MNS7M-ZO7?& Z&^C$+'Q#Z5)D7K^&8Y-&\E?[7R[GDRCJ+IOM15KM;+J03ZW" +MW7EXV'S_EZ_PN7S*'[+M,W-27UAR^N/E7OBUSOYCD<GTLC>"C922\^PS4JFN2NM\.O.L3)L=^W\1"\>*[>SRT;B>:[7_/'@_IRJ3 +MY+O=^(\.U6OEO6I-N\EQ_I]>Y8"U]7>OU2@O1Y%H;&'_7^K+[."5*;26I=UP +M?$Q>T_=CM[Q>GF*A:?#[C*?NA]#WN=T_!JG_,M%-?IZ=W.,;_5_J6[$SDMFM +M^Z'1+3-=]F:C2:83+J_NR>QGGEJE*O%8_ #X#X*'33M;V3W:U=K^/TI>&TNM +MOF@Z!H9>U5II,7D'W*)\*DPS*73W^,UM>IE?O%XZU/.F9O?UOB/ +M3F;U&%QBK]_.@_PPF7YS_<9A\QK6HZ']9#*K7D[;8(.3GE^6QO]]=9I:I5F( +M1^=AX7+][=*C=N1=;^WV/>^SNWLTYO%VZI@9YFN?13X[[S9CG?+_FBR7KXER +M>%<._[_YV9O2V!M$"_MX99GK73^WXN2A72=G^74CG'W??Z5%M;=K+FK#\7Q\ +MG=5_ETK_4_D$;NN->O:Y"]OP0[W_,M7[GLOEV>PP&615QGGWL/HG/Z/Q?3#_ +MAWZ+;[Q2?$PWL_LT&&]NLH?VI_(N)1>).#3Y[+3\O^K'T>H?VS\B+L[(/#=^ +M90^S7K@W:Q7+_^[TQ^OUY@>FHX_U,_=_EJ*77>'V_N[J__HMN^Z%Q\E_+'G_ +MQ821NY/!=#N=!?[[H?+.N$Z4GI=M)!&:)[*M?B3YS=OO]\JG$T';^50VGT>2PCZ=9N]6@41K75(=([W5?!Z#JV;0QG_\\^$CA/ +ME2;/6ZC>B&Z_L_&UM-]W&SF=_&JTZ+0RF\V\W!N\QM%*YFZZMM;]Z8^]+C4B +MU?/L4X^VJNM6L-%L-&^QZ_P5OS=R0Q-\U_DU_O66GUGN=5NO&J](8.O^+"]. +MX4BXOGMM7@N@?]Y?9$>+6GX_CN83D<#'++0E>>;>[)\+-=951_0L&YX7D )Q=[RT7NW5RT^RNZ\OR)W-[ +*WSH2)3SP8_S\B +MN5JR=>X_!H_W[7L;[>:K+CGJH-E.CZ_U1_DQW7]GVVKYU&@_WJ]HM'$M9/9+ +MR[XY_B9O^\:AK(^\^B;SW7RLFWD=SHMP9QR8VP3?Q9]/NMY>K7.#=.]$0IT: +M!"8>\Y&,['KWN+T^[4FH7X)(I]*W?E_JQDVSTLOGB>/HZ-@(7A*\]+V.ED]2K5[]/S. +M5%OI1"Y\2WGZXXUT-IF/+D;AY<$N'DI>(^5%8AF;%;:KHPSE-3/<[6KA8F:Q +M;<42[=FA?)XN'OUZ-5;-9,+I:F]23+9SSZJTJGX/I7AFM]CLWH_K(YL/6B.NTH-?KG<9G6OC8C2='Y7, +M[W1LF"O%?Y_=YQQ8V^SRBTG@-?6<3RJ71.HV?=RCJ?9FW"_D-\_Q]7YIGWZ) +M^"B6*0Y"SZI6>3GIG3.YWG'2?ZU"R5@SJE#XES^__ +M/A7IYI?QQ;B[_1P_V[Z>23D3P\+\N\BLQXM%957\"!4'U7'ZWRQ'LH]U\-DZK8^76K"8 +M?GUGRU#L.#@$OKK)[:&6J?;?[<+YW3_4E]W2=]Y=Y(61CH.Y57YYCTYO_\$A +M6MTLUXUR=YC=U*^E:6$WS32*T>'Z>9H-3\=,D1 Q4T[4"_]?[OP(N\Z9=Z4> +M.5:^\_H@,-0HU8O%=^[TZGX>@^6KLYF'(I4V][N_'[.E]+FTJ7W#YWFI%PL, +M)](R\@YI?EH/UX.Q:2Y8CVZ2I\?ZX^*M=N;;[[]=_KDY[_7 :.A7J5:7^4LZA*2,3_^KVO7/UO9TEI_OL/AMMJSH'H]>R\Y^54Y_F=#9SI?<.59+TJ;GNWL_W].E4 +M.,T[C]WG_Q[\VI=\)E0.1:.AI/+XZHAD)Z%/X.X_K7^Z@\EUE"P'%E/%Q:8^ +M#/87A?ZGN+EF#J'(X14N]-[58V)V;IT3O?'Y]0C7M.MZJA;Z?3>U56RU_T6^ +MP]Z*@?U#(U?-1QJYPB0UK 9_V$RQ,YK9?-^' +M>NQU+?QRJ^2_<,SL?[M]<-R\(8 6XH-^?1@/4J0;M] \'UD,VL]PM+%N%^YB +M9^CGOICP<;*JGA(&SFB+QEJ?! +MW"V5F92<"0-7Z]&DDLB]+^O<]],>S9I!+K3ASC$[.?QBW73TG1@G]YU9JLU# +MS49]. ^"N5:PLG[D-,D'ERTWNQG>%\V*L4WG5+YO'J7<;I+F:J_)^7"<312[ +MY7E\'8[N'LU)K_*(K_N52[MDFP^G1YWC8[W<+JOUVGW7G/;[T_+AM]^%K9#_ +MXKCA5^?1.3^+Q\WMW#OUFXE*Y'XO1Q_]IU\['[[?D[6T>#7,33B]V="VF>@= +M/M=#:Y=?;J;K_3%3BG_2E^O\.I[]_@^B]G&-1]/9;"O@Y?=Z$DW%*[M*II_K +MSU/%\8A-/VIEMYON\5T*7;/;2NBXK4VWCTH^,!N)Q6.!(33,[+V2E@X>G]UJ +M['7K=1+WQ';>PD9N_/>?Z7G_G*Y'U?>J:7F*26^+3KT\V3=?^?)N_IVT6XM2 +MUQ1W^5O,.]7TM)O?%#_Y4*_GS^&WG1]N!\%UNE;(///]WVN6>NS4*7^%=N4V3'V/M7MF +M],H^>X/Y[;@?=H/K=6'2NCFF*[?[KI*JCP:UW>':K8S[/4;TVBO:R17:&L9J +MMGVZ9_.)7J/3_V4!K<%5L)R6M] N +MJL%ZJSH:-T31OY77--,:-*>5^!L3V96?.'2J>?VVVME?)X=/O=AL!E^GSV%1 +MZFR.V6"SF0KS'FK7E:Y$^];+!FXIU9CH6;X7X.GG- +M[E[18^)T@C"_]O_\L+L>@[CWRQ":/0KB_L27PT$Y,^A$_^E\+]\)_5-7'_=S +M>0E_#^U1[Q[XGU^:FUZG6\HG"H5\_'\]WN>YV"+W=L&MGN.1]FW_:^9ZX\5\ +M>RZW0GKF6RP3^&^$^X?I]UN;ES[E_^ :WVS?AT^NLZZUCD>Q>&9PV+Y3[?&E +M]B[%#MWK>-JI_'X+L;,SF#1N[<0L"0B=J>2FXTDTTBV.#X7LM!AXFW:*@V8\ +M/4,$?WR^W77H'.D."\EGHWN/QRW[=?5:OW2/YV;I^;@'I]UJ.5O>_8^U2&.Z +M9\/-["Z!CUQYLNY^#\/_^=5NG!^YT1K%.-Z?'<#^DN5G8Q$\Y;O#^KH7"B4C +M\6AM^6$F7R2[XT^S\OM\%JO!K'-PPOXM?H7DH1$?5+LQU_G3J*_GB77U-_YF +M=]__Z5;+=9/9\MFI'O)!\.CRGA8_@O+-Z5(;9"-E6K1Y#+JO-?2 +MU='Z$4^%(L]MJ$O"3:^TS)/X?I:,CF_]]3F[>33KK\!L]O=%[(^U_3N8'QZ/ +M][=;=)D9!U:SU6N['4I]6]MZ*YU[1Z>;2V;V3[YOOT5A\#Y.8L'R>%>H759] +M9.%@4HL^C]/NQ;>8GO^J[\-@4NE'D[7/:UJ[;V.95J'>NP2V@N/(:;G>50.W +M^U7TT?TV]?=(NFXN][HK;K_0N13CE9&HQJM?._]_IO_O,; +M+63@O+*[#W+)S#25\R7=UW^AT^JVSP7?X:R6-GRZW>N=U:)V:\=:B\8GM_V_ +M%H/%ZGF9%>*3YRMVS:!(%_-J]! ZE6;3]SDY6R4"X^GJVS 97[0@V9M!]7L= +M=4O'PJYQ+SQ3T5EY\[H\(]-C(MM^_YO7=?E4FJXRY\PFU^K3L:_?"57>U7RQ5'M'KZ$6H=*,Q(* +MO0?VYDST<]G77_GN_!Q+?[Z1VFQVC@Q+@:G <_B=6!9_MU/V==HG?JGLZ#5, +M)HZ-=FK S/-?6'ZCX;OJ^']?9HU3Y'7,K%Z +MG:*MU[753Z]JHU3XGSC-B_5E92!V7M_U1;?Q;RZNE7WAN,J%2[=P.G!U#[QN +MKJ?0^% -Y8K?\J@>7Z;*X\O]U+^45L3V?3A;GTM@C\JA[>4UN =.K^NP,;UP +M+613LVSF/-A6/MG*X_58-'N';X9H?(8NVWXOT8K\S]OTH.R(/4P$]N:'S.&S +M.Q1+H]3Y=-K$$@/M9SI^^F+IC]GAJ-!6POP'5A.?\FA>&!WB^4RS.#!>\^_9 +MKM+]I5*33SK8394:L\A,?-W&6^GUYY/NW%:E_7S6J\: +MZ\0$VD8FFTJNLZ_'3P+^\C\$:XEIHS];=Q?KW&95F_9VJ=SEFZW_8L70K5[K +M[Q/YR,6/^7[&TBKC[_DAI@?SQTD].MM7HY/9KMH>)E>A?.!^$/BJ)F:_^GL= +M^/EE(X=?Y_ZN][/'8F>=J$[5HZW8\-=)96_UZW".]58[=[3V*JC26[/3NWBA7]U-8^T +M2KUJIWJL'.K55_M="4P-PY=3I[&<= +;S=0\%RE7/)SY7*6X'K3C&S-NM!Y\ +MW?:UTC:X*/0^WTPJ?^@FXLMKMSX_/O:1<71U[/??S7%QW4Y^*X5H; +M8#^2D]KWK]0CFQG<1IE_<3+MI1:GS_M6'-\#8XUZ^=%Z_0J73&I\J(W7^\$N +M\H\'=M.)_GA1OS:K0L73\9'M76/U\JD[+>^^JS.C-G6M;F>[XKZX +MB^V;G=$I74\5+LG78K=X-U_WUSQ^/58GB?A^^)9([S[1Q^A]BS=^R6+R?)XF +M\J'R\54+K#7V+/;^>7][=X+I^#O1.][^ZT+XDMC?QJ%]?YIX^PG+P6([L<[L +MWZUR^3C-CBJ]4Z%WS;X3@;_8J-,?]7*W:V54?N9JQ7@;79AXG$/)2;>2&Q7T +MVVSSE0BWOKG=YM_I%MN-\+>Y3_='V?"\7)OELJ'A*;ZH9F>E7R3Q6[4?B].@ +M\H\$WOK]\M"W6$F.?]E8,C]*5Y+AUW1>Z 6?YUNDNJXL.^7:*;#:G6;UB=/G +M?/%=&,0JQV+W==N=<_7E[.,!]9]+_!.9'8:QQ\FV>V-53 +MQV\S,?WW-]?LK!A-! [KY1"KV.T7@TVV\-@Z'?9%K;SK'9=',SF +MI7YD]"ID+_GN(I5:/XO1QKT[_N9S\\B^-,U7M?/@M0Z-$\<9 +M4>N&]M%:;?ZO8J,^K2^GW<*C%\C2-E:K;Y7B:G+Y'IRL) +M]O9>V"R:U4LJVZED[ZG]+N@6W7?+B])F4NW%,B!OLMW\)ZJC^?Z[">TNG5UG +MD>NV._G")!+)\D-XO.L5=;MI[)WO_Q +M/$_NO=6^V3]_GK?4-UHM1G^W7K*? !=W&N/XI'J*10]2^R,56Q\WJ6DZ>#]. +M%N_3&>]/@RSN>JTM\^FPXOR/M@8A$O/-(DZV:]]I[7Y+1/P\J:? +M?45#R\(LL#J]#IZG9C 438S'Y6 BEEOV_Z/+_?P?/)?A0FA5'Y<:\^'NU&Q] +MLXG>L^HJK^8:FV-W_@\,W%66E>@T?^A/XZO\]GATJY.1 @UAZM;._B^1?W>8 +M+*('^^M-^_RI!7:32JK+3^\^."[&N_0UL6J&*[7/H54X/]*G>==?F2;2#O_# +M_W+[N 8J"\/W4;W[%+46AK+4RU<]7#AO=]O5]1>:S:KE];,=V,]$"L/G-A'L +M!#[#_T:T4OK41_UQHI=)=ZK?UN2:R*PK"65_-1ZG=H[ZZ^5H5RF/9[=<>]P- +M/(T"!]_Q=_Z?!M/7^_4B]Z;2 +M^V\^DVB5AAJ0J>QT_IETKOU%KEW9I_/K:V;'FJU^"O_@Y[UM;W*;\F/5[C]+ +MNW7ZZIE=9YK1^ZP\*9F)]ZMF*=>=[CJ_T+\>C977N42MT(AM%@G%,YD]E)H7 +MI/5:N$\_P\1WY!9=I2?K4XV>G6KV=OW>:'V+YVO5V"5='/^NH_WF56CT$J7$ +MK9X,'\O;]JM1G#?NNS90].Z9#=8?P4ZNWH\$.[MLLMDY_4*;Z_Y:B;:C\<+V +ME9V5*^_0CML:N!I^NYWN^5MJ19>Q1[V7M$)MES:C-C!_FEOMAME^-9GZM[+E +M\EH-=Y9,]6>K;O%XJE^KLO9P[1*X3K4G\T@S=MVW^U6!]IE\'2NKSN?TG?S? +MS^4VS:3N)_?MZ.MY:97.HVUJV7_.PKE2\=7^7(.-]VP];NRWC?3%_E_-#Z5^ +MJY8O7C:CY=\FW=\OL&'F>G?OU9/STS&\[O=1OFTW& +M\M]XK?^]'.;A:7@U6'\B ]-A]OS*10>3W1A3&^R-EOMHNAYKK_N/]3#<_34> +MH=E\]=RNO.2IR7K<&];NL?>Z."I%RUU9ZGWL''S/O_F(3SYPV$UD(KE-HQ4X +MSH0+W4ABO\V6X^/2Y-<9)3O%??Z;RE\7L]UEF8ETZT6I?7JJEB^!T=V\./L= +M C/?TCRY?;5"HV+SFP^\QL?CR.^3C7>ZQUGH6+KVL\E(2:6<7DQN3>UZ,8\5 +MW]?JW]KM,(@M;HOO +M)UQ.9!?U:JH^DYG[DY@$[.O;V$Y6MUPY>6ZG X??Z/T:@L3LO/NKT'I1F043 +MG\O\DWWL6O_QCCX]'XR?14'+3K"UX/ZWB48TLCX%QF[AW#<8F:Z_K]1A>2JG +M-]M]^+#.%FX5S_;Q7\^_G6_NM>_FTU/;?'>IA3E=;R2SM2?K]+TDRL^9NEEK9ULU"=0V6(U;O_/TK]&\G&]=,NAZFR!@%T8 +MI?>C2JT86U\";Z]J]CZ/+T25V,B[S_XUS#X?^6NJU1F?,U[UL3-]C*K]>K'S +MG=_/I\!ALQE;'KK]8?I_#18.FV#P$?P%_ZM%)S(\;"*/5Z?S# ;_I\\@*-!2 +M_,'@)_W>9,Z/P^;\N&;2[O+U?_L+G_?K\W?WD6+_XE2XJ?$ZE3Z^,IU=8#6W +M"OR''=/)\O(]OV06WWOD$4LDNYUWIK.X'O_SYZK9GMU&K>FL68CFVJ7"<-H\ +MQ0*3Z>/XDCC=AXN/(_:G*#^G-^'P^)J>=!O19CHUZ>Y"[=[^L;^O=[?^[-"[ +MQ\N-QO >C+\W@T2N<6!"+M1;!:%B/IP^E9/'6(@3>[*Y+0NM6KI1ZSYRE<:M +MEJA..I=Z?=2M?L[3Z.C2'KW^GV1R$_\4;_795A%L\%J]K+[6ETQY#24'&4.@;U$\Q*[+3N%9Z@1NT_@ +M]=%G).3[I_*E6#V9K(?!27=NZ/5IHQK]E5;Y9F4;:JQRVUSM>0VL+=?9R?*= +M+!5'SV+BTU]L+]/B^&2&6*IT![W]('I-3#S(KYMR5HMTWRSD9__>-SFL_0,[ +MU_+FDNK GM]Q>OT(C-:WM>JT?JU5+L=0\YJ>[=[E8?01J#*V:OO5>=9\A6*= +MP&6ZETX<>_O"MIVI?L_W7"K9BY?BBT\[&,T,PI_3/#79'$.[?_-8^[U-Q\%X +M^>[NFKM3N'WX3J[_?"$Y'N0L_9-_N])H1]_I3FLRGLT&J\!3*)H9OB:!P]$D\BT&5CZKZK0V +M&T1*@8-(#];_K9?+&OT_>:HU[Z'^.C)L_X/-8_R^?OR3_6.FEOP6$/OG9]IK +M/8_U1ZK7"]?"G]1_]/K4FNUJ*JE=9SO!S#K6SJRZK=GJU6P6M\OW?[0N[ .3 +ME]WIVP_-RN5#[;8-M=>3P.TGVLA?8N7L/=O\1)W\K4N\_F^/QXGG^);.[)J' +M4#:?R@7FQI]D;UOK;_JW]O0Q&!\BT<+GOJZ>AJ%..UU?- NAMR-VHE]:K;?= +M2ZP^7 T'NWMV?!VUWKUQJQ!97ENI_'&T6!^NE4ZMFFT-?L_7MQP-?$R^]3!,ID9;[+XY6"?GR7(_<)1_1ZK39"=UR;[?RLVO>__-3&5LO2OS<;8]8Z=SVSX^NF/SA6+__N>GA[UPKQ1K:\GO5_J>;V%8XL +M:HMG)K.+9:>19'9P:;[O^5+QG$P4R^]-+^!E.7:IF\_.'_G;.I^\IG>/26'R +M+)\&DU%BUH^4VI'*H)V?IF^Y;H86>KJ,MMZ1Q*5[7_6D@X/3K)$[K7:S=CK9 +MZD4NU?/W7\S./J7H*OGL1L>?V"\V?K[OX?ORTV@?,N'I\;C*#);QSLJZ'"YD +MYKW 4M$8N_17Z +M%0WO59VC<&Z\+TR*C^[^LMD_'M]^KM1MKZ:W]KQ1O$];S5N^&MVM\]W-:YH] +M/+/]\F;>288[S_#(6AN+Y2+5R\V*7DD$"^M(YCCK[[/YX9Z%?U%29XNCPC$7 +M+D08TZWTM-,;7D*17_8\_+K*-L\88K0W$SPV"PN.^=0KM=:+S>(36Q?'PVWF +M$DH^YI'0/778ITN'?2;\G?9KL7UDZ<4^+?[/5.+_3!::B5FP6,B,3\%6-':) +MQ2#EE5LC4V]E=OM/X#]PN#^78MUH9!\N/I;1T*=IV1=;RU:W>(H62O?$*Y3, +M7\*?U6Q<6%4+TV*X'$M^3L=4O]$:1H:QE %ZZ3DO'Q_GT3XT/SCOO_QN%J^4 +MNLW?;+&^]O++VJ^[&ZS#+7WSO9;-AEKOPNLX?;T*Y6-@=5Z>?GO1X_@0;9X" +MW=]+_S%=&A93Z6PB\/:)'Y[#]W-=>F6ORWFY\VR7BT=6ZD0O?HKE8X?%Z_[] +M5.JW:"L_NLL1YS>]_*31R86:]>SG*L^HMNRE$ +M&X&SB\Y;G 7^TL%A/#T8B.GN$_WTLG]LK1+/Z_I6VSYN]^L[%ST.BIU-+):O +MUMN#4&>7D\,=UN>']/G'(_TLT]W/U#.[63\VL^"RU;I79[G(/__:E1+N\ +M:7V"[UOSMWAVV[7G/];)E9L3?6/FO96P[V9O_(++NG +M7'G0ZO?:LX8596LR?Q3>C\?KLRBD4OWK/A]*_3/]:^FV2,1K,O-ML!K=IL_T +M/[(M=W;#ZRPY2U2OZ6(K^-H$)G+U]SOX[<3>_U"X$:VVVMG?/[\\%UZM[O8K +M]S8[D>LB$Z[%,^'0J5L;%(O+\ZD?'3\ZG^;H>0QG4BAO-KQER%Y:D92Y\]=M +MKQN)=S%BQMD=O]NIZSEPV:ELHM-UJ[GL)];#9G?_RC[JXVHU,@K&H_E%:O>, +M5"N?S*=?+=>K^WWETM+)MY:YXJ]7/I8NQU6U7EG5AJ]4);]>?NE0V^%;;CQ: +M3"N%SC-;VL=&S>BI,W^G3U'[NM76TD:^W>_Y]5SVGLUCK/N7"S-W'D>VO.A2TAL"@2Q28D>[BL.F/_OUN +M9+:.=?.%^+<_702^5\GX:GQ*N?W![J^P_5_N\];M](ANFT.!=OA]W:.%[>\2 +MCD=>Q8-)?9A5+L]4Z'V]G<^IQ759[9Z+__H\G%U.KXEQX"=!1%P*GZ=%F;GP +M.W8'R6O@?RT;H+^3Y28RW"U6X5FR\](,_,H&70,X_58V@/M^CO/SYBX6'T4K +MT7AXF5Y%VI7?=#4+IN[S5#.<#H?M^N8\-9Y,XL7ZKE)SWFXCCUMZNR\>K]'' +M>G!]ICK-Z')U+_5_Y_8]FJ],N[GF\S^+KZ>+;;E4+N=FB?MJU>V')$DC(J35 +M[BXPL2YW1[M39+T;CUJWQ7G9["8F_V9TT^DT)[-9XY!KQ6>S]7D9NIV7W_YZ +M\L_HNJXW_5FUN]^T!YCAU*<8*M[?A5@V6A^&6X_L?RZ62S +M^"I,#O-M8/\R'NK].+[DTV9C^M@.3BU/KL_Z6ZM_8XY3I):/_3&OT +MN29*IIZ?F\[S\59SW8+'\SSY3A?GWDBR6;NU*-[BI[@;#0C9PT"SN +MUK?5.=0Y_5?O9RG_2)6CC6"IT,OU(_=A6V78CSPFPW#D$/XGU]W]^?MI!-^G +M^#BROB<*\URRL>@^V]%LI?SJ'5*91>K?W&S'J]3M]PM46F^G9691:4\;V5TP +M,>8I+R+YR^'8SL4V[?XGNDJEUV+Z\G_2 +M6!4[B_1EMQ_TOZ=*HI+)#7ME$/@J G@N''Y]!['">;3)#&>#??9S:ZQNO^"Q +M5#DH,PO;P,EPM#R-D_VM&C\[:T_ZR6RE^HA/LOGR?)(+G1_#WS_\^3Q*A=%] +M]VP=SJ/Z-+*Z=73=Y_+@\*S\,_G8KK0_1\:'>^CY'(=JG\+Z%YR3F=?SPOE5 +M2D:_MVCV>GY:F%^5ZZI56*Z.ZM%&J=7NOL^1WFX&YKWN'_=#.G=^_VHJYF:T +M,YQ?L]W>N5D;S*N'8#,S2>8?_W+D]QW6%.VU[[4_/,Q.E>ZE.=C/Y]MG[!K/ +M,+2#Q?'9_/Y>&-[N^/\:)S+WVVU?S 2FXY'Y^9KNB>E^%L%O>I\);(<[I4;H +M/$],[X-NO5,YY*:_2S466P=V;N/P,[M:M!^#]*Q9O5]GO4UALQH/[,V]Q_GY +MFW43YV2MNWSO@$D_B68O-YAO;D"XC?MFU$@ONMG$93!;5H:C8#OX?T7^[_&N +M%-?H#^EGLS\9%$KUW(DHWEK7_NU!?*-IWIPN[7K^7N[]4N_1+MU\+_?C[./X +M;(QO]5.A7LO][,T73.K;YQ /I4.367@V["32Q7 R$JZ,6Y=I<)/I?K?Q:F5> +MC"46H\!J)K;.[ANCW;X:V^O]Y6WNGTO6#O?J?J:;3[X2@VG@XFI>OI_O,2%[ +M?!AX/@3?T\RL7LB/7XGJY_L/;&QCYYZ>^5F9R(%&/\/_X!4,YX_+^+@2.J:* +MV?!G&E_N$^5=J[8(ON[-03*7[$V:\4.P7=E>S[=3]:^"V_KVNY/=LQNZ;&:_=4;S=GE5JFT5OM$X=J9K N74N-+$U^M1[U/M# /!O8+H<#F6!JUM @V +MBI-R-+AO_):?TGO5_HQOK?-T_CU.=L%R/-8,%6:;=BBZK6^27R'CL=/,!>/A +MW-PPN7BETK5-);WHY[.3W[!W?OSBP53V4^KD$J_":W!9/C*O7S"=VN;KC]]A +M6[S??N/GKAJK'QH!+Y<>G6.U$OG5%XW:H121]P["LV5C&8J="O-=892HE-?5 +MI3EN)%,85J:[6?+8&>7:T_:EK'8O;Y-;^#7Z/9*=;BF]VVU:J63PU@PW,O?? +M)AZ]-)/1UC;V/\H'TSN9JGM<9.-8**JHUSM>M"ZG'U9Z$7U%NU;NT>:YV*_KXWS>+#RJSH_+731:2!9B +MUUMA_1PO)X/6>/8^#9KOP&9S.RG4)ZW*LUQ_YH*UPB+6A\_@/+]_=,50L[Y[Y3_4W +MN(8&@\BXL_2DSBW%SN7^=O\5L[7X)W3]AW+;R7[7UEEOC_&GF%CTLN/4_S+/ +MW&:CUFH6_VS*S?OIE-G5[_=BW3#9W9UZA]_W6NV.9]U2(G6^#W'"O_:W7MQ4 +M_YLU$F+Y&[U%7I58.M[I3=^I\CFY:FYO_Z#K/&GO1JO:J=X*)"2_7DWDTWII +M,)N^O/O6+MM>MSJS7C!P'>X6QO-IY+>[+F/+Q:%BCYJP61G5AZ'K]'PJYKJQ^.QC>L<;+>F +MXTYZ:3 +MX[T<5X_.\H=7?)">A%/UP%,JMJV60^'G.I2\[E+[V603+J2"^;K$G7AFL\G_ +M[K"H'NJG=.7YJ_8=TPUXT85NR:+6Y4S_+XY=W&[>I_7F +M?3$,,2(*7Z]3Y6(JN]@$[N+!P,2[T(\]WY]R.9]J1=VBQU>X5.J,\O->LC8^ +M5G*/6[!]:CVJ'<]R:OD.#)PDVK>Q5-\56RI:;1XG^=#L5&K;*B_3RN;< +M*R?6W7SSO1Y5XMWA;]L9]C?S^J47/9\&]]BPU,J4U:V17?[XF+P7B\JP7M]\ +MEBKC8O2J%4:YW2ZRB5T_K]8C&YL6BZM%+7.?];OAQ?LZ2E^NCUVN^-K-ENO9 +MKK=>U"OEW?RC+Y@?[F[?U3_^N>5R[>WT\EX\&##[CU1W.[]DSY=.,G*+=OK9 +MZ7 _B_?NS?[V]QN6?Y[ZJTY^>CUE"O7G:CL_?)K]0PF0X+^=265*N]TI=RZF +M%JM2K#+/1RK+ZW*0/P7OJT=OF!].TDV=_'S77.1*@]IVT]VO+XG2)Y@"-@8> +M-HW!+?+(];+S=J9=259+]?U\\VS^WNU6'XTYBJ[V'N2MW>RZI5+^-MW+*U2Y +M7'.K7'@^?C[6QV)[7;@N8LMILQJ\5NO3WRL8O>.BIYJ-[/.>:N[DB&>+[DG] +MCM>XL0>OT!NG75=^3O+$)=)H_!K77FY^J90_@8EO-GGIFLI/C6@\%^Z\G/?Y +M,]VXA5JW9>C?7RS&D_/FM#]GCJ-.\#-LA=;3^O\^[Z]CJ +M?//G2SNMWPXW[V3]5#Q'ZO_%HW_8_=L;+,ACL?Q<-6[W[:_P"!SM!JGMX],I +M[3K59[N[7M7ZQ=3FUECHND_+FDQYLQIT'JUV;O&)+^:=324Y&!Q;__:V>Z], +MMO/6ZKVIU_OY]+_7&*XOC5GM-Q@DW=]NO7HL9CO#2H(7_7#+A1/EXKU^?D:_ +MQ>*KV*UGTM_!,?I-W#N[0K^06^3&YWS\>:L7]S]59VJU*WYCD5D]D>SNP9KSWVJ%>& K?+[U_N7;X76:)(8JT>E]&3RG^O=K]5=+?R\M"Y*% +MV?EP6%[[RUIJ7;O%]N_4OG\YEK_36*^38'D_J51JGU]5]LM][3&KS**+87%T +MJ:>NJJM(-K(#8"5NSVVM_RY7[ TMN2"!PY[^?DYZER9F/)]R!R6"=?M]9B4:Y. +M6NO![G@H]:+1WF>1>6XZR>^WNWA''6ZN6[)*O1V)L]'ADNNKO?8IFNWT[% +MG[XPTTQ\0IGS);Q+I[[A6_ XCF]FK6WP. _M"^=,*'+UP!R_9O=T_EE]QU?= +M8S%W3*Y+[$5M]ON0F)U#Q7)8?G5:GJO5?[3_B(46K\3W]PYU +M4^?JL]&L'G.7>[95Z(YV[5RIV7QTZQ.^\7E*Y^+C<^/ +M\2PWRU2:I7"IN_YV^.@/H_GN]/9\+*=Y%J] +M>:(W_36GY]KZ/.-&SKURM^U7)W[I+%^ZCC>Y +MYR<2"9R=MZ]A9UGH!+[^Y\8Z$0H-;ZEIM!);M2>'8N Q<_H$>]>MO_7YZ'72 +MX^TL'/VG/HUF8ET?U)Z=Q"4X_(^/=,7(VLCV5Q[M8 +MNYCT/J^S8C>:F32.C7;_.MG_(Z'3HU0-3-_CK_0OG@LEC[O.I+S;E=;CZRE: +M+VQ'U]XF%>WNPS--\G&B^=Q/:N%],YP/1D;5^GI?'L5"AAIAUWA\GD'^?60\>V[?7R&0NGD*C#[L]>__Q59 +M>O!/\0?_BC1B6#P;7Q\V!<^87WJJ-%NMTME/I+,/K,8"%Y7X4JOW^^] +M?[A\UX=Y)S& ]9?+A=V\L&N$4WN/2?F2_/2W\=)R=ZPVF__YM9,; +M3>>A=>"S$QVJC//0,-%#]&^C@<=<=->X]%:?T[M_G0=>CX7P^M^I3TY?J+N; +MC78SL5PE/3CMJ[7#?IP?BW-.XK?2>AJ^/3OA@5VX>,E#[9;F[6'=\ZP]H\498DO?K]FW*RT$[&N[%'8;D; 85+M71[ +MNM^\:[5(>=E\]JNESKQTNBPSSU J_ J\?*KI<+WMX_Y4V^57[)4K"B:OUU0B +MOQU.0J7#:%\8YT?=3FR8_81'R7+^W&]OT_?;=;U*O .KY?EM?)&1/_^!]\>F +MM"XLN_UUI[JH+M>UXV(7^=0ZE5_S\ZZF/Y=FMYO,?B:I?FTX?T>:O6;]G;J] +MF_9_.MBII[N/]*M:;,=V]7TS.WY<=Z7)M]S9)KJQ:7,>"S\KZ=8@UL^?F^7P +MF8 -2]-A^7J4CU%63-;/=<'RW1A$3OK +M[^7,?Q7=ICO5=JY^6]7'_TYI=?B\6^KHN\8D^U@%=X7:YEA/]^_53W2;Z_?6 +MWV4A/X&QOI_A%SEIN]3?Q7=13_JS?3O-/LO#NE,P"S\>K5OG_XEFH^]VZ) K +MS__KQ+#ZC?_WN5CU/)E&^X7FII]>KW:]S+&Q;3_3NV[BLOS&<]IUM-5;/ >Y +M1 ODWR="[^PR])Z6()7Y\+K7.C=+U6RW\]V"FO? +M8N?V&5M)@Z]96LCEM\O^^#36W6Z7W* +M[<8A>,]>K]_'HUN]:MN; +M\]%U/[U-GM/^8]\YOG:C<\0)>54*>I^[Q&$A+9T54NMYIA-_-4[+9W@Q?0^' +MJV)YMCJTRZ-:]K_\9NN+T[?;/!57M6PIDQ[5$V6)=.RT+IP^A7JC.!A7PMEN +M<* 2S K"=O?M=SP^,]?$R<3J]W(;2O5*85%^=]&_T7UKEZ +MIY3K5I*UY/21'[VJ[5>[-#T5BNE%<;Q:ER[-O_UAU'SP^7X/O<-GV +ME+X7W\WP\=EM[^O\I1$8SQ_%X-.)]/AW"*56EVG_VGU5$ZM]+KN)_R+/S+2= +M_NZW.6S\OD8__&_*X_>S\0H5IK7"/AKN[+3J;+HQZKTO@=-HHEIJ)JK1QCT= +M2ES?O<,X6:GMJY=D(SO2KJ^AZ'@_>97*XW9L5A@_NK548A2+E![1[' 4_JUR +M_]'_%DR^U\G8X%3OS8/W/:+CVVL]NP5ZK]2OA;,W>*_ +MQ_?\&=8"-ZUI^5W/UX[;U#R"*\^]<^WOM?D,[@?/KPGEI7YI_7*U?SEY;I>> +MG?(D=^@6!MGC?CHZS^O#[C$1:48CPW_J6.ZLVNO0K0B??:>*M_K+++R:AR^O +M2?*4#4RD3K70/[[H?E+9S>Q6S[^;F4@IGPM74X?QZ/P^#5^SI__KXJL8;Z6)HTGAL@I/7)E0KGK/3W+!Y +MS:Q:FU"D$VVFPXKV="N4R>XSDT/D-VE'V]MA^5F?'ZLM^K<4ZEPB]VQP&#AN +M?[_Y>&7R?ZR.^5)@<99KYS>7G3O12F7W_\>2E>)F/$^\XJ/C-1V+3'/)2&NV +MC'8^V]>OW0WL+'/Q8[UV:81*O55D.!N^EVO;?+N>&W7?@>M!9S+)W8+%T+GX +MF-1:O=)HW'S')\=!+__1]R@7N^\N+/+N)M2+)2())-=1 +M=C;0,]?&M4)H]H1&+JU4X]_-9.ST;F^9I,%_-GH? Q^%]B2QOJ7\_ +MG&GD9ZEA+)A(EVKUT7;27LW5C)?E+Q<_;<>S8SWTJX:R\??[RJ.N3B.]^V6[ +M&20C!N%+9U8+-@^S^/^7_R8+W]YNW]I\Y-[][+D<61/6XJM(MKEN?UK5_"V\ +M?IV7][P%]K0>G(9"X5]AYI[?3Z/V= +M:=4WM?M\WBU6'KU_M0S%;%^JT<@IG-E74MO.(C"R?P7+L_I@WT^,]@$O5Z/O +MYC8UG&P*S>3NW3V55^U[)_O_G]O_WW_Y^LTFB]"G,[J_K_7)IA58^X7GY?;N +MT?[]@LZ$]VM@Z_G:QX?!S^7[*D>6K7RC%OZ-X_5E]=8J]4:7>>@>NG\FP_KB +MLWK=,Y'08#;*YC?/I7AH<3QXE39Q6_QK8_B:9 BCR\&O^1_MB]/LL;((Q_Z) +MW>YU#KU6R=WA?#DD:D,T]/YNJ]\F.WF":+OZ;FR6Y/@5@7#]E1_?YIQ@NY?&4> +MB9?GY7RLV%_*Q2O?Z:/RFG2BL6 +MOI_#K5 *MPJS03\8?U]SO>USTO^^5NUZ^C\RPNPJ>+N?_ +MOAQZGDJS;]H!?#_--5Z[0R8ZWM;2]VDX%2XW_MFN*G0N-=P>IO=")40;_84^ +MH]5D%EA:=Z6@D[U+Z!PV3(:'U5.C-D_/L]O]=/MY+":Y8*A?#A:"C??Z^3^/ +M^O[BPNK_RHP7H7CT_KU7D^/2HO@$4*1T?G? PDJ\,-HGH_UZ.M-:C +M3C74B/7[M6EEE>AM,^=V/%T8I0Z]MK@X?YV,6HN^DAH;OW!:#SG1&!Z50ZG;]7)M;CDR2KL@[&6=CVI/FY/>_SE +MIAG^GQ'CG=IL]#BD+NUU>3)^7M_1D96_- OL?0>EU3HV+I=KP\@W=9ZTU.Y; +M9%).)*K[6*0^; 2VCN_+JYCX=?N92B[5ZF[N]W]BOG[.TL%6I5X5XM8S(?-U +M%=Z&M@[@^?;CD_A42J7/:?8.G$\[Y7)CNTP/T]%%(UGL9PJ'7[E8?9:/\>)G +MY(?[3=6>Y=3_LXF]NU[U>_D=G9^?X^QS,Z5N,*^QPSEP$&L5#]M/N_L=MD[E +M?&"N.XHVVO%+B9#2\RZ=(]N5J5]/Y?8/)Q.?>BE__X6'CN0X:D +MPV8WF9X5J^E#-U2([@J=0B563@7/X]HFV,M,'LG"Z]Q[U@IJ]W.[/N8/D<#S +M\YC[!C^_%ZFT5Z0T-E.CU2AP2E1,;0;I_F-1_T2FG]-G-.KE,L5C_'86R2;C +MX4L^^?HEUY]%;Y5)'N[I5;*1NA<+H1>N,Q[*!GXVF6SZGQVD6^_1K!7=WI*3 +M=U ^&C.P!A9*15[Q+30K=+^/_2\4&=X3K7]TM,X7D.O\\)L>G5;Z:'GW_CV=A.GDE,]W$:?<8!A;: +M^?FM/SYJ2$N+:N45.,IMU_W(V T]_SB'>]%R,IQ*1V/[1*:LK\\G;T[VW7H[#PS15.L;CNV(HF/[XN-.5Q#&?>L\J +MS4*W=!T7S\'++IF*[F:%:["_W=X+I5ZZ\2S-@[UTLG7-;R*I6GQ]>AW?M;5Z +MY#0;^1Y'Y6"FD;B74J=I:QJ/=>*];B?A\S;ZI=0;09O)?TK;5C[ZFA0ZF<)J +M&"\J\0:\[,1CO^GY-A]X>ZQ2V]/!B?\87&BM"R>>5.*1!M;NI[1[[\_M]7 X +M#5=2GV=L%#BH_D;QP?AV::[JN4\ZV.R-4_UVH9/[G_JM1&'Q#N[FVY/IN'N\ +M.M%G'XD_!*.WG^/Z.1U>GS/Q8S(6K5:B\U+.N)I+7..+2^I5KJSBD6=KVPWO +M7*>3?K 3^5>2[?A75W +M>6OVP_%N83H.?^_L!BW[_7Y:);./;PQ8X&YQ:P[?^9/O=4U +M5DP-L^/H<-N*%NOA_:;7.>?*I-GH,Q34=7<'__\PTJXM(?*O5B55Z>].D^FT +M?4HM:O_FX)'*#YKA1;6\?97FJ5&#@[ UBZ5O_^/UU5*/O'7;O43],?[WGM5< +MIEI:UF(6XMMG.U^54/9>:5.=OH[=7C-^N_PVX__D$HW%-KFI..>YG+\U:Z7! +M+[&(E+/1QK?W[A13E4\C=GJ6VLW6=+-^/G*PPF2ANVL^IL':?A 93:^_X,@# +MNO$?!1XDN8?YHG^?SM;'\NT<7*=SBTE[,[^$1^GDM;Z_MWK'>/I0J84*\6(X +MD0C7@L]ET<59'HTZXW2EWFZ4$YU[,.=[!F^+X2QY?OTKRT=[O!Z5VJ=5^9N9 +M)S*%WJ"U'5>^HT&[?_A([>WM)CV;IOF8[+"A?O.9C_\/KUH^_^J/CI_V,7]L +MU=JU0;-YU"W>IZ/+['PKEUZU_>AAK;T,D*R'9>YXW9[&A7RLO1KV:OO@.?3N +M9XOI_G+32^=N@=UN.+^ZY1:U/B\9H]U[5E!V"_<7S5?@ +MH=K:5=*S56'6F"P?K5;AV/Z=).M!Y-P-C1?A +M3B%ZF_WRGV_BW1T./[=3(]MY?+^]S'-0VN7[D\=N>6ND,H=?M/W;U!_-QZUT +M[1VN3O[FY;?89D/!9?EP&[L:/\]'?70MSX[QTV51BD0RT_?N\RLG?^OO^%7Y +M/4;Y=VN3&60KSG_ R\79X'1=#'O38*N__*1;ATULF6UU(_-ZI/5,A5NO17)4 +M>:9KU^[J$KN$,O]O_!3M#Z*M::[MO,>+E7#O$IV-MJ_0[YNX)"O/>B92/T6: +MPWP]G=]W V.Q^[M>3/];X?RF&#PF^_??)MJ(CD2DC]1PLV\>FK,YE7P3WRX? +M\YU,^=DM/5JI>6,5&\36T_FR&&^6@O7\]!29KPN7:>D_ZS@3G$?X@L/9]U4- +MC(<7]W%R$FYE3X=CY;28S*+][_[ROJ1'U5\P\DPN]EFSO_'ZQM(A6J]E'YJ7 +M5JO'/CFM9HM]+%2N/%[[UNERI[T/HW/F<7T%'^EA<'[J;:Z#?RVW +MS!P&ITJH=SLE/JV@5CD:_#:^Y^[U?(A7%N=VFE^_^(X'M=DL_TY\9JG\\[N+ +M_U:?SJ$2_O1S>69WYQ][///KACCW'QZ^SK]XN[UXQH/+9R97_03#E6_Z=WUM +MQU+DWT>PF,K9X[,QCH5GE>Y@DJJ+A;.Z\"@6G^P7^_QP;CUS^=5V5XW,-YW+_Y ?IM+YU[HPN7_'R=9L6&].QN_* +M8UF8R-*&\X&-["9[_+RGMQH;9#]PE&\<)O_.(3'H!<^K6"VTFCZOF>#OL4Y= +M;[]Z%[Z/)_K75BSA.BJI;#[\/C=BO.#G>;J_: +M^;Y,URJK1O.PF/X2N^ L'/IDQD[,;G?T/]\CRV0O$BK$_M/AL9,[]/L=^(U4M>CW??FTG"6S]B>0&A7-E=$ZWQ_/(([X>1E*1]+ 4#H5>M7$X +M^MUF"[/9]5FL?ZJ[Q> ;6>]FD\[T;'X'/NKCZ?_XL;T]Y[]&Z1FZE$[CVV&\EH2,&,V#X?KS&E^'F<@MGJE,$XU#M#X-M7OKQVB:Q&8J5IY! >-[OCU&4Q;W>3S5VI/,GOOZOBK[S]C^;1]A=F3E>FRMCC4^0; +M&#MU%GMM=B3^J.]KR]]DU>EV^OG'9?RX)3:?UB/R=DQ^J_O#\MA=]+OCRZ[5 +MCQR_U_6\,]JGBZ=76Y+T&NL4!O7+OK.;KVUA;^=;)A:+)1.)1.XT_57'K6OU52Z?F[0>Y8KK-)J,%R*58S:6*LPGD>QH%CF=J[')_?Y) +M3'.![TONMSA,VI]W91 N_6J_1#;;K^=CO43E5=#)?SNYU^603@PS\=W[,GI- +M$^O;\!%Y]A+-4Z2_;Y42^=?U" +MB?XV<)F)EG/=ZCJ\FJY P=.+[B*.S:[<2J7D_3+-MO/KWBT6O_CW^T^KK;1V +MUM_F)) DV;L_!MW/HPD.WMX4K\?-*>*%6JOLRX7^^K58Q^/36W :J]P*E_5J +M'S[<4^K1Q^?8^YV[H\!1J;$9%[O]^;H6/V8.L&32]4XJ7V]ET\'O>3=__.KYYB[53E4KO^'P +M1)C_IDO[YNJ?>=\;"-EM)O?HG-R)-\/S8]%?M$Z-U# 9_3V3G6/Q](QG1\_! +MY!F9;.K%;;K]>J[[G]7O=2M,)MF#O+6>G \[5L%/O=,M_KNMU5I(&^O%!]NJ +MYY_H!I:_T*N-_<#/Z?D/'ZS[22[3+.O+X@CEJ7=YE^OO;>' ^=FKI +MPN.V..P&_VK\5!K^<^_D>'[YSX/3XXY5_XX]ON]H)WNY+A?I\V@R\!$NS]3PWK+T;R=XRG&D%I_=^ +M+?^7VC[&HTP]-%T-]L/]>I*9'P?73EJ,.A6+]5%(9_U.NG\951*Q0F:2*0<% +MF9-MAX$P7M_94+\WKTD_.WV>@]%V.7.;+TZ;4F=_X$M&'[U),#^(5#XTL,'2 +M_1A^GWNE9O4_Y)3.%3"97Z\;BBUTJ%G\F7Y.? +M+1,)]#SL9L[]X6(\F/3[IWVC%$YW FWHQ_.J4>GG:I=9\AV9N=\)I(<)9_HY7][F0J9A?O5]7 )'IX.FS'_N1(* +M;/R*L40L'1]%FI7R-M]L7X[IQ:GP5( ^GKJG5F"VG K\GG]1'>7HF'IT-,?\>Y.3> +MQFC5;K?*N<'RT2B/!_5WM=^1JAQX[_*L"1H[9=6DU4_.=J:_G^$N-8UTD[U5^G=I +M18.]4BQRK$>_S=:G,'M',\=N/919G.O);61(&C4WKLZDZ$+%3";PN2H54ZW; +M(E\-[X;!TK^1^PS/C54''8/N>(GG5G\ A/2P>[B^)>(Y[>9 +MW>F[KQ:CB4G@,Q\N52.16. Q&=^/1I_'\?@]=A*]9700"^=#UUQ_W$E5LNYO +M)(.(?US-5Z_O.?0I_EK#:^:;_E^#!4:+\X'^$ZM.9!C[1R?K;>87#'Z/?]GV +MY=PZIC_I]R9S?APVYX>IY;:]_F^E&QN>?GH@?MYD4L=4-W@H#LO+[G6VO&_J +M\_"A7I>E?O1:G_Y]N"KWU[G".O[)G">G[2SWG,9#PPE[=E^\-;:Q5U^S[$![D1"'AC +MN0T=PL_%>UI81.??[2.RC5_6_T_GL7Q6Q?3=6?;V^1=JI^,N-GOE>H/(//S. +MI\*CXV +MOO=DZC!+C,>YV^G<^\_WB^USE!TLEIE/E<5=_W'CSV)_8? +M=#9^PF\E]1YOG\]"87(\'R_EQ#JR_YZGLT5KVHU>BJE:=S5+EVO=>B95G-;> +MI_%TN4_%%Z/S\&:(L?1/+Z*3=S&V[M1>U?Z![5KY$8G'%Q*I^'5O^\@ETOOR+/^KO=:'W3#1G9P.C^2KGO^5 +M]L-*_WMJ7.^3$G";^34^@;]OZ'MZG;,!+Z]OO7%MD'VMFYW>^E.=?(K5T#NV +M"^R4VKU.L79?)I*-P,?M]5I'S\_;__0X'!J)>C#QCVY,QUHED\P_ U?A1"5Q +M2N;XWVE[N(F%\M5'\A[LQH;O;6^SNX16Q?OJESC&\IU,];4[;?M[\J)"NA^]^GL.@GX?Q$PIZ +M$!,]E3?7\_$V7XF_G\ED-?J+U>[_QBO8WSWC<[?H([:NEQJ-3W#_7D1G\TUU +M-7S=W]%SZM8L_S:=0V"2U>H)^P_>&JWX\)(Z#Y_Q>#1Z7F7$SNDE$8V'&H>=TUJY/$M-WZ_YO%I'Y; +MB40;S=#S'5\-"H/..)$^?%.M^+^^;,TFQ5YID4:R;\,A@S_9GV?J]4ND%=I& +M!^'/^:KK9N,W NO#_C([?21NX= WEOPDWZUUIM&[Q__-\_[\&<3#Z6JO7LJD +MSHG*HUH/_1O9:V!YH^IL53*K5&K^JCY[WU"P$IR?)^?<[18*+)8FL^FY_=F_ +M8HG0^'&.EZ[KZCYT?+0;S\MD_QS'%.W-\:K0+ ZVJ5\RQ40:S,>+YVOI]ZR' +MDX5DZ=.,G+KI:7O7W.3/I^ H&@L=EKUB;/^\3L9NZ.=Q_7GMM$;U2JV6K:_R +M74^XR]H@GWO+U:'WI+@)/.\#EPWI\'J93._"6,WGJQIK:?3]X2I^#-7'WUVL +M^,^/O]5?O(+=L?=UC=3C55KW4IK.6UUAJ]/NE'8%-OO^"ZW[+R:@\'W7%_H)>NG6N*6 +MJHXR.OGK);P>E7_!<.L3#6S.J[73+%Z(11?Y37=^^S76F^M^.V^UI^/W?')+ +M1>KQ8E8./=,Y=8(2Z42ATK]3GK-E-Y595ZZ?;',V2?T:Y\OK^@Z,O[*33WY^ +M/U2>\\@[<'?<3$*51.=3F]??EU3 R_%\@O_^I_KQ3#PP5PN=]J=?Q=$=^0T3 +MV?CM7W@T1OO\]C?)7\?S2N/7'T>Z\6#Z]+_.)4F[X=FT.CHMEI_0_]0Y-U.K +MW*H7^\<;I>QF-/NNB\M/KKYK%'^I]F&T_\[NV=P_$R[L?].,LA_0F-G_.Y/? +MJO;:!"^7[?Y[?V86@^KSE[NG0N7;ZS^-EM_1X'B2:]7*T6H]F2].^H/_QC"Q +MT\W5&X7%K#T]S582S>!IVNT/1__38K3; +MG$7?>EDB73\<'^]>]!_"_??YT@FLIY*%T6#6CJSBB\XH6M]E +MD\MR(GQ^1(Y.ZEH['Y4.MN^7U6>P:>;#[_X^^EN/R\O.\#0IM#:1>.@W#&_C +MP=TVFPS&S[%4?%-HCPN%4:=YO_X.BO;08+F_;1K7],$.LC29?+N)SS8RLENN_#:SZXEL*%3S?3/AYFO4M_ES) 3WN?_?.Y$MM4'N_[/WL,CEN9 +M[2+?OVPRSRIO$R! S%1G/*M7Q +M=IH^%<[18[&U3D0?I7&WW%H<\LG5,9F;_=>'4'GRF6SGM5C_F:X7EION\FVE +M=IUKH7FA4]W_>Y'?[O+:-6^GSN%W>F<_"*?R[9:%"GO6O'ZH'O>>EW.E[F +M[T[G^3[MUN]GKC8OOJ>5:#(P%!LMX]%TG +M6..6.:[WX]JS_BGUWJ5/:#]*'\O;6:D4F!W6PZEL9K&LQW>[P[%_FN2C-O1] +M?;-=QJ*QP.%ZEA[F!\_I[G,.-J+-XJ_9RH:?@8WB)_,JU%>[YRY6J_0[E_WO +M&[E$?N6(\QYZ1/.M7;O[?^WRLTRJG?M>OA?%^JITB64T_.<\MQ?N('+DF:"S&[0[7GH%M9UO/O<7H1OH\KHT(V +MLB,5K^J'8>(KRNC)8%_GF2?S7VF-O=C) R;SGGF M'-1!NBV'4E=._W-=I%> +M3U>1WCG_#2E@5L.]5J=Q/\R+Y\XJ:TD8S3Y^+N5SOZ?L41V-)C' +MP_GQ?OYY-4Z_Q.61WY/=YWLK':U<-/KUIQ@+W 9VLZ7X?C$*3%8;@:'E.1*8 +M#@_G(\6#Z5J.3XHSL_E8;.P#_R'7]_HZ+"LE&NAU#)7GWC5F^"M_GQ\ +M)\5GK5'-E_O3^VI2:8Y[M?-X>=GM[Y_*,1$:SGSZ^_H1Z2WOES@'U" 77%\_V]KA=(A7 +M/WM4_[I\+U\NWW.C-P['1IU*^K5M'!WLQ=ZMDZK_Z]7Q>E(K;4+%S2BRC48: +MZU.ML^Z^%\_<8W(*I=>[8[U;3O2RE5IGMVFE;Z_OP/Y_=P^[QG\\"2R,TO7@ +M\C??_I^+^3LZ^1]F]]YDER[5-[_&.)OZU):57>?RJF7O_>*Q>^@7A)%/K^[N +MW7J<;KU8I[*+#L^[\O,97_:/N>+S>&I?;KM:P?F_71N?4:6U[I%$8Y]EZS\\ +M%SR@*[/7K%6)GT&=:-;%[SD-WM>UW7&4+$U_T74G6E;D/Y:D]NQJ7PGGEK_U +M_^EN#8\R_<=*9BZLFY7 ;&K0G\2SQ>&FO>DDO_>A#OZQ=!Q=K\OT +MZ)?/EYK+:^OMGHYQHNI;+?;K]3 +M/HS:Y<([E/^E%X?4Z_B_M2,9"O-;; Y +M^T1[B=JM.QJY[(]P['/^5%?[4*$4ZA>-$/C;7JV3=O%5[GS^/0/ +MK)T"E]E[,UYKG ?IS?G_OS[2B\\LTUDT([5%9UZI9Z:+[_>1R3V?T=4J<@E7 +MQF,'\.T^=.X6.H/F.GN8C.*=1F/=DI'/RJ%AI3Z9W>=_8&ODOKXF9O_5]!0= +MSQ;[QZ4P*&^<"9_S0_BZ+>9GR\XZE"O6R__L$\J\NRR*PU^G\]MW8_M"85>N +ME"[SV[?\:14"J\-^KY1Z_M[288P=>AV+N?W+W.GU7@.G)=;>O5PMB$LI))MV+#W.L8;WUJ +MX4C@L1![15[KS"F:;0TK]W G=L@7M\MUI_XN))>1H$Z&=B=^CWVRH=WST#IV +M"S"9AY=.!BBMDQGPLD]V$]6U7_[?<+4:V-M]0Y7K9#Z/38>;_V>V/-3^U5WY +M''Z=B@LD\$DOW-IUYH?4?)37,R=#[4XIL),^]T^/Z3TY*B6+R6V]O2QBN._) +M??P^/->"G5 C,VG,VJ_X^#*G"9U;+KC+T>AX^!_[?MT_C-Z[6 +M(Y7B.5&.I>VM5HD9,!>=I+%:&IX3<5_Z=$M=&CU.]-&ZIL]ENOK +M\$,8.3=J-1_/Y7\9G02N&MM=ZI1.W3_757G9WH<:S>2D?,G4\ AWTTADGZG5 +M!Y?Q,G(YK(+GHT ;RLZWR7AJ\ZD_1NU/.=C>OV;+VD^.^K>S3[:"FUW@99^/ +M+I^57G34:0<^!XE1;[Q*U4HS49B_V^6W*?)+JQ[2/8 +MF=97RW%EL?QVZ_5CZ/<,WUY%!==,^?]1,X8?\V1NVVY<1Z%6]13QMGY6U4]@ +M4)'R\MOOVY_8NOC(?>_CZV#;C85Z@_0X=DL>LI?N0^T^G([1?C=5'K07?1C* +M96=?+-?']WYJ.WS'U[?EWOR2TW;U7*ET<[?QHG,\[JO7)KCP^O5N83#]Z74 +M/CG&1O',?_?C&1LUH*KIY!.O'W.-V>C>R]0QH +MG1;) +MPN*9_1YGYW>L5\FW(Z5WHG0?_,6YT6]C<-IV2Y%QMA<))]O?RSU\+KT:@KGQ^JW:M]ZAM]K71^ET9)M/-W:6U*ZX2 +MW__UZ;PGYH5YLWMZMK;%^J[Z2GRRB_+H79\,BK-2>!";_ >Q^#6X;@3#BWEA +M5G0-Y\;O:*08V(M8E\OI9O02BRRSR4!<<2%4C0?F'\E$>E%YASJY1GFXFP_6 +MSW;H-3_YPN +M)PO_UB\:!7-'[Z5Z/KP\/#/IQHGI_-XO!PWQ:2I+/0^OBL50>GSN#7/S8ZW6 +MB[[?Q44X68Q/(K/P)I V&SAMU9;5TO7TWJ5#KV-Z>-1F'3;S\V,XN_U.3\M# +MNVM$'Y0SKF/"L\?_5)YW-I/=NET/TTOW[5Q>/:=;[9_DO3TW7XF-5'#\3B +MQH.\M)TGUL+AX7^1N^Z^W6[[W"_//M_7''C-%?_K\7>[K_Q?)0;F,OEY+U^K +MRJ&=ONUW2^E@]Q6^31:K1OO\//W.J.E6/&S%W2R __?O54_-\[5WOE$OG+>7 +M6J:PB&6#S71?O'@K:4)_]MV.S[[;]2OY7CCY#K4OE7G_7#T$MZMR)SJ^5]K3 +M:W^S/Q_:Y7YV6\Z77['#_JOFG@E[K_O5X[H;U\?/7.;RWAEXFNX-# +MO=3-W0JCZ.7:V [.R<5JE/CF/Z78*Y,*UQ_1I7X[[?6*HU8Q75[DF_/49]V/ +MS_A^#K5:\F4K%/X=!^Q]XW.42L\WC?;TMBO-3<;QOZGT;P]^JOMM& +M=Y_9_KK;]OZS-8N]/"YT"N-::-Q[-!:7\V-TG+;6FU]Y-*_$M_]\X.A4SDH]3Y/7^MK^3E^-_WV[K,]2\8O64T(M)54Y#2IO%*I27#0Z ;N#]5=XC"* +MMA^_X.0WC"?6I_R]U^I6\NG5)#_81I_?76H93WR*P;A9.-2.GQJ!C4ARGU$0 +MMD?I?JW?W[Z2F]LWO4],R_=S_9Z?CG*1_G)0?@[VZ?.Z\(BNDM';6&7\9W;_ +MQ*FZ&/5KE7$G$8_T;M55\)+/SM[_P%7I^]H^M:2'=N!F!0E?6=3?S\YMM8J_ +MHG51RO-IF1I.>N=JNYY^9@Z]V+JPZ/Z.V^YXN"_U_J=2_E3YK&;?4Z?8VP2& +MQN]3]=>)!L9FR:8N0E?T96#N.EN,$O='Z1@L)+>_[+30^)5NN_KMXR-]GD-+ +M;'IH=VY?6Y?'/-^ZY2?IS,T1:SA9FGVGL>5FZ#B>U^N@S?:R_Q>WJ(W:>2KOS.#+:GA^G<;@YV)[2_]_\ +M/]CO"M'?L=J=K8>313\93JU[Y46RFPASF4V$F[MLL%_[ +MY.+S5&@P_L9ZNW%AFXC,,YU9H7+)!N9$.L(A+=+'R][ZX3U[$NE&@Q&,OB'2 +M02YY Y-/9:7)8\_\[O]#Z70H/TEF&I_/HU2<3J[SQ:PS?DQ/_^W]7BV?6NW4 +MZW.=!F>KP/M]TK\VRL]P=)Q;=QWLCV?G.FB'@N?F+DJ(_(VE,0C'XUNWUBQT +M%O=N_';\O#K=PJG[V^W6E5#N?ZG8$Z?>+0_RPBY:B$OB/G+*]P,3[ +M6WRN&Z?!<=-9US^'#L?HA&^G'/: ^G\%I=74)KH*9 +M1/,3>76>Y>4QN$D4LX5JJ-)JGT[#6O>9:TS?FV_[9H":7>6W@_7MEU<9V^=, +M:1EL;V;O9NUX^J\ZZULZN=M7-LM&?5=3JROG5JU3["^*V?&X/54%?V9>S5NZ +M]DP.I @&1[UGLQUM;&:9]CEV"M_GS48]VGI61NE]);\8?ANK2:Z8V99GZWV^ +M'MY.'?/^8VG:#*FVAFMA$]^_7[K9I +M?M_-__"Z/L\/]_ OW7BD@T49^:UY+L]R.WUU,9*I>J&.0L/E9NMZ>Q4S'Z;_\7MOCF^*I55[UTL +M53;-SK;]ZD8NFW*\-OQ5*1!OE=&[M>^46Z5_^S\[C.SXC4RNU)E^"N]ZOI6N +M=WJ3QJ:_[>RKJ];^=QIOA^OPXOX<#.NG5+KTN,]?^U_T?0YU=LM756K//FZC +MP[D4_Y8RH>M]5HKD3O=3_?\I%%J9;G=?V*?JJ^AT=+^6'XO\X#JK=(_]='5S +MG-^&3HS%3J[9^0<&N^?QXU$_=UZOP?'7/'RRN5!\4LW7=O_-%RN][1V>+[6 YV_P?@_:\=8JO=JE\;9FN)B*G_6.3GWV]H7N9 +M^&!;JK^WC5-L?JW^ZMO^;+#0%[[CS\^J<2[TYO=A+Q_,G\N+Q>71Z&8;I<1O +M.GM\FO=ZK4E>;Q>Q[:JU6K1*Y=QEVLAGNBIC_CV-/XZUP^,=*$#=O]Y?AT[R +M4.@O"KD%D+2RX1)>MM/#=K";YHZG4*F\;8U'@>%[?Z!=?U;]Y_:.XT]OAYG= +M.-.+/D;S^2M^?^\OI?VI\CU])[GHZ'?+5)>A1S/WOC7>P>OWMQJ&%)+A^BO2 +MKX?#A?ET.4KOJO'E>K$_Q@;G[2WRJL5:\V/Q$POF&[_\)]ZJC,^59'@1[ :^ +MFMN(?/QX'"4BX>%_6OFU7]5\<#E1WNG"^U +M7N_\&P3^3^-1]S#5^SNAYZ <_Y^[]WOQE2@=QI%=N]B].*.NS/#KI]9PL_F- +MWO-X;3K>*Q(VFN%]8A"%R'9EYO5I51\N*\W*9+*/A):]RCY2^_7>C?UM%PKB +MU?T8EW\Z+,T3U=VW<>(?_I5R@8OI*O,+ +M?0^?N'KQ&=@.)R;;W&,0?AQWH? TT0OV0H5A\A(=S,89L]!Q/?9.%J-E,UDS(S_5P^AKK-J;)W2+3;00NTJ,0H+ 6SH>'\\_PN'PN +M\XE6;QCYG8OR_'8SL+%HM"*-1>44K=Q'K5=BG*&AG-YZ__LE,DRL(]-+,3M- +M)2ZQ06*X+(82H54CDI_U$Y[2?SM^_43#VRX8?+*SZT9#P>]J_&E'UQL8U,XQ +MG2M>B_E%KE1KS[ZQSF9<*\4SVT^JV3O$O/6QYS 2N;I1'08NH\UU=]\,[ ^? +ME4ENUIA.-^U<*E5,58['>&@8/GV7@;7A*)__92*-A]1^7KU'W67F,SQ(F-/_ +M:[!PV 2QL;G3B54G,GPUZ_?7X_$%3D]_U,;70.+_I-\ A.;&P^;\<#38^K]5 +M3]GPD@WZ.[R\GI^GH?OC2D$IM.4^%DJQ _*J$?U^5!YS[OGI;Q_;>?JY5J\?1XO4WD*I5?QU8Y +M#"WH^+W-\O*)).+U>6-V^-]W[UTLEVV?XM_XJ;2==:^-]O"^S>1#D>!G] H' +M-G*Y"%E4JSS,ER[KY&"=S&Z&IVSXL=IMXMW7\QM9<6.G4X?A]5]+E/NQ?SCT +MF54BVV^[D6T_AK7!2"<_[P26W^E<)^X@UQ+OC[E]X*D17Z;6OT+FN^VM]KG +M_%'YG*YNA?WS$3\]HXWGNI8L3%RQG^%A?%JU?*]4O1;/9P>N6RP:_B7]T^?]7$J5S[AM\"K3S +M3+JZND;JG>BS*H;[>8TOJ_2IM@CVM]_.@,W[#.YG[\3K]CXO$N'Y:7>;)IN= +M2F#BLA73*^F+[7:Y\5X&SZ5$=%$NW)KS6[K;6VZJT>5TCOW/E\ES9#G>[5+7 +MS.H3G?[NC7@^-;_7E-3GR[X:;VR?P>"F-NB-/_3>335?3[YKK^WCTOW61\'T +MO[*+S>>G2"]VS5='G5"V^C_VAXKV=*8X2_5#T7[FW0S,?A.]:2<[7[7RKUNU +M_G]DUNGNOY)?GR>?P[K2R!PNL\HQ?6NOIY]?I:+K3I9+@_$U,5^$AY??^O9> +MQ:KK??PW<6-_4C9CL%1?G8Z'5ZG9;XW.X\2V%6ZL!Y%PMVB83,2^^>:H6\GF +MUF.-N_?*]I;_TVB7^\]/Z5,YN1O5CIG.I]5-%.O16V17F*Y?YW7PF5UL!82O +MW.O<*Y5'B]0FUVX"AGNK<3*4+)R^W6TAL+F++6[QPGZ2F52JC_._%ECXK)Z; +M[V5^7Q^\]?5PHQJ];&N+^WZZN#5_O?&]G0A>>Z/OBM<$]UV9_Y(72?3 +M]>Z7/>[2ZWTQ,OR.$XO!_M2+-496P<%W,9I4B^WE^5INO%K)=KD=:QTZO6X\ +M$1@:3O,&VG+]N0]<+\JK=:A;Z*=2T56D=OMG;L[[*+V93U;IY2H?N3W39,GK +M^OO-_0O/6.32N(4VM="H5AH5L\UQ=SJN%LN/0,0ZESDT1C/I8&\=&G7>D4&E +MF2I$6LG?>-?)' :Q5G)43XYJCW3U=-RDQ^WR,=2-%V??Y;,\\R,.O^/M0)W\ +M-#@TG^TBS\A 9"26BXR=^"J>G"6JR:Q!G%SH/1P @- +M(A=_K#^I]NI<1D$?'(:C\?)SSOS*TY/SGJA]%^WPXIRX'4KGSK\T.]=[Z4+O +MD.G>RY6P,.J8E3_<1"^Y0SM7OVZGU\FQLCFJUI[D6S'[I-R +MXS:[ME?Y>#LTGSO6ZG2GS>9TD5J_KO]A.#H[3Y_MA?'R.EMV$TD!=29PD_F/EOW+K)6O +M3]JCZZ1SJSY#JHZL'-H9\;]Q$;SW";\ +MG@A$!]'K/UV&_5NM3[:O0N_SJ;=S#7&LV:U=C0W +M-I#.3.+[6@:'V7S\^OI<+OUT*AZI)&+S4F2^477/L^-$>OL5>WO;8'Z5/RTK +ML<^[F?>JY\'F<5,LKV*MQSJVWO1+DT3P7CAE'Z7__G%8?BJAWZ^>O'ZWUV)S +M-H@7.[O\52^8W,0^SH31R',0JA3;]^5D=9^$WZM)8YXMU'/OUR!?K 27P=>P +M/>O&EYWYC>\=1VK]:7CP"26/]X]T\#I^WPN[<\8QF3_^8IUD;;A_IFZO?#-3 +M75P_HTDMFKA$FYO/MCZ:O/[7SJ_3*^]R]7:6N5D;Q(M!"/U +M=?QP'+Q/AV\XF(O?)SC0GUSH?DA54L?T9M'X!-8&X\WSW=^'?NWQ/9Q=[0Y* +MZN_D^GB\*]GS//1]YF?UVKJ4+99?IW.B.3FL5O]COI]X;-Z)VKSPC\PC_\!R +M*7EHY4?%[4-E[,9J@_]GL%TG_]%S_I!^]U*;\W.[7A43H=XJEJUN+5=_;3GPULXO/N]U,I3MY_(NIY?*RR 4GG1C1O[E6AL#ZE8]6T;WP48O.Y#G]P>9=/K:^J3*\4[^ +M$ FMK\%#[U,J1ANA9[Y0G:R7]7HZ-"PF \^WW"HWGXX.LU7^]IE40\Z$M6PO +MU$SSVZD0@T5>1&O+27+=SKT.X?7M]-B%SZEBMW2[C(O!0:YZ +M/H>/PMY0L)WNB^'Q>)G^/C^W1:W6O@5SGU)- +M;*4,'NZO>\4QO=H./]GL1=$YB'QK[6W_L+>S5GO3^ZN\:_9>SWOI/1@W%J#V +M6WF7SVU&W5V^/'K\TCVQ]#*%U___ON9JX\/T-UT?Y_MW/]=XSL_;7:,: +M_#4^NU!VO7_/9Z'">%">O.LO*>1\0:CX3U9^N_(X5 M<--+%2R?5&Y^#QU.Q +MDKJU-HW!.5*]#Y//]+*2K5Y'NVSS5N-Z^7SN(6VGW9^86&GEV'_=-Z7')'>?SE.7].3J];5_TA'[EV_K-?G)?K37"5GP^3 +M]?5CE3[WYK+4G5Z_O]_6PK7GX74>=SBYG7A]<=H/2K%'>S*=Y9O=SWC\3M8# +M%_5Y+)4^#U_;K SJ*)30Z+^9P$FG&8VG]L?[L/A2P*P>F^M1Y#?+9P>U]&&4 +MRX^?Z=@_?KH.7JOM-ELZA'U1%_GG7ME_*/6FFI#30RH3B7>#P6JI,3U./X?& +M.>]*_G_G0XGY\-HM+8_/WK92/#;+G<'L/HD<=AU==_D:&?2KBV=Z\EE,$MGR +ML#.?_R+9;S5ZSW8^MTCND0U\M9/C92-:_[2.I4)D_(R7MNG>ZS\UX]Q>HN]I +M[O7*1J.A@4\T>7$=ZR,?\D*A4,@WQC5B<>1][M][WU;NE,F.0Y? 2WL0%I%& +MI\MA^EDO#KJ!L=]IY&\_2M*#^4+CT:T&YIMUB[U>O5RBJWYFT1'=\\U3N1+J +M!B]QMVAAU$W/%O? R#.TFO7RV7.L.JLT(ZE&,GG/]T>OAY#?,%P:9">O;X&U +MG\X^H_%U6(S_E=98_K7(A K=2[)RS#9;JU8_59RT>JW\[_:-CAO_YN"X] 6O +M;*Z%!'KPWSLNHZW#\7//2 ?F+Y-X\7(?C]Z_:?/^N0?G^?DG' E'<_7(.1_- +M9D;+<79=+E5;[\*M:!<^18.'^R*YS,:TRMW YK,7*>97X4=RTH^4$HO'^?X: +MQU_!M1SDL7"Y)\\FZ>&^L?^&6MO*4J(BBDB#P8Y%=3)?Q^+3BY;]U]6RX20J +MT>V4 E[6LNVNY^5IN)+Z'!.1P$&C]QW/$Y-7\O-,IY>'^ZA.L2Y_HUHK]:BD +MVO%%HQ?O?T:]K65_^T0CR>2DDU_W=M'9Y_>]E"+ET+#4[)9CC7KS-!O^[K7N +MH#O93E^K?+WZV'Z6E?9OVYB?O>I*J308'A+/VC/1:J6^^5!@-C7MOL>%7S'2 +M_NZ#U7SO&,G>^B$"_ZIZKW7>J<'^OJLV7[>(S+QO--/I\;"0+T8VX66U^0@\ +M-7^1^39:,BB6U\]PN?B>GR;CYOJ5C#VWO_-[U2KDRYMRTC,[KHSBT6VN=XS6 +MY]%O[C3)/Z;%77DR[J=&^7(X'5@-S[*;?S,RR(=^^TFR&1LGE^[\2?BL]X=_ +MJVZO=,O$K^_6H%>9]%+W[:Q<[^4*__-IG#C4UNU)O+--13;;:N%R+ ;GX\P@ +MV#Y&CR_S>Q*-MU:)>GI?M'5GQZ_,9_),A#_S1/BUCTP&\T7NO5]=%O%=KMM_ +MMXN!^>E\/RB?1ZW8P]RX2^TCR\Q":PXMKY7=H#KH[=^_268^+[1&QW7C,#OT +MLI'--Y$J)SJ%]6;0B._+M[L6:5C-F"W/(]UD[-&L%1NC93,<;34#%['][7=L +M3PJ[T:UXV;TKI=MO_1GV.MMC9!VJ-8V\PT9@QKJ\GQ^:QT%AT XF^KGY,OC) +M3Q>PL/O)]]Y!\;WYY7'$DUHY>:FLDL&*&&PZ?&VWI@M)TFZAVLB5$I'H)A9+ +MU9/,F 49^OT=_EM3ON97##UOP5OL\)[V7X."Y-#_S'NF]_!=^TK +M5@?[TV^V>C= /Y5B;PC"\;Y?:%V#Y<^IULY.H7%[M<(ND0OLY.*5TKQ<>@8; +M;NCAWB!\K%S6C\QW6*PBX2^CY5?JH%@'&>I\HY"^++77(UGH^SQ/9@[I2Z@2G>\JQ^E@VOA5Y]==ZSI.]LKK +M:(0#]G']#"[_5SV\>:;VK_4MZ_0A& +M9IO8=9)?O^NUVRH<^;:[K]S\=ELO X^)^OGU6=_RW4K\\7*=JY7C,-D,Q5J) +MU3,5KDZ"P]\B%OF/_ZO(/C\X1@^_V"46N*TE^NM*.MH>5WNM4N1;G'Q^!>]S +MD7F>6LEKI=D?38KU7+@<&!M5EI%QH?\+;.;2I7R8Q3VZ?MJ]WBFU7HH>,0$NFC'8+YT0*W4J]^U +M"6XU/@_NQ_-^!,ROZLS6OKM3JEY[B*#?QX79M).9-KN%>2X=6#S2J$?74.#X +M,EB5 T?#:>8:66P;UWQX%B^NPU;!6NJP#RR,_9&HU]H?N;!LSU[K7K 0#+:# +M$WTD(2/KCT0_$OY(/ENOEYO [NF_#X=CH00U:F9Z:->#J<%H=NM^*N?VOCQ/ +MR[T>91C$:7W_)]DZDWE]WY;A6>A,*!7/'X\C"Y +MG_*+R>+=*-3E7F[XZW^[GOSZR52N=X%2/TN3<*$9'726A5!SF1LVW^/O]GT? +MQM>SXVS4RW:OG\*T^*SU]W[MJ=6,1KK#S+X=+,<'W>9L79NDWL'1ZY=,SA*I +M9#0>[5RZD7/K'(P5,K]5(O";"^_Y?R,\B\7&[=PTF9N=? +M/)S,C&:YX3J1_+W[V93I7YW7ZI?,)#^JGG=^FZO!Y#^]*ZG""7IW)KWU>*Q_NU+C^.ZE3]'EZO$XG4Z-'Z)=N7]OX&4MZ'+ +M,U#OOP>FEL-XX'M8_/_BT=PBDE] *QW?:R>=C@2W]T$N,)'+_?>I^&[3+/TW +MH^WPQ54>?X>2I*?->)@8IG?O\CD^K^7>Y_:CWQJ4GOOIYA2??;K'3Z+\>,\N +MK\[^,9\E$[_Z>/.)O'OU[GH=\/(V&YOO;J/MJS(9[&J!A\RG<0QM_]U$.=8Y +M1U.%?&(RB,9JC]GM'#YTHM=5[!B??1_CY3HE,RN]]>*IM)_GFY-&;;29A8K# +MY2@S;-ZSP?6@6_I\ M^=1.5TC4XZ2V#I.K0Y)]_5=*WPE9D?U53YY]XO*\5WJ%N[WBI#$[OK:%;[$P[=_KXV Y +MMWT.7.#3CW;R/DV?@K]%:=MN[^+I6_-2B>PNQ_U3>'[,+KG*_]=>-/>#9?W_PW?OG-IH&Y_SOTF/1K\T ;ZF@L&;[UE]_%>)3.+Y?S +M7;24&D9#RV@G_WY7HHO)<)W_MX4'T,!F6TZ7WQ()T//M.'Y%U +M)#_?5U*Q3RIUS=[?\\-TGEZ46L5RV*ZM1/=*YN(D40G\-+*I].(6*XXSYZNW +M_K!-3FV3M5[IGSE"4?^;OW:C48P?TO-E>3U.!T?1P_W92I>6M>LJE?ECZINQ +M2&!IO^G)4J=#QWAXM)[_GZ%37@4\-PGW2L-_]YN>KG/MUG+?C?PW4)3__X%\ +M^@@&P[-M/G!>FC8$A.>!^'P_;,GGF<$?W&[6VT.F_S]D!M:3KS?OBW+ (KFS +ML\+2JU>ZF,HN#IK0E?AP,BI=\LO%^)YOO8*;S"28U@$_/'?U1W?:*)5RI^K^ +MG0H5.IO]IKY*WH?#8K&T^]2D")^S2?'U6@RTE:-N14FO4^6U04<>_ +M[6D>>.F&WI/]HG7;KW*KS:!\Z&UZ\S]W0^'Z +M-S 2"55CJ>&_UWL$BF1ONVAJ$_E-S\'@-W9.E6MQ7PBR)_O31>SRG>[;ST<_LLET+9S=]?;\>]73@?56,!9O-D/MVJ=Z +M7I5*EN+")+UM?SK?CMU7JH++^9\K283=26_"7OWRW,7LWM^?0OGIN_Q;U2BCR[18:F7:X +M]9W><$EGF]3[=3]'DOO=?=&I-0:M_. \&S0<[)?MIY8>RWN[I53DVLB\_OOL +M+/;+PX9SU_;U_ZJ5]OWW*;%?CE_10KA(*TR&/^%0_YFUS;\;U?THV@P,M\[= +M=!Z?9":Q>,]O[TG_GESV%[ON,7E)Y%;OP&+X\)FGHOMA.9Y]7?ZKO?/^?_TW +M[WTUE^^,OH/6:]7K;6K7UV.]VT=KW7)Q_VNONIE+;UIOK^.W3.1XC,;C*(B/ +MUVC;48\.MME]=_'XE!>-9S]8.;;NE^;KG[Q'NY]T+EU9QTO=W1[;7/W7WYU( +MX_1=#+KE\NA?SNC]@TU['NUE)_?[>AG)GN*?Y_HSVR_*M=WU]MWT+H-^X"B: +M"_PL ^_%\*5;[@26_NE^[;\._KSUQ72PFKZW:[5:)217[KRV[>=Y4)T?*IU@ +M"AF[V7TN J_=.DOQ-KHTNL59<13:YRO=Y-PQ70J/AZ+ZU+\X3J;>F_7P&9_E +MNI%-)[JZA72I7YWM);.YG#N;QWH3W;\W_6#NU!@=AKN]?ILHM]O%7+?3[&=6 +MHT8F6RVMW_O1:A1]'?OI\KU#; T'PZUD_[K>Y$Y(_7F^B'8&Q^-_+&BMU;:_ +M^:M9Z?1+S_EB^W[W6]MW,QZ8+8129O#/3_MR3>3Z5?_R;=TZ/V] [6D]K2V' +MP8*E.-J:57JQZ*:[F'=6X6FJMBO5YHW>?M11!H_>UO]BL1(];NJQZ@;U#@8G +MHYMHQRK][*QQ*YS.U\OBNXN,OIE% +MJ=_:U_O]TFFU;FQIC:?2:W:Z3G:UPTW97\K=6N'+[+?Z9_JE3&U^W$:+Z>@U +M-KEE%I5,*WP:58*K8O#Y378_F=A_>PWOTI#^WV[,WXNNSEQ+=WZ+1&'VR^T$OU^KS].QV"A^!Z=%NO^,Q9?[&;3TNY^W3W:GVEX\3L%K_W9]Y?[ +M+KSJ4^97ZV9#SGLWU%K_YZ]TZGB(-0^AQ'_C&TB +MK64Y<^\U,(*!UW.PY+#V_(39S6!06WR[X7YF-O]=F^-_-JR7KA<&HU!1V#D[ +MAXJK?&F1*F67X>$N,-3,9$.ATOQ<&OD6)_-AJ%HMI&_[;RGILO6D%9AZU +MU/B?IV1_ZL<8MG4^B:?FH>-D<2[OD[OJJUT_3O/[WC3;&V33[:A0\?%.4"L' +MC^RB7VUYA+^]SQ]#G!M5S[/0-K[I'M+/?>'>6\;F^^SCMHQ?NK_/NCZ)[ZZF +MXRE8R$ZWW\L/A^'WOQ4<;8^Q?#A6 +MR->E87_IL05I[)=;!4[/N_YL'LZVTYW,-3>-UD;]WVO>Z^UJA7]O.-YFQL]C +M*+#X#$PF/MG=4=T9GW[3 NTF\-^JQ$Z]ZF34?&VU9RG.P7AF-&Q.>SV0N5,Y.G@36<&8\6N7Q^/-R=+KO9XW-[KM=^JVIBOUY.MV=M[KEQ/67[_>XH7YB5LO5(Q-SX#YR?QOUY-_U(/Q:I +MPWMH7#S9XZ^GTR6_5/ +ML4=TO+E7C.?(?SCX)&??UV)7K&QJL*N,MIA]?%+Y82EP^OV5 U?W2Z;^3!V] +MV*EE6SUZS56:R]_LLUQ'^H=Q]-D_Y8JQ]7>=!F=O&J=-/3O\3-O/Y3!Z;'V> +M4^IH[;;4)+_6]N=0Y%\JW6;U]RQ;[JE@O\.]=C44SMUKK5N\NDLECZ'WM5;^ +MCZ;SY3Y;6>\B^<\[\M4D7_9JR] _5%PODN7&+_5N7E+GZF#U?7='ZMG<*/&> +M'(N/7O@^NCX2D>&APA _KV.C2[5GK:U7)L-P.G%+[LJUPNP\[ <7W].U,EGV +M(]\+ '_ZN-Z#T4C].2Q7$I_G8#0.U2.M\Z1;[DH'TX7^>G9KK+KMS**6.N]W +ML5R^=UEO4N7^99-?E4N)7CD16BYN]5W#>IZOQ\51OO68-^I1X[5Y2[1R^5WZ +M$WN'VK'$^;$8%9?AW.0;^B5[D=)_7.@F=]':]EO+1CKY56HV_!3M E)+JQ?P +M-5,Z\NJ]3LU_\&(7?#SM H"D@SN]@*_7*[U@-W@(+-D%5[7 8##]CX^.CT=[ +M,V[/@XWJIH&&G?_?FY_5+A*]3N\G6>K 8VW7I?48/K41AXEAI7+9C8(G%4:U;Y( +M]G-9)H*Y?JRX*(1^RW4-XIP6$]/"OC[=W*;+6N&57#/'-^>I%6GR^M_US_GT +M]#Y][O->[,1NVDUOH[%9/S 43'([Y]?W:AS,+C+'S#/Z3"V/Z6(F9'B&LO'Q +M<):Y/#+M:O;S[>U[BG8,_2C=C&[SV<2I,YR6!_?N-%8:I.;9ZVT>?,RZH\K_ +MD1M]VYO->#Y*)A/G?Z/5[&1:Q;L'^2&WW\8^E7_[D,\=#I=5L!,I?\ZGS.8X +M_J6:RWLV>BPE&[-^K+(O15^QJ C_NWK+=J'S\U$\.?IUP[!8^!FYGXWIL +MLHF-^[M;;'=N-K['Q>7UZ/T"=Z_\Y/)/'7^9:ZLTCBS2N5;V(,_O9Q??R3Z6 +MG"3*S^M*WIHH]#OM]N_46Z(0=D:5>WG3NTZSX_MEW8\<)HGS)[]=[E*C>U$G +M_SP<7\?#H3Y*A9N/1J4RG%<=[)5V/5]M]M[#2RNXVS7VO5@HU8_&ZYG(*!21 +M@_W,FJF[1K]XMP?5H'PUFRQE]I-)8SSZR+?S;W=5KA1PRM7OM;K/=FN+43C^ +MRB6:U6IWV]TU-_6ZZUSI7FJW_:2UJ'^2R]9O7IU.$_WZ(+N?K._I8.42:O<6 +MB=KZE^QL+I/VKCL;?>J36B<^KNDHC\=T/APXB#3ST=6D6KE-_I7SN-A?A4X- +M/N;^NFA_!Q[CI_@-UC:W0T^Y_92?Y78AN_>J@[=X^/>O_M:Y[JH8[Y;:F\MP +M$#AIUK^UP$)EUCF5ZF,]:Z+T_46#Q_*H8&_]_=:'8V0C,^\G:M%(>!0;%4B$ +MT6(C<-T(7N;-WW:N_%#V.5N_T7I)TXQ,\ +MQTJU?2E1*1>C@UULE,N4WM5;/)_,9__I7S4/%7^&.\ER;!1M#0LPD,=B>G=. +M;/Q:*>GKV]Z><\/IIUII!(K9J&-]+F9?/2:]XO% ,+\%?O,<46H7LR%_8C9; +M?\SSG>#!U5M\W3;Q_Z62GBXOWUFE(\ZM-JSA4[?'JA=O5/;CRF*5BY5RBWLQ +MFLC.4I?OKGS?7G?/24[#T4KF?+IO&YOHIU=3CX[V_>0AV#E?FN%5X7IY +M%(!QQ_76;QC,1*NMS>Y77E?;^51:&V]0J*)*MEZ_SZW_>6,5>V^V/A724&GUD@LM3AJIN)D;/5"@W"/U> +MM7WP$5G]ZXEUL)1OEZ?54=*W6(O'#C]JW%ODDLFV*OO_J;\MCQJ,TLDC-*@T +MG*#7ZO_Q4UWU%A[9W>]];1U:C]+(%'?P;@26O/&WK7[F4>]] M.C_2!3^97Z +MR6,_^Z?*=_J9SK:# +M5:??.>2J$V[^>QOK7&J]3W7<*T4*^6JM-O]>MH_&9M8+_QZ=MK WNIF^NY%V +M)/#_BS02YWA]_OGDA^-4:#-8A3?-S_DP:L_WK]X_-!BTP[MV/!**;S^[5F8? +MT6\KP?D@'=LO [>E]+NWJI1FM>O^NX^:K*O9970I'0.OKTSJ.>P*4\[WL>4& +MZ-V5PJGDQ/L[&\+Z4/I-?H>SX/PH3IL_L*#\K[=2VS+E5MS-1JN +M(H&;:7FVG"U.N72J%LW_G7P3_=!8&O_Z"=5>VWW@L9HX)KN_Q3CXO[SGI>0\ +M%<\N-IOY"8<\W$PF3OMN[+DX_NOQH>G8'/]>B^@FM_H>9]%?6$) 1=;MXS.5 +MZQ02JY:$X#38D1!0PEX+@4H(\%D)@<_3J^DJ<+;[?T/%:KB7_K#1D[=[M%4: +M[#[1FM[?&1PVO^]Z.8K59MW7=-1;>VGGU44Q6SU%+\7RH)/I56*W_C<3#44* +MD4LD\#2OW=K;REJ.^#%I)!++=RZ86!]"F<9U+63$;^?>S +MT=5NO/FGHI%A_Z'3UB*M]'[>T#,/,]' 8V%>FI=B\_?YF$X&#J_I92V5;P\C +MZ]?U-JR?Y\WW(AK<1RK97S=>^$_[IN#S=W'MO/>*W>>M65\D[I/+X#Y[-8;E +M,1-N:5O7+4]'XV)FGJQNSZW?-]U<]:NK:'=4##]:V6PP:O\'QJ;1^+EQ&'52 +MU=AR$#YM=K=D^Y^(_8:%^.\U/%6RHV^GUC]-DOU,(Y'JA9K-V3.9O+S+=O%Y +MI1R]=8?3^WD7N*N4+^WO=S\JU9#CJW&Z?1RD)K'I=I\*KP[MQ+1=J5;R(4_^ +MIQ$,3ZW+[=_@&KT.(CVT\=1\W_S&T?K2+]52GQ\'>;!WR>1NU^[N4HOOJL+" +MZ.<>*]^;ETPSK\Q,!UOOQ_N06S1/Y78N-Q_GLIU]>%OFW:?U0R84[LWJNWXW +MTDIELZ/>H]R]YT.KQN8[^G0^\O%^J/)OL*?;I=R2 #N2RZ=&E]XF^6B,IX_ +M2[Z5SZ=2]^&M59M$"Y7(/3_^&87_N>/Z)L^[@G+7[O="NYL[Y3:SV#,WR.SN +MNT/FOH\%UD)D]$WK,,LUKL]RJ[0X*=A7IU%V57D:)A/)_"F>GC9/\WVT6<-/ +M5MKM5NM22.Y6_VJ^^2[LTK?WK]6+AKL$KR4WG1\M2+R=?MZ$\O#K3!?+1O7^ +MB_9SIU\[]KG,;N]4?7O*'2+O:NF^7 0>#[/0\K=-3U*;U'%Z&9X'NUOUOG$G +M7K:6EVT_E*TMYYU+:O]J5C/MZ",\3GZKYW6OU9\L,Z5S9_'OMA/AZ&;1[$[* +MN5.X[8K\U'4+LZ78]\SVF*Z<=L=IL]A?#K^5Q+S="WO5^ +MS_R'@?EG:'T\_C;]Q]#[W)WNS7GE6CV$+]''8];^[->W>S?5.V?+8ME@;OVX +M7W^]W_N&-,PV;MEK^[8?)6/+V$U+.R]-QJ/8L!&,KN]:8?K<)0K_\SS^ +MRD>^U]*VU-U4PT-__J(1#?SE5XW1>#OJM481H6+B,BS]:X_[,;R-+DHYX^#K +MFTQD\BF/,5KM]J/SP;][R7ZKC5%Y]6KTPH7S]7<=_/OED6%RV(W]:]GMZ-%< +M!=NU2GX6KKWSM4RF,#XO:_U-Z='[MK;YPS[R'#=^MT%*T1Z./2+!PR)Y,@N/ +M;/MZ9\J>'X63Y7\[,KI?^]]JNK-(1?+19/_R_/T/T?*@WAK3@4_[KWYF',_& +M^[F;=?EQSQ7;V4EPWAK$.JO@OOB9Y[ZO9:_].M:VS>%V] Y?TL7V+']:=@OI +MS&>9FF9CEUD\?MDT E[^-H*/S+R;2']-AN# Q +M'0#F3 ==FPXOIF.T'>Z/EX5![S[YI^KCWR.3<7'Z.AN]3*,Z7=>2M\/AFRYL +MHI5X>A26&+L=;\Y"K5^T\%F'TK]S9]IYOG;5PRY02KDJ9,K)4>39ZD3+U6Y[ +M4AT.F[;*X7\VI]?S?>W +MMFV'1IGZXKG/ON,-17OJTK]-3Y=1?;&+#^>%RI'_C@>J1O/%6_N<+O['0Z7R +M=K!(%;^76B28FV[ZPSYM'>SH*!?3PJAX+M2*_>WD4:T-6NU-K7!>SF('O'AQ +M6^G,X8S=S&BZ_[6^Z>9\ZM%;+T^+YNY4:JO)5]?J[;=S)OS\U\]- +MKW[MW:G0?\%/;UF;=I>50[,36J5Z]>.Y/8N>KZ=%K5>>'?NK>"4]3(0CR__B +M_K&+_\KE17W[KM5^P\PZ-RU4-O=7_E0B[L^7W#:Z&M2JR[@\>OY,/U<>3^3@;=V_M@;)$O?7FZ>J+]J +MS5#C]5_=KL?G:/:JX_[XOZ +M\O[I];+)];W13L_6E\7Q4"G]/Y/4;5-)1^X]56[W=@CG$VNK8'H\R)=.DC83(=>)S'C]U*<5Q-M\+5I%>O%7I-E^.UO +M31ZZT^@UE^STGXY]8L]X^G1XI+KWT>00#,R3U: !&>&<-R"/')K)7*1F0/;8<=<@ +M EXV(*,O[AHKK]?I8BL;W R'HV+I5,UEOO];^IM(O8/M=&M_J >N_]]:(:VC +MK*WSA7YW&?QL9Y?(J9R,3GW9Z]]T/=Q<)\]T9'B*YN/C^G)YVE1*KV NM^K9 +M6^__]62I,C9BI]=]4]]LP D3M=+DGM[G-\-:]SO.'KN-A4[?8_'MO["87G.%Z",Y.DS"SY^(//I(C][OU^.S +M+=6^W6VK-&RTI]]GN;,)Y1[)YGN=N+GG.EKC*J5>T.C[/1J'OLVKP:]>ET[":&<]ZQ_$KO!U^4O5D +M;[H^YE_K^N^QJ*^RZ](PW:__C_5S//9NYJ;92[A8+P_WX5-=)]_.]^Z7P6)M +M&K_?C_W;?SS+/?:S_*_Q6]46[=DLE<_<9HW?O_6)9H[GSN<7ZX5+N<)RLQ7) +M3OZ?<^-USS'WIU=\5OPNGI]<:S0(?^*7Q" 2+'YWG=(MV8^D8[78.[;,3%/= +M0A9C/^M]AX_8*;#^'YY7^^:A5>D/0M/0ZQK[]:^_^#'[JC6"D?*C^]TOU^G2 +M-9/;=;/=3*^Z+3W"-?5H-U.:7NN1S^!32A3OR7/P7!I_!O?.87B9)*/!S"ZS +MSI='\]EZ=RM_0LM:-_](5#JU7^ UW]4J8RAWOUOM5UT%O\U::W-:G?ZS5G#3 +MZR9NL49@XG@)SG;K97@6VA]#1K#G\78[ZH3>ZZE7O:E\OH]<>WAM-]^[VBJ9 +M:?13L_ I5$P$\_UPO_-I5&_YXS7PUYH/IY/4O3QLQ8/1P_YY2XCEL\D^ZW//?>]1(.O_BI:399:W62^,%^OKNW[+IX)5S*+:;71#1W&AA$J +M8Q@9CN6*B=*5XP_&@AL)K(H1HF$$53",^#*]V6Q"W<.?2UC,K#^1B+"WN-Y? +MAK/BO'7A^N[JX/J^97JT=&)ANC1/E7RWP\4DF"]%D))&\ +M^#-=YUPK74T-]G>P__L+7NNO8+'P/.W?DW/WD\^TAM/2]9$)IK*!WWFX&!]M +M4[%(Q1DS]&MYU=MI(ONLS=O[U_/8O!I[E_?K('\(5FK-6V8;2DQ*T0&!<=&? +MC2[Y>/B#J PL-E:O?+IN ;F*96>;66566HS*U??Z&M%.MIL8XND^L#2.QJ/# +M;FO:S<77O=6VE#BLWI_]:%>9UX.KET9_G(]VXUHN\SZUQI?Z=C=MQ5.][_SZ +M*CQ&LVEW5JB7*Y=2NW-_DJ(NXOW+.-$*/T*G]VDDM9BEZ_\0B]V6I6 G-Z[]B*)&.K&+'_\UG_=5P,OO?N"D +M\+N?6KWZ8US7I <;[6OD,:B//_7_X'*OG@;U]V"VR T.M=QQ<'EWS?6+8.*= +MVM]-8.;VO_9^G9GO6^U+N;=*/K>3LS)[O]V_/ION\;&-53*'8;=(03B?U-Z[ +MZ2G7W0V"H8=5,--O=FOIUJ!:_;22@=E99%2N!T:RQT%]6.^D0YO4XQ%KW:(+ +M+_Q2:'B.OS:'Q^EI/:IGZJYON!V_)\%=DU +MC\_:-IT[Q6/CW'TV;^?_M4SNE5__-\&?C/QQZD7FP?MXO5CU9[G7ZI%NGC+[ +MWJ_;?H5^Y\>N$.KW!OMU=_WX_:_'U'=RC"36V=&RVDZHW97HN58[?)>_SF2C +M\Q_FD5>B&PQ,QF9_2 QRF<=S/'CO"]59]38-O:.=TND^',V#03_A(CI9 +M-5?)6F%;7+6:B^\Z'\[7\JG<;=1L!BZ6R^LW7/FNNM?&X7$>-M:1PV9UR12" +ME<"6!]GTKU63U?G17NU[KL@DW/K9SVV+O\\PAPL=/E=!T +M&9H5EY7_,)&]5N/)R7":7HRB\7WJ- H6(M=D0M6Y+9="B]XC)@%NUK8KVT;U +M/:HF$Z-D.W!4G*^ZY4FREMR$JJE$8"+Y2K>+Q\JE&CKNKA&!-EJ..28#2^U8 +M>=I;5RJS>*U]_@9^@M=$YIX_WV^I4OQ4&VXJ]TLQUK@.V5!WQWAE$USWI?9S +M:[B(7Y>E0[90;-^,H[_DLW9=5!+3^F!YNM6NUW@D5=YGDI'?YYA\E4OO67@[ +M6BX7V;]C^CT,G?>M="3T#1>JI74X$9UWGM],(I+)YY_Y4_(SB=Y^M."[ES9] +M,!E%SMM7O/=?)Y-SPV1GM]WGRJ]79Q,X'^YW@_/PFJ^D&M$<'65J?*XGKQ,& +M;B9TB+RFPVJQ_;D4>_U^,3WGP);G![_ _,H087U',[_C9''/+$#G93K<[:?_ +MB<5]U*ADZLWVG7H_A$FSW\T_/[N#5_7YS_V_DT'VGN^=EM'IXAQXFL8W +M^UBJN'VE#Y=1;3^Y=];MY2%[Z+5G]07^'UC,LV,ZI@?;YCO6K UVW>:E7QV^ +M3J/6_Y_?U][K1KZ\'<8>U7%P%!_]RK%MA='>=:HWB?GG<9FU[/]7T.G#J'6.3XJ9 +MR"-AXJ9P/QI$;LT5M5SN5-.;^O[7"=^K"36ZWB\ML^7)^'* +M([YXMM[]\:#X"$_"Z9D0_FK?V\\/I77O5"KL;H=XJ3JI'0[K>C*?>7U_C_*Z +M%$PT;\?PX3\/__/?>^,4^NYZ,H3GK7Q\5QA?9IU%_+P?G'^Q9_,S:;4>]6(A +M6W\&+]=>Z)*M%H.A\'V]B=PRZ?Q]DO]D!_M:IU-L^0E9U=U+YMBN_#[+7[0> +M&D9'L4?ED;W?Y]GM\[:MGYN)\+^9RFQKD='Q6-BG8]7\.O);MPX:?;P1[%P: +M[VOF\5-*G"1G^^[MW:?9&TTHK+PWS>$GU.\6 +M[Y=%.GAZCFO&ZN!^&KZ>OZ?&^1L\76^576;Y#1;_I5?O&EZ="K-&O/C_I)?1 +M>^)POO>6FV[M=0S<37/%:,K];6R87L].QUXRN$ZELLY8,7"5&X4;=A'+Q276JY5^C>$YFS_U(]G=_]A^W +MTC?[F,S#SY5PW OE=EZ!UW"D6&W>*K'E)+Z/-&:APER@H@HR?%'85&UW[68<"?Q_& 0% +M*L"?N"*!5,%U)/!].!P+)6+)7O 6K,YFF4KW/M_7=I]?]5!;E6NU_B71BY8Z +M]>Y\VVM&0NU,]'=X*JV%\2QR?SY/Q^$PD2R=ILW2@J2-+6J[7G^S?-Q>X]6N +MF/BMSN_QM3'OYP:3^7%0&L^"D[3KG'O4-Y'4\O:(U>*Y9W%\<1 .C\? <_[^ +MS1VGM>LP6<]&FNOP\I#(;\:1]J307"8[H_IF*2-/W+:=N)XJ'-J3VS]4FK8FX\L@WAKV7)B. +M[&TF/4TLML=*LA JXK?UWJ\3;_T.E_JODE;+ILJ!LVGPN\=8:5+O[>JGPCL:V-Y&%D5M=G):R_1WVW0X41LL$M5TM?=-'.[?V:Y] +M2U2VF\KF7TU^9JW$M12+%G?19&.2"(@-D[7B^%9(C1NK^_/Q/*2ZSTJ]44O'\\/YMG6I/Q.+^ZBY-5T_B#W +MYDNZQ*%4[5M)/;.76+-UJMPCP6=Z^)^'>O7&:)ZMBK3,*]_+SV'S\^NBWOUHY.)O'6OU:)S]K]_NYV>H0NQXWO]KA&AGG'N/P +M*R0D_+5?_]PIW_CW6X/^X;5);>X]!]M?>U7?M@_5TO,Z6%6V W3R0;0]W\4JM-Q;3[Z.5 +M?J3O3D8H>\ -',:ST7[R+YU[J)CGA!=;/4=(J.=\NEY--Y'N.6^',9+?;BC2 +MP<8]^9@HK[=.\-;5&)Z3,&#'U[C[W;["GRL Y/'S*AS:#6?JV E^SA<3_713P'C>KNZK=*O +M;B#1(;M:3[[)83O['Q<.\4BU?*I]=*3B*34[I;?:7 +M&6:FF6/U68@T]TKKJ#L=?P^A>F&6BVVNG6"C4*J^#SV7O1!-Y]^3UZCSYDJG +MPZ?L+/<-/O>CT^G^2F;6UY;,=/O_C9>^0ND>JE_^[^UW/X_5%9O4)##>B +MC_7V?CC>QYGZ/7*\K R1E^'->?+*E*]^[7(RF-2#CU,J>.BN\\%I9,N#TC'X.[2OAW+W?Y>E#D9JM^/[EAZ^"I%L +M8],^WENK7/<>>:POM\]]N6^7\S[*<.??K:=>W7BOE4_72K'!H]FXR=(_K?)_ +M-;QT,LOSZ;TIOVN5S&P4C-]ZG_YGNIT?'N_9Y-0NOV[#6S,=O8=:MU>TO E\ +M-WI!;?8S\>Y-VKU;:;QZ=9;Y=6.0SUQ3S7G@X_E:CN;S=&K3KDRKE=8F';T. +M Y.[^.1?/B?M]/FT;_$RG!]FA6QC5$OC(L]BM^:J5F_/&H57X//RC<='G?KY +M//@^8HNC??#??RZZ#-C99K\\5ADSC?CT'@[]9I/2N]:LA/^;>+)S*MZ?/MQ@ +M+G6K19?[5HT8\97I7(K1[?[^&,_2M>XN(;5_DMG/KER-70?5068AV#_[\4CZ +MN"@-0OM^;=#9QE6=DVEUMQN5E\/"_59+A=.UVOM8[LO,H_%G$L[F^LG%YM3_ +MQ:?[Z2VR:\1OM<)UW[N=QLG7]72;E0O/<;0?JI4J^W^\V+DEP\US49)T$"Y$ +MEK/_KUT( T#/<_'A.AFJOR\TB-M"Z)1NSYJ/<#:VGIU*N>NXNMSV,\]U^];I +M%=O:[.XPLEL6#__B-?BIO,/9UJ94/OR73/Q>9+-H+8N3X#4P[EV3P_9@T"KUK8IL-7N;SZNI4^?57 +ME>2IUA].&X-XH]M^3W/]<#MQTZZ+A^Z\]&B-KLG=?O_M#W[U_&,6V&OF?NG3 +M_9)[[N/OS3'Z;N_F@U0J%_V%SJ/;I%=9SG9[@?;2'4R?QW3ZDJV],L-V9A2L +M'K>QR3T4+54#M^%;[)(\M2O-^>A;"[WND=.M-PN,A@*+U;"#;6@;34R6I\CK +ML'Y/CKE_;M)*Y3;-]QU?3 M9J'6SU^YE5A\D3]'J\QG=:A]]B^UL +MHQ^II!N7<*'\_S8*_.BG?N*7W+[>W>2T=,RW;I/A?%J+CN?'Q&\^>IW.K6/@ +M/+9N=Q62KW$WGZF?LY4RY_X;-\O1T;U\Z0V?0JB3XC)^2;5SI6MJG)L''BNU +M826V._8CQWMGTTQ([<7K;9F+EC/W^.732F0JO]EQ'3Z*Z^8HE,^??]'X+EWI'N:/8OZE=C_OKU#R]KJ$A\WSOCU<]@OGP72Z2V>" +M@>%4)C6-O,.A47TWOC0#?S8&ZB=VZAB>3J?*>53 +MTNZM+]A=]\O3T"7U*<9*R\PS,WC%)K'Z(58(OI.O[#@X+556A^5HF]_-IXU+ +M\'?M)??G?NF^_C1%*;OM8F98K(0/Z7NQW#]N#O_OM=4=GG+92[;Y;=9WS6?X +M,.Y'"H''\RIP.BC=+_%4JIF=OTJVRE]\7HTO--/CU[F3J2Y2F_6@M4JUTLG0 +M]_7>W\/QYCI=" 4FS^G X;4?+KPGD5?S-0[\G-2CQ5?A5IC&:J7O,7<:ER/M +MC8_Z6"D$1O^)T34?7SYSL\!D+Y6>W@?Q=+FTZ1A@3Q.K3N:O[.^MZOW%I/OK +M'5>]]GG^3G7?^=!G5GS':O5M]?5+WA/GWF%Z^6V+X=AV?[Z*8I2 +M)C&1HX7P>CTN1$;;928^_+9S@T%^=.JTQ[W0M5ZK'H?5?OB8&C9K@;5#)A7- +M7"N]T?UZN8KIT[U$Z%B,%Z)E!LC(<"JPYD[/^W#=>12BT]_JUEK/E]5WJM++ +M5OS/[&Q^S;>7_\(UYN(L53]@VL\[$?A_W U15Y5/._M*)7:Q??>4BLTK[P5: +MO#V/UEN562M57MYGO],XU1Z4*Y9]NMW_ETKY?JGY[X;.B=;HG:*C/DQ_I\#* +M:KNIW1.9U"Z?2&:JM\DMO;BU@L=Y>?P\;-HMQW2JT/^FNKOJJ_@-OL+5X.=2 +MF0SSM]MYNYY&*QURU/NWNLJUMY/1H/G^KZ8^:XL,,EY;6Y &0Z?V)S/]C][? +MPJN[[SQ>S7WU'TR4(K'X)W+.GI;A2G ]K*UWUT$TF4XV^_O7+OK=,G)_%J3C +M.+>UVCSU:X7WMW6,]A[[;7O1>U:F]?GM=RET#I]Z,71_ED[_SZTW*$_?D>OT +M]MD.3MKLYB:PWGR7[JW2Z9&HQS:322-=&T__JWAFN&GB!UO1^G=2R)U;[M+> +M>+:RDU_\/$Z-T/5SSS>7\><^EQ]WWZ=A,9W.KCMB9RL;BU>2B>_;''FS_M66Q]?] +MZ(Z\++V'V5,K<@I-I^'N)Q'9!G^=0:3AOVE/S4+?W_4^&.TWGJMF +MX_/L%W?A[?/[ZO7&S7CMWXH_LOG8H9L9=$*5R7GQO+9"E\/P<[H'EW7UZ#MS +M^T0JI>/M%_G<$^WXH?G4^E_TRFX^G/[!3,ST[3P^U3OF3^ +MW^+2_=U\OIO8,-@O'P[5QZ1^V=1OI>*CUNW=?Y/.ZK2MSWZ?]JBZGN0>P?[A +M?_VO+K?XLYV+7M=._GU\.JF6^]=K_ET:?5K;<2HX'*TCF^+T5>C>J5CX<[__W +MP?I]M!@!D,_6KV.L^V]V!L?3]=D\S!;%V*:[-@L??X/3/CK/Q#.I[3K[2,]W +MO>PU4ZWL!MO&_YY<7 _S>7'\/J]VNW[Z\:D>"^W]*-N=QE8_A60T.?MZ_O/; +M<]9JS[ZIRR=[JUVFT7_P_9L_,]_8;E!Z1%:=_W"F32_\CKUP-W>/C/:+J!,S +M=NA/M_7_^%OI6-/;PW_DGXNMGO=#HKR:%OKIS3Y;?HRCB\OT,1F\FXG!<7,/ +M="Z>5C>1[.1^Z!SQF(]4/?-M;T/903#VN1].P=UU\4S-ZZ].Z5EK?)J5]: Q +M#*;>_=#L^*W_?J-Q3U,I +M9]]SJ94Z/6SUM48BFNT$=]UGI5HHEDKW\O78\FM'V5+V>SQ5V\O0X]QI=?_I +M:'?) 9^,]6_]\+8\V1:?GT=WG?Q,H[M1NW%Z!5;'XT[",NDGW(^+Y]3CO!LU +MDL%=]O$+QA_W2B1]619/O<+[66XGBO/_+G>^I._5Z?%?N?R/^V+M7_@D9Y[2 +M3_%>[OYVD57^6?D$5J[4>^/3KX_RRU.WD8O54I5Z]CB,YB;3>'!]V,9.CW&I +M]ED].X_#4NP\7W+!V^B7:<4:C1PTYA4#I=;<[^[;QZK;V^HZ[[,+_O:9_DN?HJA6.7; +MJ*^[V^Z_]TU^HJWYJG73GJT[\_FR%;TD%]UWNYGH9X/&ZFZU^PP< +MEXN3<+>[:,]Z__\[XL_L5A??-PT_/Z[_6NE_,5-M'Q_]R:PZ7,[*]]]J^U@' +M=\;+;;76B*<6X\Y@5@Y'?M5W)=TJ_3K31KYU:CR*K_CX]1Y-DIE^+IZ8Q(J1 +M]&-0["\^^<-?[\^^\KO!<1#X3A22OZ6;_G+I+B+AU/O271W;@^+VM^\W/_7N +M[]K9;NXDS%+L&\\.3[%O,>#E>^]?:YT6D4+[_GQ?52[I;*$5C@TMU,@QLQD:+FMB9B^]V@:5BLQ3>#W_I7+JW,+HO +M_?)HTW[FX_/DH?H]'O?7;6Z4+UUJ\=.F'1O5O]G1,+CPJL>Y\;Q1?R=3O=!" +MW!DG=,*=^[XSV>X/*T6F=AV(-??: +MA6UW$IHW#I=J>M$-]8:M;#FP-RF5BY]NXQ7MYS[?2"=;C=9ZX=YDG5BV*BIW +MQ(.\&+PG8]%K][PXO-Z=KKXW&\#VJ=T#\P<=Q\*M___\"O^0C>WO-M/G)L;-:;^,!>LR)) +M*N&>&?S![6:]/63Z_T-FX*[Q]>9]<7%9)'^V@K/QJEG.9C*#76!@,7,;S21) +MUY?EZ43+'(4+NWAL<%N<^W:$Z],J6$^5H[G<^3IO=G:KXK[3*+R/Q7DU3T0< +M?W?BA9OY':S=]^%,/KEUI#]#M\3FL^DUX^'K9O' +M5Z5^IMU:72-G'\@]-N>.KE;.!HL)5X]FX7.*:F%&]M-3^9U_-5*75'@:/Q<[D66W5%J\;[W2 +M\?D.7A:O6?B5S@4^Z^F)D;<>GRQ?_^P_N[G71+25Z_MPJ_8WK=URT>PU-IOZ +M?!:_?6_[[:)\J"^CG]XR>(M_#IMK]6(Z1K>7Z_85[ WSA]6E/P]NM=3ISV;R +MKCT/GT]\OQGACI/Q.S+,+3,;A&CH'M^&OMM>_.3B7 <6%HG3,9Y;)).15B-S +M+$Y&VU#)/CWB9X\3P]%J$60!7T:CV60SY#XJ,\;RWW-&0/CJK#^-8"TLC]V? +M%_.I-+2T$5^\:4DOG6:P%.TO;N?U+MY]_?;7R^D5?%[>H\^C4BML+/M/+S43>6YJ7W%&LG4N'<= +ME KI=*YU&43LXI4U8#"^V(;CS_1TFV^V:K'QL[ ^'U.U*OIYW9P:O\%EV=JE +MJ^W/OYR8+/[_7/[W.:\F,;/06?-0^&^6C<+^GCS7'_5G9CII_,.)8;+_F%P3 +MCT?RTL[M%M?+^C<))@>%\NIRGU??HYEV71^L/JU,O=L_U*N/7''7V20;V^\@ +M./]7>\O(N]E:C4^G3P7(FNU>'I'I93.<#+^#>CPL(7ZEI;'=[M:/I?SJS +MNZ76@:'UK#J]?,2CJ==FGG@>9_-,+S>]'5_BZMOC\WS^]\?@68_BV5 +MU/_T_O)IM*:%>;PW/"83L56P$/O'YO='N!YO7B/+>GY4O"8FAVSAFWN8< O5 +M>7#5K;\++Z7U."UDYH&3]SS]H7>\&SA<*R<_Z%MB-'P_A;B4>N"S&WY7$L5F//0?Y4&!A\QC. +M:E$RZ$LVS2^^V_O,O5_JGBKYQ72R"2^?WT/V.&VO+O-"+3CKMPJ7SNH]S::_OV>QNNFO,ZE< +MW]Y\O0W;PT<\M8HOX[?RZ=&+]V;/]K33>Z3?V^XTW(D^0L5@Y+OI5FJ?6&^? +MF8YCO_,\G4F^M,JS\K[?>LF;/__)X9+IU9+!4/+Q+:V'UW]KL&QXI"O!V/)4 +M6&8&@:!]F@B1%#&7J.7,[TCB&GF="K]F]2TM3E2GM^1\ [WK96@58H]X/F8I>8[CJ]3+!G_VL4D@WQO-Y_=1OK&ISO7_W&>U"_>"^V!CU-H5Q +MK+?X7,OU?;:UO/P"2Y=C_/K]E*+E1X\$.Q;YOG+U^3_Z><7ZQ[3QVF_7XLM; +MZ=C'($W>X_WZHUIJ]!KG5/.V"SS76]MF?9D8!8.!W>PH$2Z,#\GX:SQ]5]_- +MDB)X:[J]#0Z346R_W=CK^Q8MJAL7#895\QZ.MZ+BR7]>:U5IS53BD9[W=(5/>9-:5:N!J4BW. +M5N5-^7['G-VKOV:W?();^]__(V2)4O +MMWI_,X1S/L.8+H>\F5"N_]_9_*]+K/@[5VS97W\=N_42J_XLLUX]V +MNO7VOG@O"L:*\GH]E$X/I0^34;WT?U +MV>CDNZWI9+><+UJSPB#9*P[#E\>S-DF.DAE!^F"P_*[2^V6MG5R]54R5\]U7M'=I9!^[W.+PFOQOBSRV?ZCL:]NJI'"L<1@C"2:CV!A +M57)B+M:O23_\?N;7EWZT??R=)L%/7^+?[(*?]3WYK7?OSTLI5UE_=O/7J# - +M+J:MT;2[*M0VKO+FA3(9STZVEUGWG)EN^IW$[9I)=5._9^+>WYI2=I[1^#>5 +M&-Q^\XZN.?):KD[[;^KQ\=:_ZH?D_5#\-T^5V2L7O224V U Y>=0ZMXNJ?.J +ML7K,)O-R/I<^!POQW_Q5"5QESX?XX"OLF2+^\8O5PA78JO3-ULM_._]PS53^JWVZK@!+[^WA]8LM-NM/O=2/>0I +M?V0F%4SQ=BD2_^2ZATKU<__:;HU:U//G%V]?%NUG;MQ=M[3IL +M"M_]MY:+5[FQ#0T'F>ML>H\&5J;97G79^RTRN?ZYU3N71Y_;O[6?U\JEV7:0 +M;!2GI8.P-S/.!]Z"UT3Z$%O?WYW9X1D[UL_30SQ=O)KK(U([W^"[4C4PK^?GGOWV=#O'E.3<>=!^?_27] +M[4\;]4OR/<]MNF>J?3H?M!KQ3D>*L#Q95Q?!PV'>2^5SOVVBMOHSU_(W/'OU3V:8MUEJ%W+>BYMW&6@L#,J!@VAPEZJLMZ' +M\^Z0F*]WTV\CF!IO3Y=S==98DPKOV=-DMUU./K73/3\1]@[?R?4L%LY45UCR +M_/H7CZ7-2-._;-BY/!M^]\7+X-0,7M.[]#F=B[U3J79AN+C%Y[.:DCH[>==+ +MY71H^&XA_>C"%*0R&GO?/J7Z+G:/O>>Q??"7_IX"9Y/7V@=]W)[3+ +MK[O1*P9QVMX\.S\>GVRM-ZI6-^-U.3HMUP^9:NJ?.<:RZ=S_.^U#K7.X7&^#8JNS:H2/QNK1(Y'_E0Z#W*K:#_7> +MC_[OG%U7UJ/@.++:Q(PS&R^'XEA.Y>]XT3Z$@-?4Q +M4\V@V.-51?LN]"[L\ZUO(W^NK[_QQ:&13P8_J6AA/\G>0MWM5S!^&=P;E_AE +M<.W&9\E\ZIQ:UH^C]E1I;=97D7EDV?B6R^CPOW;B^]!G7Y/32BJ5/;P=VMVN +MU TLYB/55[M[/'W"C_NP6ETDL^.AM?;\3\OOM\4H4WV^,[GULO5(#&:??W60 +M+(Y;W-UTM6DS)6GIUUB +MV/R54H/"K$UF+]SGI>,Q6*RLP\M.*Y&3X;^2KT;L5)G/TIWJ\W],5;3*H=.C +MLLWEZ^5HX_;^]PZSW&,;NFWZDT[R>-@40Z'H=CR-5:/M8;25Z20N_?KF6SS, +M)JOM3$L;>[7OJU7CW1IEB\W :F8[G+Y3V6'FF%_])I'(]C1.9Z/Q5J6XC!Y# +M@?=G*/G\9TKOVRL\%I&F*KMV[9K:Y )GLV9I,;PNOMWSK3-]? :E1O#W"38> +MN_6]L9Z7LI?V,I->A+?I_Z7<:S6S2NIL)[*9EO^/P,-O4WQN#]/QQS=]Y-Z[7WJ_ I)A/Q87>P]2#/)A+=5O:[ +M_P36]]MP?UC:M7JYP,A0S$#=UV+&\*=W;V>55U3XS\W+4,W@8@;H3LPPV5YW +MTL5$=G$H#L_+[W6VS+?7;]!N]1--M[% +MQ7+ZNRFME]%EL'VJ5YJ+4":72\;OU4RP[ZW/;H_S>ZP4V(Q/C[7 +MSFV9?-?GEWMH4UL^8K'4YYJ-3YK/=+\;ZB#/G?4R^TQDHX=)??^R-R<3P\(I +MFJP7&M7)Q-;JXWQ]KH>?P_=\/=]K+.BGK_!ZCB\BQ3+E?,R +M-3_& INYW,3\_J3+S4]SGKZM>H/W)@>]YJ_GV.#=RFQ/DU)LMOM_UJOG/CL, +M=NO%]379F;]OLV/G4+EV]87I\+3;G>4/Q]C_UH\/8OM+ME6*)';KX/I893?^ +MS]5#*;R9U1K7YFD:^V=NRW;LD\K7J@TC;W%4[M3;NTIV7]C76MGK\#9VC@9C +MLO>[,0C_7KG3^[^]OR:7G+CS^V[>3OMR=]9.7N853:CE[/J^K/Q+Y67R<8V. +M/[/_-E]M#2Z!J_XM7:F>GK]QIQ^.)@^_4^QT/ UOUQOR8 +M>5;[U6]O&U]NEK_Z[CK_AOO78N[3__AP6 XOE;*OTXAOSFT +M5Z]=>_K-S&N);>'Y7_U'@:/.+#%RL&]FL].AV@OLQV?K7/@]?M9S868]]AQX +MOC<>(.+/>3X+QG.)56F7*YZ;_7)G6Y1CEZO2P52LF6QFW^OA8SQJC.ZK:BVW +M2;UK]>MP%5M/2^.SN[K1OM12S?)XN^IN4_M(/I2^#..;EW5YFYU/,Y%??)[- +MU)[78;]\;\6?H6TE%IBOG]>AP%"GUKGL=J?EI&CSAY+G97M7*\3*R+5$.K,2 +M8L]?MY?J]!%JQN*#^. 8O,8ZQ:@M +M^Y*/Y"_MPOW@.I\[D6^HO/H7&OOQH-<-'X*SPR4RJG=G[K1'F9#K4N@?UN +ML=X=AQK;2:R9J3RZO>>YX YO+E0;FAO=!ODH2XM6DY7A<7!XN(V'C[,(Q/QV +M&_ZD1?Y>G\+%5#=X"!S% A/E?2@6#/4SSVBYTNEM,KW$;'/>93*Y1?\[/T]Z +MWZ7:G6WEGM_U,IQ,BKREXNR;N>P+]6&VE!P6D_U/-+$[M"[1?3P_/-9^K6KL +M/6C\7[E29UU\^;AWB5XU%]J.;XE&/C#1FMZ/E50Q'>[,-HO V&I06$R\[%.5 +M\Q&O11O9Q'.]?D:#KWC__?O9Q4_!;O8S[6[CYW>X\7S3*Y_3O7[AJ=5TO"W=6UVBHG39WFY![S\"U8FS?KP=%U$KM='XM'!+;6JIOO%0!KFX%M+H];!4W>57C8JM;VN>[?^G%[1][N\GG07 +MUEW_/X_J:),9_VZQ[W-]V UG\74W49@//H=1,+-;S"JG4;L]#];<(K?[ +M>.\YGE7K4R*E7_L'P]U[XOLY!M[D4"?>NEU:O@?O0?5 +M4TG9/YX].\=BZ!0IA3+3\]">_NZ>FLG^KS:;U7*#1KFTRN6GB>>CU)\^!LG@ +MJ5-MUAO_W:QR=Y6_4KW,)AB=5"N?0;4?/M1C^=7$ K0T"J]SY63@-'U9?]/? +MQKB7R1] X)/;ZNYF9FQN.^9WK+FM[G_'WZRPRS7']4%BO)Z/\X7?J!/XZP<' +MYUGA5.S\SJE6[_/:-G?AR:H;N;UCR]XEKJ-\G=N-9FU3^+<_R4^KO"DN>M_N +MX!-^UU/%:#"VBVVOA_!Z7:S6AL.Q&8KE"K''9-3L)6__5;(XV:6OG4/] +M5+M+!SW2Z=/X5FI<'N51?5R<37<7UEO>&#P-"YW>['A.A1K)_6E=K09SA\9B +M/F[L3JU2(I35R<=6G\A@7,ZGNU:HT7L'@-\-7J'8/&/Y/^KW)G!^'S?FA';'U?_L+GP^;^/"RO91V +M[_VYN>Y.)^5*ZO-,HGC_]7O]XQ8MGW.)3GSXR2QRN]JMW9Q>QMU3JMD]W<[! +M^VO7?QQ:J^!SE<\'!HXJA?]C,[RW4Z7:_?^?NI [UQ/U +MUF..DZ]MM[45=_3X?Z\FK^/U5IVO;Y-DJ%H?3IK1S.+XR\G,V^6T64Y'+MEJ +M8C+,%N*G;/?[2,>O4,S 6C9_JF6VN7N\5:BOJZEY)G"1"CWSHT@\VDGM[>*= +MP7(^T8DO)MM$N!/8;I?&N^J +MU4KM*':>]MM4I?=]G:*'8".1WI1KS]3\N8_]C^_>:E9._Y+]X2[\SK6SS6SQ +M.RZ&O]6L:[P:/E]3-E0+R_JH+5J_EZ5-OE9:5@Z3;SBP/H[F]N-#)-I919*A +M\#/PV-TF5J_NL56NQN/%VF2:,L0,!Q;ZBT)L:5),%+);=PNM1 +M6T: WGDI?/IV D_?KN8?7N4^D0LU884[QWV]^KB.KO$ +M%L=HR10&VV3C]K_L%^]":K&R*9^J]V2@99\ZWG^OQR7:R^;S +MM=AR\EBG[KVLO[:?BF\/N]CZ&,R='O/K='W^=:XI7KN^>_M(3TH?YWTVJPP* +MJ_(\UJ6*I_/GY";UFF6[\4Q\,CI&H\GS[]M:WG+YY_&1+/Y7V^*HURXFLY_% +M;Z\R]D*9RZ783.>GHV(QF:^.7X'Y]^;7699"JS^>O$PH3_G2.'C(=':S6VN3:=;[L^^GT;WMWM/KY=8K1SK_XWF2 +MRNR[@UP]_QVE:MW\?RH5#_^7>K\1ZJ[]*Y4>HVLR%"H,SNG9[?Z[3V+A0Z^; +MKRW#X=6@_>FLR4#L_U>.?#7SJ=^^_VHFOPN3L6H?O/Y+T>J@W&ULF@5 +M_I%>+W5M?AK-;OA8&Z_^Q^JBLXF/JZ-/>KGKG"*)=+0^* S>\\8B?/ ^]X=D +MIK2?[:>+QF12">S]OIM+L?U9#6^Y:+463;3_QT@H<#0OU:OEZUE22ROO3>E>ZQT6GOKN=T.AK=WR+K?2=\?FYV<.SJ*GL9KL.+]V!: +MV.9BT]Y^!>_-!CV@M\?2[":L+SSJEW4HV,]'<6?S"44'__:H+HU:V^43[^:[ +M_NMWJOU(N9->YTN]Y"8=I(+OGTK)?*)=]DT&K^<<#^8Y-N\UFH'I7JU[.COY +M&]O7'?D]):7%P&H?_S5?RE HNIZ;Z'7CP4&JYXAU]O_71M50O%$.9^?)<-W/VKALAZU\O/AKYY*/ +MP:<13W>GL^6Q4PH<_E:!LW'>M%ZO/+.W1RTU.Y0[FVD*)3Y?_*K[Z.*R_^7_ +MX5IW5ZGT=H7.^_W+Y[K-V;VZ+@SKJ/OWNHSM<^;W9')^QN[?PZ^9#%<'Y?LF +M4AE7IL->.E3;Q^NSEN'X6@=SZR.^\ZP6PD\O4B)YCW=DWUHJ6__E+X#FW"OUPYV\]WXH$#I?!8?:7^Q3ST?.B +MGF[_SK%J8+J;BW6J2ZUR9=QFNTWJ[MVN)<_%0-GV8DHZNA<;K4SZ\U\ +M%\E>(Y5I-)F(=(?5=*CYVV^7G] R<-AM52H%J^#R4(K^MZ7@*!NR@]\&!M]. +M%?U/.E7G@>_^/E_Y.=6-8"$85*JDH-6I0CR<*A^NS_U9N%+X'%,E!\+,,MZH +M3'!AR_68*.JG[H#?9E@+; +MR6HEFL_$XI_ZY5F^75V]*TVVVW%A^\KO +MQ+?1'K_NJ=@N\%3.E2>Q;/-SBX$2^[A/Z=6U4M\\UOEU35:Z=/)P" +M&UEO[ZE=1 DGD_Z.9X&U3;QX?$Z/ +MJ4UU/A^]F^Z0Y\+Q.RXTUNEMHWT=%(*Q>FU7RQVR'ZC,0#5COKIHOP?W^[H? +M/2\;I?'-'K>Z>8::Z^0SVUM]&_MW.MO;=!/7S2=38F_CB> \D4U>7D&A8KN\ +M"IZ#P\,I&7RO!OOON[T[CP>/T;8^"OY?RW_CO6EN2HO,]/D9#,[?5^=;+6PS +MV?+AVSH(>QGF5.?Y_^;[NNB3QZ;^R<82Z\(OFMJLAE![JSWMVGYWG=;[P_5O%8VF"H-J^5 -W6K]VH(D/WT,?^=I+50- +M+T.9SJ79J8]_S?IN=7]6!NVK3GYQR1P^Y>SC65RORZM) J[>OD*!G_'ZM9AN +MZ^W TC.\>YP7H>2RNN;8#?B/0 QGH>!]_AKC=.3\>HY#^<2W-N^>WL])<3=I +M7#.5OOOD:)A]M^>)V/<\ +MW&XKNT3JF_GP?G:,]P_1V@LXO,C=9L-0\:MVGR+A)09D +M]OV--WN!^]3@]CQL=X??O;O[!![VAUWA\GD'P58UV/JP*2@9?)G]Y*^=_F:[7&^6J\#IZ?^/Q&-A +MJ;TL,%1)CT)$D">?+%3G=*S)D*/7BIXZ#PW<_^ +M"H-K-MKOQ]+K2GCPF/;+W?,N&8R4(G[]3Y'9X=5>MVIKF?C:J9]^R_+[56JTJ]& +M.S^YM]MLO#N!H?7E53VZZC>Q9SBVF8[>VV"Q-CUE/I]MH;=N/"_EZ7L7S^^C +MG>H\=Y@';C>W0.O23Z_WJEZJT<7LD>Z=]LK ^UD*A13(: +M?][BH6_E$9Y&R]$3D'Q34+0_DI'X^/IZ[Z>WS/'^[;8S@_&RN ^'P\UJ\UO> +MO#OKYCU[F!9#ZV^WLQH%-BN11V'T5$XE-C'_FNTI=I(Q2X3.;BSY'.W-S>!F_(J&:Y-GIUOZ +M7&NMY>=>;3:>H7CRDR\\7^'7L_P:[M_WR*&4:@2>5OO+K[L(S+Q:SYC*.!A. +M<[/?X1(.KSK_ITCX2[^^C./OE +MW[=>*5)H9T&*3]UR[8=OV^IZ4".-Q\O-X[F?*-6W +MN\9XTDT%JXN6Y?JX[8;_L8YB?]#]5-N'7/N@BWC^S7/O[K'W_VT($">%X)Y' +M'6DNPL=!-7;\_5.KW*^>:AV/X\FZ$U5:+\/R:O=;/=J_R"\;WS?R[5TO\?[- +M)+%#U\4[/N]^:NMMLW*L3N;O8R^[/XP__42L\GH\7.?E>)7*CB;E1+4X6B[* +MP<#//?H8JVO;I +M^UT+G^^"1+WN+D@[TWM\$@K*S9_/E&^>^TKH@)==D$C#R>?I^71YF9;SS]"P +M&OEM5HM=IO9NY%+)6NK^2#_")>VZ$5ZTEIM:+A->C%_5PCNE[)7NO;5#R:66T[X>4^-@H_$JO4KOG*Z^2O@9%4LYJ+%Z_= +M#^F:7AW[Z65M3IGL]/.7]^Q4/P<^:PE.>3XSNOQJH^)AWDS-V^5]XF&8?&T_ +MQ=]7V)G!7CEX>".%IH)]]LV^^EIEZI'W-ES.[S#!RFW6*Z_=N5'Y< +M6K6D*&7]&4O-;H===M9<7X>1^CBR.)7.[TRWDZB>QRM2Y[QVO)[B_N\W+]44[_&;!$^/5;%T'/5":Q,GI-M/3_J +MYD+#;2\[7K[GG_Q^%XNO2ONE''$T.6MO_^?R\+=[7M^;5R*QGMY6KV2ZUDQ_ +MCO=;_?IHY)_E1'=U+R2DWFZJ<-E&+\5(I:5F[#07C=6DN_GMFJM+=S,KA9;U +M6_LU/$<&U5N\<$KMC[UCO31>1@NS[&KVK3T_J5%RDZ\/1NI1L?T;:O\CP>ZB +MGHG4;@B$_?:-%G.3HZ)MAS8[06YK,2TLY\]O>CD*I4JI5:%[+>25U/=JN#Z/ +MI;O=V/LY*F33X78S7\G>8ZWO(32>U\^_4.W[W)>^B7>M?TO.AI7VHK2>[S+7 +MQL7 FLM]^I5N;OUMC7^%W^ZSRX=/E?E]T9S-UI==8QKZ5%N+WZ41V,AWJI=R +M^K:\+<]U[H5VGIM9OTIO 8CH*)1C&W6M<>L^(OO!C>3Z/M9AYM +MCB:G3ZPSJM5RGUT_+!,-Q78:_1]7?7HMQYEM$& ,YGN9T;%9Z$T#"]EQZI,\ +M'F.-33X2SX1FZ:_ONVC-Q\E<+)4:GE^NW>]^-]OEC:NS^/L^@JGIXNB\5_-=1H +MMGZ)2.25K/7")3'P;7&<&"R/YQ^BNS7?U&ZE]V&5*OTBSV"@_:]'GWZ6T4UY +M%QMG#IO =GRV>ZU?@^CP'?BH'B^/;_>7JY=:TY,19NUSF>+8JU$%QC[?E]ZGM;@XZ +MI^.DEM40387VZ5*E]UD.8L]"_- #TN9SV4SI\0D6?I-/KS9^9T[%:CW1J]\2 +M[[0>Z+QR::2.GW3"_M_^R.AA=';_,LG>D?/;1*R6'%X5S.W.JMR9C1*5Y"-P +MO4JG[JEPKI0[WR^_6''Y*SZ]ZL%V>FC'QNO@IGM^Y[K_];_3C,3[Q^4OG$J\ +MU]]]Z+8]3N?_WJL86?5[LN\I^_EDB^GNVG7.WX^C7XH,B@M_X=B#@U4E')VG,?"[VHF/TQ';^=> +M^MPN%Z.'[[W"JHZ6Q^W^<1S]AAN[T&8SV'6.^?X^U"C4JK'OME5TB\;^@XSJO42E]NN>IEU+[_>H7<(W#YGU=1])2./C/J1<$F%-!4:7,J' +MG)ANX?.XYV+9V_8^Z%0'T75A/FU'K\]+ZW&YG+.95:J;&BX3UQ!'-ODIA >O +MN3CD<-?,3)76\*BZ T9-]\;;??5X[45#QVNK/#CMKOEQ(_7ZM8;[>?R(82[/ +MPK7/,CO>-_.MP>)4GFAIR]O5JKX=9([)<&,_VRUKVVAM>QN%TM7TN6"1SJ6F +MYV>V??O]_\]\_5*[!HY;DV*[-_Y'=93%XO 4#ZN+]^7RI#!\?K[?YGP4VRR3 +MAU!KF@B5$F!_?WO\3?+/8>#T,"A,ILW']GV-S-7N:JM5Y*@VM@=Y9;WNJ-:&GY3@^7W\>EO$^_5OG^-/6,?.;O?R*G +M'AU-)YE\^5#LWLN%[?M\KQ[&B\9W>/M_@J=9T9$;?F5V^\&I.K[,<-=*/'+; +M-8[1^/R84QD[H]7ATMC-ZKMK9UO(E!.?12L2NZFR$>B>%9*QV/30'J48VUIQ5CLU^_>I+75GN&XG!__])WMK7 +M>V,>NC:RH=SPT])HV_?<]%,KU#]=V*KYK4P +MWH[#Y\1RM#J^JO5T\MN^;CMN_;23R@]VIW;G>SZ\8]_U[5$*#DW'P>Z0NQ1Z +MG=MQ/^M&ZMGR_)$LS>*70R\=JH]KC7TO<9HU<]_TY1_XS..9N\G^XY[-%1^! +M?FU[O!D]%YWQ;O$H'6:]4FX[C#,(U[ON]CI]C,?_UZYN?WO3Q[]0:CT]"-]M_ +M)GJ]_:$^OL8ZZ7!A6BN+Z6M2H*/=*WX>3P:]W+&:^/T7B^2Q5TB7W]/JMOB\ +MC^>;S.8:[A;W]T)CVX]4'[U\/M3O""-WMYE1;1!?)/[Q2R.;>VZ;B_CY'L^> +MFMW=+_3+#([9\G(Q#V>_E4+SLBW7;^^3I^3RFPNW*I%OK]F)YP_NQ+W<9A+<9V^= +MSK>0.8T6JUEJ??VU UN/93E[;9Z[[^*Q''N,%LU6<#I^![.=YG 0V#I,EB\] +M\_E7:AVV_]IL?TC49^_,-?59W ?SWGSV3F8*OTWF]FS\5ZM<,-EI/'*I\BN: +M&!Z+Y= B'#0=L^]5J;C+5*:+06O_N,_+B^%BFDX/H^7+.MNN50>5Y^[U"1?' +M@:/<[!]97(>3^J/MFRUUG?SIX3Z6?KWR\=2H>*V1XE5,G=JWFNC9.5>^! +MHWRQ''1-]RXCEG':G5\^S\;[O-VS:FQ<1N+K46);#\_1U6QKT +M9K'K8='O_MN'8:'R6-U>P5\M?O^&COEZ[U](%/K59?8T/PR/SGNVF&L/ L.% +M>2*XC&;3]\!EZ#(-?DZES&XZM"S&V:.GQFQVRKY+BT[@=[X;:D@[CSL4LB'F +M+/V\UV[;6#X?^;8;W^]E&>T]$]?>YEN?)&J-[;01SQ2^HV%Z62V.#[7D*39> +M5C+GP/]:EGKVK'X.OUJO>&B6GRUG R\_H/[S%1RY/V]]:[-A7K:[FYTNC_?S7 +M5^%EXI5^GP*;P=OX6 K\MHN;P$[@>>Z&_C_]K]=J_]OJ#U.KZ3V[3@[U8;O] +M3&3S&Q^KK_(YA&']$"$';@);L7[OMHCE W.U?O&E=O?6Y=][E[AOOKO0)/$+ +M%\:7Y.+>VM7[U=Q30QP/%L>9#8@U'(J\BL]SXKI>?X:#6&+1DH?O@>"L'BD1I^>3XO>^-TN]H+%B7&KR9Y +M*1M-X%/Z_(YDEH-"<%B'F6[:<">[G IQ'R8A&_WLZ7_.7QS&>:O6HNRHU^7D]?X>?N +MGTL^D\GDU-Z92ZQ8*O?*AZB^?@]/'HKT]^#9.BA21Z];LOU5>D0_TR; +MK>'@7)V\^\^E$KTZG20;^5$H6EUNQJ=DJI:(I\[-XN(<3%>OFW+WD:W+QY.A +MP-+OF/Q[W ^+@73LW+BGGS,/JUH[3G._*/':CLPETR,=I7E +M/'0>1+^&R=+F6IBFRXUXZQAZWK;+_B5XK>WO[\ZL^%\GK^]3+U$([=ZM]O!: +M/]0#*[G>.E>ZCN?1OMS[7']_E]4X.?X^K^?D9"<$&NN--Z?4(;6-A9K9SBZ8 +M/"::[?#\2U3BF\[V\VE]"Z6TXU_]C O;%*16_"PZ71;A?;Y +MU_-KY@O)5#);F6P:T1VWK2 +M:_W/\^DD-?QDPJU:._Y/+>E1_:V[_*:2BDY/KL>[KO<9%D);M^/U)=8 +MG!_G]HO>J_Y/#H;_UWV4"\QF6LOS)9TX%+SJ1W";[O=?+UQAM#;>__S2GWJB +M=#RGVX&=8/9X6[^&@:7 >?1R+,=/\]*DF6Q_-MW2NO)[F8Z#52(T.'\RC^2B +MU1^_*N%JH[OK_B^56&IX&6?R^^#QR- +M7^=,HE&-K6^[02_=^ER*W54J<;Q6R\/]_G >3"NI9>A=*2];F>VC_AR\S[]E +M\1]X3NG]Z6]KF5L0VU[FX_/KD(@LWF#E5_2YH(H^PM53^9UL'SJO[K_?&FVF +MMTN[_+O_?N'MV#.[SW87^VLRT9W5MK_JY7*;&B+?WZ4OJW20>YN?Z>AR=^R^7#0]ZFT(L7=JM +M_N?6H[Y^ETKMT^K\R\P3R\-QEWVU4H?B3B1[J)W^N=(@/9NF1\=@?1(;]:&I +MX__#JY;/GQ.18[#]S!^-SS;%?1U\EE;VUGS13B6_63^CW6M6Y+ +M/#P!L@R'_ZMB-YXOI6[Y=G4=;+^BQ=Q[]Z\/G[GLL]AZ+$+!P[R_>58FI^HL +M>-LQS;U %V*_.%KG7JEG?=GZ3=DTD&WL\3K]) W][ [V_::N]0D +M,ZP>CXE(:3K;S+KG5&YXWD]N^\!#]KIX7B/[M(OS'I)ZGZ]M0Y3B^'F6-M4ZL?(<%R8SP-WW6XA-@\/RNU1.S ?+#^+W?3)@O22[ X_ZT[Y +M'/[?,MU\.-;I;XN%W#LV2)V>E_6Y4MZGR;%T6E1JT6:Z=[O-:^W7^Y"X%@O9 +M[F,Q_V:>_:H-=>KZS$2RDW+ET"UN_Z7L+G 8*40:I>\ZE(R-#H=O,1VZ)=/5 +MT+\^6^<>U04^PE]@HE@\2>V3;7>#>&^'I\S=7']Y'KM9#>\&$0;2.+S/)F\5<:QR>Q1[$Y>I?2S?1P\_[WPM70A0.V^U.[0 +M-;8,+HOQ:,H>?[4*7$U*J\1GM!D^Q_]\+=G<=8K73:TT%$+='S/=]V/:3!X? +MZ6GB7_YH]+M#[![L=.?S>7OZS8V7:QYA.^A5OK[GYULQCXM9F#UKX?#P=TU< +MOH?E/-I*\BJO:_7HX%?ZM<*!I6/X-6W-$_WJ?[_N$\%&4^?SM_#H/3>/PS^6 +M/RQSR7G\-/CO?[7$?/%J74:?I>GPDYI6>]UQH=M-O?^[57Z2^HSGS_5MU$R6 +MKW4J>>46#<<7C_2^O@I5UH7U8=4/5[Z#IBQU+1WXY,>/MC*]63S:SD92D\GX +M>"DN"_-F_Q1-!XY2S^XS-=E>+]=+N1KJ9H*OW_P?&%S_KS:T%HW1T9L2S'1N +MWZ?I;#09ND>C[?&_T(D^^Z_Q.;\K'3._[Z/T>F^'JM=?N;4J^P3MP? +MZI3?YFB4V$8:S64PUUSFILUW^,C-'B;6L>=XE(OVKI_(HO@LJ=W[XJO=C":Z +M@9E=,WA.][K-W*H62;V#H]<_N9Q%4\UL.-[Y](@(+\%9)OE[%<+?7CB;"7<\ +MI>73/S5@G,3O_$N%G9CC;39>)Y.O9_Z::LW5Q7JM_4A,! +M_'.XWEJ%KMKLZ=V"?!6X26S/U?WL_C'Z=U: Q/;1>GV[Y<6HO&O/@?O0X +MK5OA4_2YBB]6OT,C5NA4VN][YEK=AR;'B-Z_#TPN ^/1-XCT%T]F%Y6XX#O( +MY6??=KI=^&[C@T+@(Y;]_V/QW<:,N9GMARE*RO-S[)@ZF0P7R^0NW;[$XZW\ +MNUQ_]%>#TO,_79_JNV>W&$R4%__%9=4X/.:K=*)7GFPZF4\OWM2$7G^3\?GO +M-MZV&A/?8OC0N52/H^VW^VA'.^%H!I!R.*CFJH_:[1P>=.*W5>@ +MM[B<-W+UH15L/-Z>/$JC32U6'B9'Z6'R'_F^*_W2YQ)Y;R*E4S4[Z31[YTH[ +MMCXG_]7T+.*&'GD4/Z5.==H:]Y?W>&\TZ-5/^-'U\W,OSB>O6N^WV?6_AT6M +M'XGO8_W6OQ:*]Y.Y?_/5JT@1_D^U0V,R;[Q">/"SUZ[[VMYBKVJE]"V4^O5* +M_OD=YH'ZS9B/./%.)LZ93J8T6,7O7>_S>QMLHYEZK'GX7W H<_5+K+UMK4;W +MU;<1CM]SG?%KL3JT=Y5O(W_M=X?/R648F"O_4Z^EM_ZQ3(1&YWYE/,[E:[%[ +MX#:2*.7;G^REG,D4DJU4X+^:F:QWB6QS<4Y%EZGE;E_H;B.#=B)OO+X[[>OB +M6PW6B\/Q(94-I1+!>+^8" XSCT?T%#AZ-K>/2[I1J:R_A>_]\YU%H_E_.O:8 +MY'N*]L!!,I8LW[K+[F8R:J>7R_LH7GH-HZ%X.+O(]5+CRNU4:[2WJ]HHW VG +M4Y]18=PX'5.QY,_)'SK__M-&9!/)K[>55NJ9:GVS]_;X,*WGYZ55MZ2Y+BO1 +M?;)W<>!'LB]1;7(Q2[E"GV7F:&&8GCXOQ5JN]^L$/C.!P6X0>2_%!^'Y +MI0^KQ"%^[*1'T]IU%4O_E]O(,!T/G/2<&+OC83;]N]\.#56KU&W_%HGWO56/5]\ +M+\JOWG1Q;R[[]7/PNEN]7J76?[&)M7__]"LP._M_PE>[V,O^?ET&+X&IW[X6 +MV!E64M?#_CH)=L?G6OC;;45J@_DP*U\/FK=H^OD\G/>/RF<_F[Z=]]WW,5_N +MAY=+\COZEV+?_7SXN$9:].OP=:KV:6WNM6KC&@Q,U-[!_6\\;R0[]7=CWBS]\O5;L5Z/K-:=;/@^ +M'E0OVW'Q'1A;>)^59*0_W$6?NU6R<9ZDVM]/I_#/C3>W6B+?W+\_SWDUN*EN +M-YWD(1XN;"K5]7YTSNZ>I6?5$?M2>:?*FFS4(TF7T_0]/H/%_>UU.W:RNLZKQ<%KM9E8_'T]=,8E^K/R)4 +MY*U499NX3'NI3&;6#.W6C]BUVP_\CS[-:28RA1P;JT%&._T\OXJK^T7L/(+S +M:XO4KYS*WU+/Z&18#-<6N^(W\%D>/E/!3N AO9U7;MW%?%6L5R_1:JU5&'># +MX4_"QUW;K<^1\'(;BU(N6PRI.G^$TD;TD/- [58SX./DO[GTAMGE-QP*9?JER6UQFGPC +MYU:JUYJ&&I==H5:JGT*K1T35\?"*;,;IZR*>W/_.BWH].5B>8^%U\UVKO6+C +MS7)>:9\"[X'74ZTX#,]WLW^K4VCTU;CSCD(R%KB(%WGI\6]I5W\V.^7Y(O!0 +MB\]WL=#DE4OOIMM@:(+;?JOOXS]2_KQJD\2W7HP&9L.^Q4?_%A+ML? +M%H>%WGPZ#ES,4^5.-MM,S%^1\[S62.PO_LBW;7,7C(TRI=DF$?^M+B=/F +ML:BV\]NOA?B8_'9O]TCND1&0M^J'SJE=WY?/UVT[^<\GNL/<(GNII3/[4&\S +M2HMSDYEH\I7*7:*CZS<7[2=N\\IX.-P]?V6G?;(ZS=:M?B2U6P\"EX&!D^@Z +M^XLU%B @?V<%S%_M(?\[KY0["F(Y>^O7+,'?.5ZZE;O*1K7;C +ME50X\8U=2L=.I=6=KJ>)J=0^CFQ/TV?C%3A8'W:%RP=<-Q@EZ&8?KYJ)+NM_# 5+U].]\-G-^T6HH?^KEW> +MIHK)R?+^"=+)_Y=47",^V8?'Q5!\^\X +M7:8--[NO?778[&=GQ59H44D>H^E0+!OZ-=.Q2.C>R\\J0ZG]U>]M&I7OL]-+ +MQSO=4.#\U9ZT5]?W?5&^9COU4?N=S55/6N)N+K]FT +MN+U3C^Q;P=&AL^F4BL_K);K:WJ*]^RO1*/>6S62A%SM&\XG@[A2.?F:WTZO< +MN)RFIF,Y%5A:C/O%=BNT9"+>Y9OD\M)T'>FEHKGJ)7S-E5['+)$T&JS]DX=7 +MX+U8['VV@U.YZID-OJN343[1W$UCMULD>CJ\]^MX98QH[#Q3S4=Y%DOL=[]% +M;K/H)#Z[WZO_7K>;EU9OOXWY%J_)UN-=GR^:Q^WC76I<=\MN-+"YV"82MZ1$ +M\3 ?S *'S=2D,IK=.]?W[#*H].S+Q=8VT,@[S\ZFS\!8IBGS]UK9Z>]YF^>" +MT= ^V([\.O5HJS>MU';C>^Z8GA62\5 V\'%>2<.7%[VD5? PC<5KV6\I&C@I +M)2X_/,CQ\EAH5[OC>O.=GB0OD_:MOXCO+]_9HY#_OS?)^:+UO:ZS)2?FM-B; +MYV>YRV)T7';OX_:R>LN>W[%U:-H^?RO5]J-Z[=Y^LUAI&DX=[I5./_K\UOJK +M>.[7<'&VK[E=Y-<=S8K?]382SQ7?H]HPNKQ^P\_AL7=YMJI!DN)L,)),S4II@(3&3K +MW56N7LV/KJ%I^=C+C,/5^B+>? 43!M; Q"6S[\]KA5TA%@T'IF_=ZB ^^&T: +M@>G,Y#$>7-.%<"G8[L1SSM#+=+OX#O\_H;-;I=>6-U!:K +MO\LQ>X[T@K5JZ]-0%5_;.AX7 GVA4[DV/XLW<\UQZ= +M^K1=F]9:HRQ(<'7))6N_4C:R/7B;GN%7&-5Z0L( X/9 +MV36SGMU/P7"B5V\U2H]Z*KZ/]ZKA9>-W>:TFO^-_W$V^F_EAH_]('F.W^[I7 +M*=6R&XGT^I9._@KG["N6S.5?A5SJ_%GG&MMAK+O==OJY[^ >S U#\7_B.YHM +M2]E^]]J]%KZQQC/=$1D>]C\H +M_TZ;?>SI_J?BI6=WO7Y7/JUJ(GF;7X*O8:SO;]V5FM/>Y7/8AC>EZB[1VX2K +MO=?Z-[C%3HGLZ[M!QSS$^Z7<[?),##:KWVH4S9T7K\?^TG'>']EOZGIKC%.? +M8.+SS;T'EW[KDHR(41Z?M[0M:;!0:'^[G6XB<-E+38.3;W_P&]5VI\S _C_] +MEZEL8_[O7Z6^N@:M5(E\KMU:1=S>8/4W[G5HJ^?K' +M?HU#OVW9]QO;?#)5;8]OA^LY-1P4(J="XUI(O#K/=V9>VH#1LY=0YWL-7,8: +MO\GKDO@%&I;/\^K-CK_)IR)%X'60\<:M1_.;;*&224:^S^SSD/X\FZ'Y(?SH +M78^WV6!3+U][QW*A7&V,EZ=%RZM.[YK+\'5X+N=:CUTAW&O&;]73X-W-+J// +MP-Y\D#BN4__()_"8W@^6R71Z=]H74]W R;&9%\+_!NNG?+ (?P:2)N5#N/8KMW!?GO7V>77E^]=+]-=^W97Z\ +M>6ZJ^_0Y>,PT(I-M:S((=@OC7>V6+EUK]_UQ4.W>ZJGKJC+?5;^Y\J/\,K_# +MW^ ]O2]WTKW6()?IU1^)52%]_K]OMW7F,ZPTEJWR\?0.[-:GS]XJ^MTW^\=) +M.)$;[\)=J3T$0J_/+I?,-M$[= ?'?6-=_%VRU5KG'-JT U_W931RFM;GRW?D +M*::F^?Y-7!]K]7'Y_0G +MN@TU6NA[[MD.?![JEVC[W8Q5?\EOKU7JWX>F7.<]G"],PY5IM)2J9%>U_Q.5 +MOLF-\I_A_E&8)D+=P6F(*NQN6H&-\BS_J?5WN];J=YPO5];E__.W7?5>N5N; +M[FT7YM=+]168^GZNZWFA&9E7GD[>YB&8;O;7O6;J\BH4@]/=*'18Q'[VYL4C +M?FV\@IE;<7.I9^*W6&68/P?&Y\]4O#!/95.CV?1\N=82J='D75Q4'LMO-YA? +M[P?C1=,"\A8*[6:SR3B]_;0_C7!RV;BVKNW0M;OXK^O-2R8:S(72JV^QVYH= +MY\7+,)DLS=OW<6'3V@I:$]G-Z'(=))KWTCN2SMPOLULF#J6]+;*O\JY]3(5R +MGUQ[GSDEMLMM)_>:GNZ;^Z^ZJ3;B>G\Y'0E*D%<_N6[D/=W7)JE=]=[]?3O! +MPB-2?#QB_>]W')YT7K-">3+__?_KW:APN?7OD5]?J'!2KW22I6YU$Y_?>_L\ +M=G9_OUR[^>5F'[GM_^_C8I"<+;_'_.N0G?02FUBI[B8^#O+NQ/W)X_X:K>;A +M?GC7".]7UVYKE&OVTK7VJ7#=KX>!X<[S)2M>KJ:[SZYU_+0"AZ,A@3BE]WW> +M4VU1S%GB5DG/A[7X=7P>/YN1[255"Y=/X^$G6=U7_N5-]_4:O7OA>7Z^#E_+ +MA]'NNME($9ZZAI3-P/:S<"TT!_="LGG*I2*':"R4R$8.UV7L,"Y&^I#9PR$Q +MF/9GZWPH%HLF*[^A!>ERWVD^D^_D<#\)'R^)82.R3/]#YV@K]$SW_[]K/;&] +M+X?QRBZ:J^7RM])C/R^L0O/TXE"02!_S^]"OUDL_A\%.MA"L;>^-9'US/Z;2 +MW=BKDW[ZQ=?YV"GP5>ADSN/;--3\)VK;=VAU;TD']_-5J!=O[+;#>FNTR[VB +ME\YA<_QB0N\Z=:?_=C=<" +M&\_=85]K]_;1XW*>W@0[CWUUO5RMSZ=:.=@[1RK)5C3W[UUBV<*T6(KM X]6 +MP67@I1B8J(^R^>HTELBL'M-?,C2^/1>+9^;?C#9;LUZ[U%T](ZM@.]B^!19N +MQ]J.%#>2NZE']_=8._9I@B&&0JG0M+_(?G:9V'C?V8V?0SWO^/3]7C^!Y46Z +MM)A?:^MX*MF+=&[O6F2OD\_U$HE0)9C-7LCN^B^R+$V6H6 ^L\NO#J]FN;)_ +MMPK]V=4#]75;%:KE6['GY'PY[YW*JTZU.AY=*[G$9KH] +M)<:AZBI_B2]:TVTBW&P\KI5N=5';!-87PV@9EPJ+A=QIZU?.BV_49?Y77O7%5:B\UG8+4; +MWCPZM?CZ_!DT1BZ(BUXE5RF$K^E3)#GZY:>+^AL;N=[]5P;O0KWQ#RP'P1 U +M^G?YG6@'\XE"\3B__KK)?JY;:YQ+B6(M&RTFPO'#OEB\#L/]U'\2VYTC_7(I +M^.^FNO_Y862L3O2G]^NA$\]G7_^CG_,ZZZ?:_WEO> J] KF9E>5H?/]NFH]' +M/68,GQ@7QX7C*+X.CPIY9?^W=AY^HH'!W#E5KM0X@[/"O?S-YBK#8*@3/:3V +MG^-_DWU4_Z?R/W^L7++I0ZWPK_*,&J+3Q6;3*F0?L?ONG3M\$I? 6DLAF]M_ +M7M?O\'+/3V^CZ>)4[9P.H\#Q^-;_+@(#P[5P-N*+7RT75JUD?%:_=*9 E/%K +M)ID9;3^_'[UXTKIF<5%?5P/W.P?XK +M;4:1X"O;ZFPV\\DV.9F%QX-&I9P-?9.O^GZ7VD32H&_K$KS-]N%RX729?F*[ +MZS]QK4X]R)/E<2O4JO7[_V*&F725O!4:L4%UG!ZWF]5@.RF6[(Q'[6NO%QUN +M+JM!+%'?+QRRZ8=CNC<==4N#X?K0;.C[]=YW/BWPI\PMGA_O8YQ&]%DJEUNOU[=;'Z7;B +M-OZH"WN9?N__>Y53X7JC=ZP=6KG$ZG*Z1:;&:^?W3[5+ZU FG3G%B]>K(N$] +M.TAGT[=,8]EY9:ZE9+#1BV5Z76OG.;X\A=.K1RC=:TPR[/JG;R6>V=4*8L';HQ/O +M1T4I6Y? >6O8B\\"FY?89IF/S':98^\8#G:VJ]4Q60L_O^_ZJ[P:)7J+3/7S +M2QS.R5HE7!Y>]?[BY%0N%^*;YOU_S(;/UW.F=CB.I[M#-[2;_,:[U^MA:0X\ +M[BJ=]+@;K3X>NUUN]RE'8G??8N+S?Q8"]Z=!IISO@3A_W?WT]UALOXU@Y/?/ +MY$>'Q2&R*6F1W?V=__E_MG*N='?#CJ'QW "^E#I]:^8&7K +MS^^FN)]V#\O.]!',,OJWQTOO6]@LUZMRJA^:GDS9,CHO= +MV"D8&OZ_X>WXNA#7%YO?U^(_6)=FT? [<6^TII'?L1V-)B?M?ST2BLV#T?-E +M5YF?;*AC\\;FD%_EOX=1M9K<15(6A/OO['0X%\K;:J$=?)?WD4%Q'2X'ID;- +M2O.Y&X:3F=XS,.PGN*__TN':<)6Z+I.%WSC]C>6N@U8C&OF75LGOXA)]7W*S +M0SH2*BNXS*0'VT\X +M%3V?;['WJS[7A%Y$^N-TK]],O9NU2OFTT^A?[^@X,=PNCYWZIN$!6IULEJO9 +M:+_X/B.C1/>SO0;N%L]K,K#W"W;GR\HSM=B2W;-W).IO7<="H=+@5NV4-MEJ +MNQN8:!0/AVC@;#0.5ANK?&N?*^6>M>0C6-U]4\-%<;*^5A:-17RC[SZ4?E,4_-7O5&=G6/_A*K1:[P +M;4TJ4_TV\ZX/T['RI_!\/M:_9+GX?=?^]W#P,DH/WN/CX[+L$K;EQBF\R93: +MY]*D,9P<>XW*(]G5*N_BKV)AMRM>7Z5';?-Z[)*%\/,73H_VIUXC\]O-OL%I +M;!#XN:87\T5^T5@7/KW>:'E*YH_>9^@5K([AD'.98K=[>G73E\1_F8[G7?WLWBWF(ZV/_=LKSY/UPJU@R)XX.,VSFX<0^%;G,?]-W1@4W%SHTSN'T +M9/D()PKW:/Z=3W4/S>>X=WI-YL5RN!,;M5*YZ>);B#3_C]EV&I_'5XO9,!7> +M&:_[:J>X>JY?KV;T/MO?BO%3:_$,5Y+U:FX27C2C^57UM\JVPH5/BC*8Z7U* +MVT5NN B?0_;_KWK!9MWD.?]V1?#P868^E% +M2W],3:+OP'#P<+S5F^&U^5U(9BKSV&YX*I__28ID^EGNGA>?5:O4W%7[X5;] +M^![\0Y5;--J:#,N?>K=\&E:+Y?5FZ(A-5,R5!Z-D,' YFR7&[>[]$,T/IO5S +M9%T;224/YV>X5VY>EY7P,Q*]I%J'>?1RZ29:@>N9[6M@(>_LS\?3KY[)'D[E +M63%\N%6[>O^I&*H5._U2E[28G\#X)\]3^!F>[F?A5.BIS,\_DA\6XDYWTLFL +M7J7;)]RX7*>+\Z/MLWRXEH +MX]B_A._'_Z\8>(]E?HG6(/C(][^54FB[.P1&[,W/-IEWO1F,6O'-LKB9I3[= +M8K>0^W3>LUS@_Q!YAE*C?B3V3.9'P+\&GLEX\?/ +M;_3IC ^EZCI[3?16Q>0ZF0G;A ^C8Z3*T/\OD=!I6$]&#OW7-'AO#BI"^(7P +MH_G)5@+'\W?Y\6]'&X/KJQYJ%H:[_VA\"MS6D[%3NK>LV,3[F^SO.BHW_.K, +M-S:N6Y>']<3J7'_/4^=S:%4>;':5T2CV]06I=L^ +MDPJ]["6SQU(A/#K/^IN# +M$WZO0/<6%_WY8[OL5FK7B!:NU)XHIB*EVZ\Y>09N1]%T\[C*[^_=9:&36LCC +M[\?K9Z[\B8?OC7._&0VO#ZG/<+NMU*.GDGQ\/>E5OZ-);!N8[MSCS^XW6"HG +MZK?/JK_*7;[=RFK0G77V^<;LT_Y>5N=G/3"Q2J97I>;KXYEM[#N?TG#P#/V# +MP\9F=']42LW;Z33(Y]?O1O=_'"4#X_G<\ST.CTK'Q2C\PNTBWSYGD)#B^S*>5[V)7>E='LO,NMFS. +M!\55TP-ZWG^T0[E!++0I-<:1?[76.%N\_H1W.XUO1SUK#?;PV 3_!W#6!RQ[M,U']N-&,%3M,X._ +MYR_,?Z;Z2=]B\,/T:W\W20<46@&%WG36_[T-Z+6]7ZS?PA^C]QM_C^^Q\9^^ +M/;+%08_W_9W;GO_$[F&$/\6)2Z/ ?1]]'=:?TOK=WVP^E7^P?PC:,>2Z=3\^ +M,^_C[U^__PMRSVU?]:?X!@4^/3#]P6"PG.R0_^GW)G-^'#;GQS63_F_;Z_]6 +M^[?_:%'&M,J!_TZ6F\APMUB%9\F.U/7S'9@<&+5K,#8XJ!RHC/UGE^W]+W;A +MO*YZOZ=;[/Z?7K-$;D#_OR9'E8,6N]A3ZFERX$1AQ2[6^U/W@_SDY]M\8+$\ +M3A>T\486*4N-AA>2=VYWAL3MH-T?'PQ +M_Y?>AEFTG"Z5>Z4NS'_;_91V[_W9^\ -TG7O,]=/SW:HCZLZ"QG5O^-]8/OQ +MA/>!D'R'IUW\H;2T/G#_A$!A[!^=K+<9\_][_ L^#X(/UE-:%R@@K3^/) P. +M\8K/E$\)[,IY-MP=V/]GP?H.S@T.[/76,CB0SKOUO\Q.E"ZQ4+I&7KEY>C@. +M4JS-P\#HHKQ/I4LOM8+2!3OW/!:,>#CX=YJ\T\_ +M3@SOV9/Q,1J,0/X-R1)V?)T876[&5;I0EZS6QD]OX3]?C^WV/:55XF@F-_[$ +MJ.IP0(7PLT'C3US;QG_ZLAN<6RF#8]/F]UAP:I>=+T'C#W;)V4]DT)W8^CB9 +MKV/QZ86S^.O^B/_70&3!]O,%CP5CO%H?3$Y]:?RAY\+?_VC=F*_ @^)"_5G8@,\&,_[/4Q=^* +MCS?ZW7KA\)5[_G9_XT\$-^F!X@,5M$I=XAOS':9[STL4]R&VO@[-9+V9PN-\U_Q/OCWG?(^@$U+_-L4_D82I>+5/"CY)[T/ +M)*C4^X!(I)#?B?'W.8V;##N?0!?- Y^,_[6'\O0<92A3%S^-%)H^\^_,8T4-.<\B,O;=-SFP[5. +M+Q'^!XER-P_U&!]6G =2/E9ZD)^X\2>0Z);9I 9L8ER@>VZNPI_T/J3QI[]C +MP3(#_9@F*+W?^),WVY,:?N$M=PY_>O9WM'"S.Q^D]/@D%5>*?SU0B0-K_-SE*XP^J$Q/K +M==M5_HP%;Z_M^\?^[10*7AZ1S4W^.C%2J^P3DT*3"%IF;#LL%E\-N^;0>:"] +M#[<(R,>5NBPT(7H9UP16[VO\^6,IFZS^UOME2R3UMS?^_""2PM8N0>&/\GU@?V,)08(!P4&!TY?$@ #! ,$%P,&!P97!A<6!P;W]W=!_F9M'GYCOF_IQQOU +MEW'JUWD:_OHK:\RKS]7WZ^/]F>.MKE/C9T2,V-GV('^[_\5U^,4[]_V;?ES4 +MSYH:]Q5_Z'&)>=4?"7*7_L\3WU?6?AZ5_E7'8H'?)@SOK_T?B]._\Q#3^1"> +M!%^^8_3<>(W/^^7U&GW]][7WA][_U]OXJ6]8:NM28[S&//1WCBOQ;C_^V#GZ +M:6UUCKNKI]_BBIP_]+\\#L,9#WC3V)-O@_.I8?G= \SFY_TCIJZC_)_:OZ.EC +ME LT;HZ=9B[YUHN*$9%I<"GCOZ]\W_#PY$U]#O:KX6L\&=OR[C1/L=9;G_OI +M#8..3#;Y8:SW1:S3LJU3%.?QR7RY=?[^[#^8T37Z !R27%[@@8<%&M1&@EQ>^' _\?4]HKR<_R>-:X/EFJ'2 +M?NBLY/P?D%9Z)__G1@@BCV\3$IM)6:UV%N=(JZPSX[93FFE)*6G-G!5XLV-P +MQ:-J:S&FL[X[=FYE[CNO4>JL):W+:"?FY$6($#XW;"[60E-$.FIR6GI:2CR9$- +M.U*F5Y\VS,S,O[_(I>Y+#\BPH?("Z*SU&.=["M ;V6%3K3[WVVEY\1G9N3&:[_-3+*I;9O13LEH):2G;7NKE=4D\P=W +MD=Y@]4MML^@DGJ034#AA>R9.$--/RVJJQ LC20=<0/Q809.P@F1B!XS* +MP]LT>-2:(/]O\BC#JU4;>F6>9KXR]^]&X$BG(:HBDH*DT<_&[U&K)3K'#9E? +MFZ<'DOOJ&N>1%,P4RJL@TP\D24EWCR0>_1U=*O72M'#4"8CN&G74 +MY?WZYG(P_QSP%711%$G"'V>B!M)NGCD8<2"..BS0#/IOP +MY\ _OE)G?GR6IV58P2\,T%*\.&^9XKP6V#!.C!$O^-F1(P=5^VY$!#Y'WG:0 +M-^ +R!+P&62:6& L #\LUE_#8FE,.1;&E&.RF'JLO3K&I%?7:/+J(,TCB26- +M8]F50=;7Q&-HFG-TO4*N##+%53TZM05']U;WF$+,KK$,PC$66\5CK=4QEEH9 +M9(6$:4P?X1K368VCR!9E-8V!K HR#)@49!!K: QA=8X)K,8Q?34M)J^JQ^JJ +M737J5K;=7EGU/)IJS"VKOKR%Z%J<9M1L;+L^/R"/XAQC9&/;X1B#\2B. +M,48VMEV-625/8V#&U.JVJS.KYVD,SYA:]7PU)@5=CB$:9:O;#L?@GF>QF#&S +M+OGJ#$ZY&&L91>N8$XW>/;O'D@;HUE4G:L(T$&G5X9OH:DS0J%K;=GTZ%CV/ +M9AISRP+<:_(4]3BZ:8RMD!X @XM.C06-J'7/=92*,35#%*4K4+/G\)BD(6[- +MD7*4U(:Z',,TRE9)UXDN1(?&@8:H#<_EY#KHX%C1$+9.^K(T#KH8RQE%Z]ON +M0..69[&4,;.^[1J4@GD333FEK>=B6ND +MAS$]8V@-\Y&YCKD8BQE%ZY@/RC;-U9B<4;7FV75-/9IIV->)65<^'/$@GQGE&T ;F\9*[YM18SHA:]WP? +M,O-D956N>#TR6F$OQDE&RR?@VI$JY'(,SRE:WG9=414]C@,;4ZK;34Y/R +MU# \M?"2".?DF* 1MK;MQXF<#Q0Y\)$BU\- QX>!#O@PT.F19M%#S0(?:Q8? +M;!8]VBSPX6;Q\681!YP%=,19Y!'FTP/,!Q]?/A]?#G& .4!'F$.2$ZCIZ 'H +M(6K5-S4>-31XV-GS=;(C>#@/>OC=)NDL%'&]R,\(%U$3Z4P7- 0+NAPI C +MVX( OFZ%#/3=$(F 6/^%V0#@"5!+ 0(+ H ! & -B43A_ 33[S- ( .T" +M & !214%$34502P$""P * 0#$<2LC4W'O +M]BL L " !8 @ 1DE,14Q)4U102P$""P * 0 +M!@!)3!4A'2[1Y;D' "Y% "0 "I @ 34%#2$E.12Y( +M4$L! @L "@ & 8 +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +*/ +#ifndef HUGE +#define HUGE HUGE_VAL +#endif +// #endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + +#endif diff --git a/MACHINES/cornelison b/MACHINES/cornelison new file mode 100644 index 0000000..0bfdbc6 --- /dev/null +++ b/MACHINES/cornelison @@ -0,0 +1,235 @@ +From - Fri Dec 4 08:05:39 1998 +Received: from cliffy.statsci.com (root@cliffy.statsci.com [206.63.206.72]) by server.divms.uiowa.edu with id MAA14931 for ; Thu, 3 Dec 1998 12:28:13 -0600 (CST) +Received: from adlib2 (adlib2 [206.63.206.104]) + by cliffy.statsci.com (8.8.8/8.8.8/Hub) with SMTP id KAA28911; + Thu, 3 Dec 1998 10:28:02 -0800 +Message-Id: <3.0.5.32.19981203102809.01371ec0@mailhost.statsci.com> +X-Sender: johnc@mailhost.statsci.com +X-Mailer: QUALCOMM Windows Eudora Pro Version 3.0.5 (32) +Date: Thu, 03 Dec 1998 10:28:09 -0800 +To: David Stewart +From: John Cornelison +Subject: Re: VStudio version of Meschach Library available?! +Cc: Zbigniew Leyk +In-Reply-To: <36669B2E.809B959C@math.uiowa.edu> +References: <3.0.5.32.19981202145120.0106bec0@mailhost.statsci.com> +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +X-Mozilla-Status: 8013 +X-Mozilla-Status2: 00000000 + +Thanks for the fast reply. I'll send you another note once it's working. +It now compiles fine into a .DLL with the following mods (hacks?!): + +The largest problem was figuring out to not include some of the +miscellaneous source files that are used for QA & utility & legacy support. + Once I read the makefile it was easy to set up. I'll send you the +necessary project files once I complete things. + +As far as coding goes, in machine.h, right near the end, I've added: + +#ifndef WIN32 +#define LIBEXPORT +#else + +/* Comment out the following line if NOT building Meschach.DLL! */ +/* TODO: Eventually this should be defined on the compile line only when +building the DLL */ +#define DLLCREATION + +#ifdef DLLCREATION + /* Including code is internal to the DLL */ + #define MLibImport _declspec(dllexport) + #define MLibExport _declspec(dllimport) + #define LIBEXPORT MLibImport +#else + /* Including code is external to the DLL */ + #define MLibImport _declspec(dllimport) + #define MLibExport _declspec(dllexport) + #define LIBEXPORT MLibExport +#endif + +#ifdef WORDS_BIGENDIAN + /* Win32 is always little endian */ + #undef WORDS_BIGENDIAN +#endif + +#ifdef HUGE_VAL + /* HUGE_VAL later defined in math.h */ + #undef HUGE_VAL +#endif + +#if defined(_DEBUG) && defined(_MSC_VER) + /* WARNING: Disabling the many "signed/unsigned mismatch" warnings so +others stand out! */ + /* These happen when comparing an unsigned int with a regular signed int +but should be fixed! */ + #pragma warning(disable:4018) +#endif +#endif /* WIN32 */ + +The only significant thing here is to explicitly define what routines are +being exported (or imported) from the DLL. This is done with Microsoft's +delightful _declspec(dllexport) & _declspec(dllimport) expressions. Next I +had to go through all function declarations & insert the LIBEXPORT define. +Ideally this should ONLY be done for routines that are made publicly +available from the library, i.e., not utility routines for internal use +only, but I put it in all the declarations in sparse.h; err.h; iter.h; +matrix.h; sparse2.h; meminfo.h. I left the complex libraries for another day. + +A sample of this is from the matrix.h file: + +/* miscellaneous functions */ + +#ifndef ANSI_C + +extern double LIBEXPORT square(), cube(), mrand(); +extern void LIBEXPORT smrand(), mrandlist(); +extern void LIBEXPORT m_dump(), px_dump(), v_dump(), iv_dump(); +extern MAT LIBEXPORT *band2mat(); +extern BAND LIBEXPORT *mat2band(); + +#else + +double LIBEXPORT square(double x), /* returns x^2 */ + cube(double x), /* returns x^3 */ + mrand(void); /* returns random # in [0,1) */ + +void LIBEXPORT smrand(int seed), /* seeds mrand() */ + mrandlist(Real *x, int len); /* generates len random numbers */ + +void LIBEXPORT m_dump(FILE *fp,MAT *a), px_dump(FILE *,PERM *px), + v_dump(FILE *fp,VEC *x), iv_dump(FILE *fp, IVEC *ix); + +MAT LIBEXPORT *band2mat(BAND *bA, MAT *A); +BAND LIBEXPORT *mat2band(MAT *A, int lb,int ub, BAND *bA); + +#endif + +It is sort of ugly, and I probably messed up all your formatting but it at +least works and won't break things on other platforms. The only warnings +that now appear during a full compilation (again, I've left out all the +z*.c routines) are: + +Deleting intermediate files and output files for project 'Meschach - Win32 +Debug'. +--------------------Configuration: Meschach - Win32 Debug-------------------- +Compiling... +bdfactor.c +bkpfacto.c +chfactor.c +copy.c +err.c +D:\Meschach\Source\err.c(328) : warning C4113: 'void (__cdecl *)()' differs +in parameter lists from 'void (__cdecl *)(int )' +D:\Meschach\Source\err.c(337) : warning C4113: 'void (__cdecl *)()' differs +in parameter lists from 'void (__cdecl *)(int )' +fft.c +givens.c +hessen.c +hsehldr.c +init.c +iter0.c +iternsym.c +itersym.c +D:\Meschach\Source\itersym.c(424) : warning C4113: 'int (__cdecl *)()' +differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +ivecop.c +lufactor.c +machine.c +matlab.c +matop.c +matrixio.c +meminfo.c +memory.c +memstat.c +mfunc.c +D:\Meschach\Source\mfunc.c(174) : warning C4244: '=' : conversion from +'double ' to 'int ', possible loss of data +norm.c +otherio.c +pxop.c +qrfactor.c +schur.c +D:\Meschach\Source\schur.c(158) : warning C4101: 't' : unreferenced local +variable +solve.c +sparse.c +sparseio.c +spbkp.c +D:\Meschach\Source\spbkp.c(1244) : warning C4113: 'int (__cdecl *)()' +differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +spchfctr.c +splufctr.c +sprow.c +spswap.c +submat.c +svd.c +symmeig.c +update.c +vecop.c +version.c +Linking... + Creating library Debug/Meschach.lib and object Debug/Meschach.exp +Creating browse info file... + +Meschach.dll - 0 error(s), 6 warning(s) + + + +At 08:07 AM 12/3/98 -0600, David Stewart wrote: +>John Cornelison wrote: +>> +>> Hi, I'm starting to get the library to work in the Win32 environment and +>> was curious if you are aware of anyone else that may have done this +already. +>> +>> Specifically I'd appreciate pointers to anyone that has wrapped this into a +>> Visual Studio project. I know Visual Studio is super platform specific so +>> is not something you are likely to promote, but knowing about this would +>> save us some time. +>> +>> Also I understand from the readme that you have an electronic form of the +>> manual I can ask for. If easy, I would appreciate a copy of that. We are +>> using the sparse matrix processing functionality for a small research +>> project we're considering and getting improvements of many magnitudes over +>> our previous techniques. +>> +>> Thanks in advance for doing all this incredible work! +>> +>> -John +> +>You can get a **partial** on-line manual via +> +> http://www.math.uiowa.edu/~dstewart/meschach/ +> +>However, this doesn't include the sparse matrix stuff. +>There have been some others who have worked on MS-DOS ports of +>Meschach. However, I haven't been keeping up with the status of these +>efforts. And I ceratinly haven't heard of anyone using it in +>Visual Studio. Zbigniew and I are glad to hear of another happy +>user though! +> +>Neither Zbigniew nor I have had much time to devote to Meschach +>in the past few years, which has (unfortunately) stalled its +>development... You should also look for matrix re-ordering techniques +>(I have some code for the Gibbs-Poole-Stockmeyer method for +>Meschach, if you would like that. Someone else developed it, +>so I can't say much regarding it; the algorithm is not the best +>matrix re-ordering technique for general sparse matrices, but +>it definitely better than standard orderings for most problems.) + +Sure, if convenient, I would appreciate getting this. + +>Also: please note the new email addresses! +> +> -- David Stewart + +Thanks again for developing the library! + +---------------------------------------------------------------------------- +http://www.MathSoft.com, Data Analysis Products Division +1700 Westlake Av N, Suite 500, Seattle, WA 98109-3012 +206.283.8802x243, 283.8691fax, johnc@statsci.com, NIC JHC7 +---------------------------------------------------------------------------- + diff --git a/MACHINES/w-mckinnon b/MACHINES/w-mckinnon new file mode 100644 index 0000000..87cb3a1 --- /dev/null +++ b/MACHINES/w-mckinnon @@ -0,0 +1,291 @@ +From bmck@bnr.ca Mon Aug 28 10:57:50 1995 +Received: from bnr.ca (x400gate.bnr.ca [192.58.194.73]) by gluttony.isc.tamu.edu (8.6.11/8.6.11) with SMTP id KAA05152 for ; Mon, 28 Aug 1995 10:57:42 -0500 +X400-Received: + by mta bnr.ca in /PRMD=BNR/ADMD=TELECOM.CANADA/C=CA/; Relayed; Mon, 28 Aug 1995 11:55:55 -0400 +X400-Received: + by /PRMD=BNR/ADMD=TELECOM.CANADA/C=CA/; Relayed; Mon, 28 Aug 1995 10:04:07 -0400 +X400-Received: + by /PRMD=BNR/ADMD=TELECOM.CANADA/C=CA/; Relayed; Mon, 28 Aug 1995 09:30:00 -0400 +Date: Mon, 28 Aug 1995 09:30:00 -0400 +X400-Originator: /dd.id=1736981/g=bill/i=b/s=mckinnon/@bnr.ca +X400-MTS-Identifier: + [/PRMD=BNR/ADMD=TELECOM.CANADA/C=CA/;bcars735.b.396:28.07.95.14.04.07] +X400-Content-Type: P2-1984 (2) +Content-Identifier: Re: Meschach ... +From: "bill (b.) mckinnon" +Sender: "bill (b.) mckinnon" +Message-ID: <"13392 Mon Aug 28 10:04:17 1995"@bnr.ca> +To: des@isc.tamu.edu +Subject: Re: Meschach v.1.2b +Content-Length: 6245 +X-Lines: 267 +Status: RO + +In message "Meschach v.1.2b", you write: + +> Dear Bill, +> +> Thank you for your message. Please accept my apologies for the +> delayed response... We are glad to have you as a Meschach user. +> We would also be glad to hear of your suggestions for fixing and improving +> Meschach. We have had reports of problems with HP machines. +> +> Yours, +> David Stewart +> + +David ... + +No problem on the delay. I understand the problem ... ;-) + +I'm using HP-UX 9.01 on an HP700s. I started with the "GCC" version of +"machine.h" and "makefile". After running "./configure", the "machine.h" +file which is generated "#include'd " before (which +the HP version of "cc" does not like). My amended version of "machine.h" +is included below; the differences start around line 68. + +Also, the "cc" compiler seems to require "-Aa" to be put in the CFLAGS in the +makefile (this option forces ANSI compatibility). Otherwise, the library and +its entries are created, but the functions do not seem be accessible from +code. Also, the ".o" files which are created without the "-Aa" are on the +order of ~400 bytes ... a bit small from my experience. With the "-Aa", the +object files are 1K or 2Kbytes. Several "redefinitions of macro HUGE_VAL" +also occur at compilation which don't seem to be a problem. + +These changes seem to generate the "meschach.a" library ok. Let me know if I +can help further. + +Bill McKinnon + + +---------- machine.h ------------ + +/* machine.h. Generated automatically by configure. */ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.2 1994/03/13 23:07:30 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#define const + +/* #undef MALLOCDECL */ +#define NOT_SEGMENTED 1 +#define HAVE_MEMORY_H 1 +/* #undef HAVE_COMPLEX_H */ +#define HAVE_MALLOC_H 1 +#define STDC_HEADERS 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 +#define CHAR0ISDBL0 1 +#define WORDS_BIGENDIAN 1 +/* #undef U_INT_DEF */ +#define VARARGS 1 +/* #undef HAVE_PROTOTYPES */ +/* #undef HAVE_PROTOTYPES_IN_STRUCT */ + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#define COMPLEX 1 +#define SPARSE 1 + +/* for loop unrolling */ +/* #undef VUNROLL */ +/* #undef MUNROLL */ + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +<<<<<<<<<<<<<<<<<< differences start here --- BMcK >>>>>>>>>>>>>>>>>>>>> + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +<<<<<<<<<<<<<<<<< end of differences --- BMcK >>>>>>>>>>>>>>>>>>> + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL +#endif +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + + diff --git a/README b/README new file mode 100644 index 0000000..f5c8589 --- /dev/null +++ b/README @@ -0,0 +1,455 @@ + + + + Meschach Library + Version 1.2b + + + David E. Stewart + (david.stewart@anu.edu.au) + + and + + Zbigniew Leyk + (zbigniew.leyk@anu.edu.au) + + School of Mathematical Sciences + Australian National University + Canberra ACT 0200 + Australia + + + [last revised: 6th April, 1994] + + + 1. INTRODUCTION + + The Meschach Library is a numerical library of C routines for performing +calculations on matrices and vectors. It is intended for solving systems of +linear equations (dense and sparse), solve least squares problems, +computing eigenvalues and eigenvectors, etc. We do not claim that it +contains every useful algorithm in numerical linear algebra, but it does +provide a basis on which more advanced algorithms can be built. The library +is for people who know something about the C programming language, +something of how to solve the numerical problem they are faced with but do +not want to have the hassle of building all the necessary routines from the +scratch. The library is not a loose collection of numerical routines but it +comprises a coherent system. The current version is enhanced with many +features comparing with previous versions. Since the memory requirements +are nontrivial for large problems we have paid more attention to +allocation/deallocation of memory. + + The source code is available to be perused, used and passed on without +cost, while ensuring that the quality of the software is not compromised. +The software is copyrighted; however, the copyright agreement follows in +the footsteps of the Free Software Foundation in preventing abuse that +occurs with totally public domain software. + + Detailed instructions for installing Meschach are contained below. + + Pronunciation: if in doubt, say "me-shark". This is close enough. +Don't ask us "Why call it that?" Have a look at the quote at the front of +the manual. + + + 2. AVAILABILITY + + The authors make this code openly available to others, in the hope that +it will prove to be a useful tool. We ask only that: + +* If you publish results obtained using Meschach, please consider + acknowledging the source of the code. + +* If you discover any errors in the code, please promptly communicate them + to the authors. + + We also suggest that you send email to the authors identifying yourself +as a user of Meschach; this will enable the authors to notify you of any +corrections/improvements in Meschach. + + + + 3. HOW TO GET IT + + There are several different forms in which you might receive Meschach. +To provide a shorthand for describing collections of files, the Unix +convention of putting alternative letters in [...] will be used. (So, +fred[123] means the collection fred1, fred2 and fred3.) Meschach is +available over Internet/AARnet via netlib, or at the anonymous ftp site +thrain.anu.edu.au in the directory pub/meschach. There are five .shar +files: meschach[01234].shar (which contain the library itself), +meschach0.shar (which contains basic documentation and machine dependent +files for a number of machines). Of the meschach[1234].shar files, only +meschach[12].shar are needed for the basic Meschach library; the third +.shar file contains the sparse matrix routines, and the the fourth contains +the routines for complex numbers, vectors and matrices. There is also a +README file that you should get from meschach0.shar. + + If you need the old iterative routines, the file oldmeschach.shar +contains the files conjgrad.c, arnoldi.c and lanczos.c. + + To get the library from netlib, + +mail netlib@research.att.com +send all from c/meschach + + There are a number of other netlib sites which mirror the main netlib +sites. These include netlib@ornl.gov (Oak Ridge, TN, USA), netlib@nac.no +(Oslo, Norway), ftp.cs.uow.edu.au (Wollongong, Australia; ftp only), +netlib@nchc.edu.tw (Taiwan), elib.zib-berlin.de (Berlin, Germany; ftp +only). (For anonymous ftp sites the directory containing the Meschach +.shar files is pub/netlib/c/meschach or similar, possibly depending on the +site.) + + Meschach is available in other forms on thrain.anu.edu.au by ftp in the +directory pub/meschach. It is available as a .tar file (mesch12a.tar for +version 1.2a), or as a collection of .shar files, or as a .zip file. The +.tar and .zip versions each contain the entire contents of the Meschach +library. + + There is a manual called "Meschach: Matrix Computations in C" which has +been published by + + Centre for Mathematics and its Applications + School of Mathematical Sciences + Australian National University + Canberra, ACT 0200 + Australia + +and costs A$30 (about US$22) + postage/handling. You can order it by +writing there or you can send email messages to one of us +(david.stewart@anu.edu.au or zbigniew.leyk@anu.edu.au) and we can pass it +on. + + If you don't have any money, as a stop gap you can get the **OLD** +manual, although it is out of date, by anonymous ftp from + + thrain.anu.edu.au : /pub/meschach/version1.1b/bookdvi.tar [.Z or .gz] + +In addition, don't forget that the distribution includes a DOC directory +which contains tutorial.txt and fnindex.txt which are respectively, the +tutorial chapter (text version) and the function index (text version). + + + + 4. INSTALLATION + + a) On Unix machines + + To extract the files from the .shar files, put them all into a suitable +directory and use + + sh .shar + +to expand the files. (Use one sh command per file; sh *.shar will not work +in general.) + + For the .tar file, use + + tar xvf mesch12a.tar + +and for the .zip file use + + unzip mesch12a.zip + + On a Unix system you can use the configure script to set up the +machine-dependent files. The script takes a number of options which are +used for installing different subsets of the full Meschach. For the basic +system, which requires only meschach[012].shar, use + + configure + make basic + make clean + + For including sparse operations, which requires meschach[0123].shar, use + + configure --with-sparse + make sparse + make clean + + For including complex operations, which requires meschach[0124].shar, use + + configure --with-complex + make complex + make clean + + For including everything, which requires meschach[01234].shar, use + + configure --with-all + make all + make clean + + To compile the complete library in single precision (with Real equivalent +to float), add the --with-float option to configure, use + + configure --with-all --with-float + make all + make clean + + + Some Unix-like systems may have some problems with this due to bugs or +incompatibilities in various parts of the system. To check this use make +torture and run torture. In this case use the machine-dependent files from +the machines directory. (This is the case for RS/6000 machines, the -O +switch results in failure of a routine in schur.c. Compiling without the +-O switch results in correct results.) + + If you have problems using configure, or you use a non-Unix system, +check the MACHINES directory (generated by meschach0.shar) for your +machine, operating system and/or compiler. Save the machine dependent +files makefile, machine.c and machine.h. Copy those files from the +directory for your machine to the directory where the source code is. + + To link into a program prog.c, compile it using + + cc -o prog_name prog.c ....(source files).... meschach.a -lm + + + This code has been mostly developed on the University of Queensland, +Australia's Pyramid 9810 running BSD4.3. Initial development was on a +Zilog Zeus Z8000 machine running Zeus, a Unix workalike operating system. +Versions have also been successfully used on various Unix machines +including Sun 3's, IBM RT's, SPARC's and an IBM RS/6000 running AIX. It +has also been compiled on an IBM AT clone using Quick C. It has been +designed to compile under either Kernighan and Richie, (Edition 1) C and +under ANSI C. (And, indeed, it has been compiled in both ANSI C and +non-ANSI C environments.) + + + b) On non-Unix machines + + First look in the machines directory for your system type. If it is +there, then copy the machine dependent files machine.h, makefile (and +possibly machine.c) to the Meschach directory. + + If your machine type is not there, then you will need to either compile +``by hand'', or construct your own makefile and possibly machine.h as well. +The machine-dependent files for various systems should be used as a +starting point, and the ``vanilla'' version of machine.h should be used. +Information on the machine-dependent files follows in the next three +subsections. + + On an IBM PC clone, the source code would be on a floppy disk. Use + + xcopy a:* meschach + +to copy it to the meschach directory. Then ``cd meschach'', and then +compile the source code. Different compilers on MSDOS machines will +require different installation procedures. Check the directory meschach +for the appropriate ``makefile'' for your compiler. If your compiler is +not listed, then you should try compiling it ``by hand'', modifying the +machine-dependent files as necessary. + + Worst come to worst, for a given C compiler, execute + *.c +on MS-DOS machines. For example, + tcc *.c +for Turbo C, and + msc *.c +for Microsoft C, or if you are using Quick C, + qcl *.c +and of course + cc *.c +for the standard Unix compiler. + + Once the object files have been generated, you will need to combine them +into a library. Consult your local compiler's manual for details of how to +do this. + + When compiling programs/routines that use Meschach, you will need to +have access the the header files in the INCLUDE directory. The INCLUDE +directory's contents can be copied to the directory where the +programs/routines are compiled. + + The files in the DOC directory form a very brief form of documentation +on the the library routines in Meschach. See the printed documentation for +more comprehensive documentation of the Meschach routines. This can be +obtained from the authors via email. + + The files and directories created by the machines.shar shell archive +contain the files machine.c machine.h and makefile for a particular +machine/operating system/compiler where they need to be different. Copy +the files in the appropriate directory for your machine/operating +system/compiler to the directory with the Meschach source before compiling. + + + + c) makefile + + + This is setup by using the configure script on a Unix system, based on +the makefile.in file. However, if you want to modify how the library is +compiled, you are free to change the makefile. + + The most likely change that you would want to make to this file is to +change the line + + CFLAGS = -O + +to suit your particular compiler. + + The code is intended to be compilable by both ANSI and non-ANSI +compilers. + + To achieve this portability without sacrificing the ANSI function +prototypes (which are very useful for avoiding problems with passing +parameters) there is a token ANSI_C which must be #define'd in order to +take full advantage of ANSI C. To do this you should do all compilations +with + + #define ANSI_C 1 + + This can also be done at the compilation stage with a -DANSI_C flag. +Again, you will have to use the -DANSI_C flag or its equivalent whenever +you compile, or insert the line + + #define ANSI_C 1 + +in machine.h, to make full use of ANSI C with this matrix library. + + + d) machine.h + + Like makefile this is normally set up by the configure script on Unix +machines. However, for non-Unix systems, or if you need to set some things +``by hand'', change machine.h. + + There are a few quantities in here that should be modified to suit your +particular compiler. Firstly, the macros MEM_COPY() and MEM_ZERO() need to +be correctly defined here. The original library was compiled on BSD +systems, and so it originally relied on bcopy() and bzero(). + + In machine.h you will find the definitions for using the standard ANSI C +library routines: + + /*--------------------ANSI C--------------------*/ + #include + #include + #define MEM_COPY(from,to,size) memmove((to),(from),(size)) + #define MEM_ZERO(where,size) memset((where),'\0',(size)) + + Delete or comment out the alternative definitions and it should compile +correctly. The source files containing memmove() and/or memset() are +available by anonymous ftp from some ftp sites (try archie to discover +them). The files are usually called memmove.c or memset.c. +Some ftp sites which currently (Jan '94) have a version of these files are +munnari.oz.au (in Australia), ftp.uu.net, gatekeeper.dec.com (USA), and +unix.hensa.ac.uk (in the UK). The directory in which you will find +memmove.c and memset.c typically looks like .../bsd-sources/lib/libc/... + + There are two further machine-dependent quantities that should be set. +These are machine epsilon or the unit roundoff for double precision +arithmetic, and the maximum value produced by the rand() routine, which is +used in rand_vec() and rand_mat(). + + + The current definitions of these are + + #define MACHEPS 2.2e-16 + #define MAX_RAND 2.147483648e9 + + The value of MACHEPS should be correct for all IEEE standard double +precision arithmetic. + + However, ANSI C's contains #define'd quantities DBL_EPSILON +and RAND_MAX, so if you have an ANSI C compiler and headers, replace the +above two lines of machine.h with + + #include + /* for Real == float */ + #define MACHEPS DBL_EPSILON + #define MAX_RAND RAND_MAX + + The default value given for MAX_RAND is 2^31 , as the Pyramid 9810 and +the SPARC 2's both have 32 bit words. There is a program macheps.c which +is included in your source files which computes and prints out the value of +MACHEPS for your machine. + + Some other macros control some aspects of Meschach. One of these is +SEGMENTED which should be #define'd if you are working with a machine or +compiler that does not allow large arrays to be allocated. For example, +the most common memory models for MS-DOS compilers do not allow more than +64Kbyte to be allocated in one block. This limits square matrices to be no +more than 9090 . Inserting #define SEGMENTED 1 into machine.h will mean +that matrices are allocated a row at a time. + + + + 4. SAMPLE TESTS + + There are several programs for checking Meschach called torture +(source: torture.c) for the dense routines, sptort (source: sptort.c) for +the sparse routines, ztorture (source ztorture.c) for a complex version of +torture, memtort (source memtort.c) for memory allocation/deallocation, +itertort (source itertort.c) for iterative methods, mfuntort (source +mfuntort.c) for computing powers of dense matrices, iotort (source +iotort.c) for I/O routines. These can be compiled using make by "make +torture", "make sptort", etc. The programs are part of meschach0.shar. + + + 5. OTHER PROBLEMS + + Meschach is not a commercial package, so we do not guarantee that +everything will be perfect or will install smoothly. Inevitably there will +be unforeseen problems. If you come across any bugs or inconsistencies, please +let us know. If you need to modify the results of the configure script, or +need to construct your own machine.h and makefile's, please send them to +us. A number of people sent us the machine dependent files for Meschach 1.1, +but with the use of configure, and the new information needed for version +1.2, these machine dependent files don't have quite the right information. +Hopefully, though, they are redundant. Non-Unix platforms at present +require ``manual'' installation. Because of the variety of platforms +(MS-DOS, Macintosh, VAX/VMS, Prime, Amiga, Atari, ....) this is left up to +the users of these platforms. We hope that you can use the distibutable +machine-dependent files as a starting point for this task. + + If you have programs or routines written using Meschach v.1.1x, you +should put the statement + + #include "oldnames.h" + +at the beginning of your files. This is because a large number of the +names of the routines have been changed (e.g. "get_vec()" has become +"v_get()"). This will enable you to use the old names, although all of the +error messages etc., will use the new names. Also note that the new +iterative routines have a very different calling sequence. If you need the +old iterative routines, they are in oldmeschach.shar. + + If you wish to let us know what you have done, etc., our email +addresses are + + david.stewart@anu.edu.au + zbigniew.leyk@anu.edu.au + + Good luck! + + + ACKNOWLEDGMENTS + + + Many people have helped in various ways with ideas and suggestions. +Needless to say, the bugs are all ours! But these people should be thanked +for their encouragement etc. These include a number of people at +University of Queensland: Graeme Chandler, David De Wit, Martin Sharry, +Michael Forbes, Phil Kilby, John Holt, Phil Pollett and Tony Watts. At the +Australian National University: Mike Osborne, Steve Roberts, Margaret Kahn +and Teresa Leyk. Karen George of the University of Canberra has been a +source of both ideas and encouragement. Email has become significant part +of work, and many people have pointed out bugs, inconsistencies and +improvements to Meschach by email. These people include Ajay Shah of the +University of Southern California, Dov Grobgeld of the Weizmann Institute, +John Edstrom of the University of Calgary, Eric Grosse, one of the netlib +organisers, Ole Saether of Oslo, Norway, Alfred Thiele and Pierre +Asselin of Carnegie-Mellon Univeristy, Daniel Polani of the University of +Mainz, Marian Slodicka of Slovakia, Kaifu Wu of Pomona, Hidetoshi +Shimodaira of the University of Tokyo, Eng Siong of Edinburgh, Hirokawa Rui +of the University of Tokyo, Marko Slyz of the University of Michigan, and +Brook Milligan of the University of Texas. This list is only partial, and +there are many others who have corresponded with us on details about +Meschach and the like. Finally our thanks go to all those that have had to +struggle with compilers and other things to get Meschach to work. + + + + + diff --git a/arnoldi.c b/arnoldi.c new file mode 100644 index 0000000..a8bf310 --- /dev/null +++ b/arnoldi.c @@ -0,0 +1,198 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + Arnoldi method for finding eigenvalues of large non-symmetric + matrices +*/ +#include +#include +#include "matrix.h" +#include "matrix2.h" +#include "sparse.h" + +static char rcsid[] = "$Id: arnoldi.c,v 1.3 1994/01/13 05:45:40 des Exp $"; + + +/* arnoldi -- an implementation of the Arnoldi method */ +MAT *arnoldi(A,A_param,x0,m,h_rem,Q,H) +VEC *(*A)(); +void *A_param; +VEC *x0; +int m; +Real *h_rem; +MAT *Q, *H; +{ + STATIC VEC *v=VNULL, *u=VNULL, *r=VNULL, *s=VNULL, *tmp=VNULL; + int i; + Real h_val; + + if ( ! A || ! Q || ! x0 ) + error(E_NULL,"arnoldi"); + if ( m <= 0 ) + error(E_BOUNDS,"arnoldi"); + if ( Q->n != x0->dim || Q->m != m ) + error(E_SIZES,"arnoldi"); + + m_zero(Q); + H = m_resize(H,m,m); + m_zero(H); + u = v_resize(u,x0->dim); + v = v_resize(v,x0->dim); + r = v_resize(r,m); + s = v_resize(s,m); + tmp = v_resize(tmp,x0->dim); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(v,TYPE_VEC); + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(s,TYPE_VEC); + MEM_STAT_REG(tmp,TYPE_VEC); + sv_mlt(1.0/v_norm2(x0),x0,v); + for ( i = 0; i < m; i++ ) + { + set_row(Q,i,v); + u = (*A)(A_param,v,u); + r = mv_mlt(Q,u,r); + tmp = vm_mlt(Q,r,tmp); + v_sub(u,tmp,u); + h_val = v_norm2(u); + /* if u == 0 then we have an exact subspace */ + if ( h_val == 0.0 ) + { + *h_rem = h_val; + return H; + } + /* iterative refinement -- ensures near orthogonality */ + do { + s = mv_mlt(Q,u,s); + tmp = vm_mlt(Q,s,tmp); + v_sub(u,tmp,u); + v_add(r,s,r); + } while ( v_norm2(s) > 0.1*(h_val = v_norm2(u)) ); + /* now that u is nearly orthogonal to Q, update H */ + set_col(H,i,r); + if ( i == m-1 ) + { + *h_rem = h_val; + continue; + } + /* H->me[i+1][i] = h_val; */ + m_set_val(H,i+1,i,h_val); + sv_mlt(1.0/h_val,u,v); + } + +#ifdef THREADSAFE + V_FREE(v); V_FREE(u); V_FREE(r); + V_FREE(r); V_FREE(s); V_FREE(tmp); +#endif + return H; +} + +/* sp_arnoldi -- uses arnoldi() with an explicit representation of A */ +MAT *sp_arnoldi(A,x0,m,h_rem,Q,H) +SPMAT *A; +VEC *x0; +int m; +Real *h_rem; +MAT *Q, *H; +{ return arnoldi(sp_mv_mlt,A,x0,m,h_rem,Q,H); } + +/* gmres -- generalised minimum residual algorithm of Saad & Schultz + SIAM J. Sci. Stat. Comp. v.7, pp.856--869 (1986) + -- y is overwritten with the solution */ +VEC *gmres(A,A_param,m,Q,R,b,tol,x) +VEC *(*A)(); +void *A_param; +VEC *b, *x; +int m; +MAT *Q, *R; +double tol; +{ + STATIC VEC *v=VNULL, *u=VNULL, *r=VNULL, *tmp=VNULL, *rhs=VNULL; + STATIC VEC *diag=VNULL, *beta=VNULL; + int i; + Real h_val, norm_b; + + if ( ! A || ! Q || ! b || ! R ) + error(E_NULL,"gmres"); + if ( m <= 0 ) + error(E_BOUNDS,"gmres"); + if ( Q->n != b->dim || Q->m != m ) + error(E_SIZES,"gmres"); + + x = v_copy(b,x); + m_zero(Q); + R = m_resize(R,m+1,m); + m_zero(R); + u = v_resize(u,x->dim); + v = v_resize(v,x->dim); + tmp = v_resize(tmp,x->dim); + rhs = v_resize(rhs,m+1); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(v,TYPE_VEC); + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(tmp,TYPE_VEC); + MEM_STAT_REG(rhs,TYPE_VEC); + norm_b = v_norm2(x); + if ( norm_b == 0.0 ) + error(E_RANGE,"gmres"); + sv_mlt(1.0/norm_b,x,v); + + for ( i = 0; i < m; i++ ) + { + set_row(Q,i,v); + tracecatch(u = (*A)(A_param,v,u),"gmres"); + r = mv_mlt(Q,u,r); + tmp = vm_mlt(Q,r,tmp); + v_sub(u,tmp,u); + h_val = v_norm2(u); + set_col(R,i,r); + R->me[i+1][i] = h_val; + sv_mlt(1.0/h_val,u,v); + } + + /* use i x i submatrix of R */ + R = m_resize(R,i+1,i); + rhs = v_resize(rhs,i+1); + v_zero(rhs); + rhs->ve[0] = norm_b; + tmp = v_resize(tmp,i); + diag = v_resize(diag,i+1); + beta = v_resize(beta,i+1); + MEM_STAT_REG(beta,TYPE_VEC); + MEM_STAT_REG(diag,TYPE_VEC); + QRfactor(R,diag /* ,beta */); + tmp = QRsolve(R,diag, /* beta, */ rhs,tmp); + v_resize(tmp,m); + vm_mlt(Q,tmp,x); + +#ifdef THREADSAFE + V_FREE(v); V_FREE(u); V_FREE(r); + V_FREE(tmp); V_FREE(rhs); + V_FREE(diag); V_FREE(beta); +#endif + + return x; +} diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 new file mode 100644 index 0000000..6167990 --- /dev/null +++ b/autom4te.cache/output.0 @@ -0,0 +1,5820 @@ +@%:@! /bin/sh +@%:@ Guess values for system-dependent variables and create Makefiles. +@%:@ Generated by GNU Autoconf 2.69. +@%:@ +@%:@ +@%:@ Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +@%:@ +@%:@ +@%:@ This configure script is free software; the Free Software Foundation +@%:@ gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in @%:@( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in @%:@(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in @%:@ (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in @%:@( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in @%:@ (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +@%:@ as_fn_unset VAR +@%:@ --------------- +@%:@ Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +@%:@ as_fn_set_status STATUS +@%:@ ----------------------- +@%:@ Set @S|@? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} @%:@ as_fn_set_status + +@%:@ as_fn_exit STATUS +@%:@ ----------------- +@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} @%:@ as_fn_exit + +@%:@ as_fn_mkdir_p +@%:@ ------------- +@%:@ Create "@S|@as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} @%:@ as_fn_mkdir_p + +@%:@ as_fn_executable_p FILE +@%:@ ----------------------- +@%:@ Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} @%:@ as_fn_executable_p +@%:@ as_fn_append VAR VALUE +@%:@ ---------------------- +@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take +@%:@ advantage of any shell optimizations that allow amortized linear growth over +@%:@ repeated appends, instead of the typical quadratic growth present in naive +@%:@ implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +@%:@ as_fn_arith ARG... +@%:@ ------------------ +@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the +@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments +@%:@ must be portable across @S|@(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD] +@%:@ ---------------------------------------- +@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are +@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the +@%:@ script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} @%:@ as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in @%:@((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIB@&t@OBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="err.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIB@&t@OBJS +RANLIB +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +PROGS +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_complex +with_sparse +with_all +with_unroll +with_munroll +with_segmem +with_float +with_double +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + @<:@@S|@ac_default_prefix@:>@ + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + @<:@PREFIX@:>@ + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root @<:@DATAROOTDIR/doc/PACKAGE@:>@ + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) +$as_echo "@%:@define COMPLEX 1" >>confdefs.h + +$as_echo "@%:@define SPARSE 1" >>confdefs.h + +$as_echo "@%:@define VUNROLL 1" >>confdefs.h + +$as_echo "@%:@define MUNROLL 1" >>confdefs.h + +$as_echo "@%:@define SEGMENTED 1" >>confdefs.h + +$as_echo "@%:@define REAL_FLT 1" >>confdefs.h + +$as_echo "@%:@define REAL_DBL 1" >>confdefs.h + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +@%:@ ac_fn_c_try_compile LINENO +@%:@ -------------------------- +@%:@ Try to compile conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_compile + +@%:@ ac_fn_c_try_cpp LINENO +@%:@ ---------------------- +@%:@ Try to preprocess conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_cpp + +@%:@ ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +@%:@ ------------------------------------------------------- +@%:@ Tests whether HEADER exists, giving a warning if it cannot be compiled using +@%:@ the include files in INCLUDES and setting the cache variable VAR +@%:@ accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +@%:@include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_header_mongrel + +@%:@ ac_fn_c_try_run LINENO +@%:@ ---------------------- +@%:@ Try to link conftest.@S|@ac_ext, and return whether this succeeded. Assumes +@%:@ that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_run + +@%:@ ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +@%:@ ------------------------------------------------------- +@%:@ Tests whether HEADER exists and can be compiled using the include files in +@%:@ INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +@%:@include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_header_compile + +@%:@ ac_fn_c_try_link LINENO +@%:@ ----------------------- +@%:@ Try to link conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_link + +@%:@ ac_fn_c_check_type LINENO TYPE VAR INCLUDES +@%:@ ------------------------------------------- +@%:@ Tests whether TYPE exists after having included INCLUDES, setting cache +@%:@ variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_type + +@%:@ ac_fn_c_check_func LINENO FUNC VAR +@%:@ ---------------------------------- +@%:@ Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in @%:@(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers machine.h" + +PROGS="" +# Extract the first word of "acc", so it can be a program name with args. +set dummy acc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="acc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="""" +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="gcc" +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $@%:@ != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + case $ac_cv_prog_cc_stdc in @%:@( + no) : + ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; @%:@( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 +else + ac_cv_prog_cc_stdc=no +fi + +fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 +$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } + if ${ac_cv_prog_cc_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +fi + + case $ac_cv_prog_cc_stdc in @%:@( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; @%:@( + '') : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; @%:@( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 +$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; +esac + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "@%:@define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "@%:@define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "@%:@define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "@%:@define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "@%:@define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "@%:@define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "@%:@define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "@%:@define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "@%:@define _TANDEM_SOURCE 1" >>confdefs.h + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +for ac_header in memory.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "memory.h" "ac_cv_header_memory_h" "$ac_includes_default" +if test "x$ac_cv_header_memory_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_MEMORY_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "@%:@define STDC_HEADERS 1" >>confdefs.h + +fi + +ac_fn_c_check_header_mongrel "$LINENO" "complex.h" "ac_cv_header_complex_h" "$ac_includes_default" +if test "x$ac_cv_header_complex_h" = xyes; then : + $as_echo "@%:@define HAVE_COMPLEX_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" +if test "x$ac_cv_header_malloc_h" = xyes; then : + $as_echo "@%:@define HAVE_MALLOC_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "varargs.h" "ac_cv_header_varargs_h" "$ac_includes_default" +if test "x$ac_cv_header_varargs_h" = xyes; then : + $as_echo "@%:@define VARARGS 1" >>confdefs.h + +fi + + +$as_echo "@%:@define NOT_SEGMENTED 1" >>confdefs.h + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +@%:@define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "@%:@define const /**/" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "@%:@define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "@%:@define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +@%:@ Check whether --with-complex was given. +if test "${with_complex+set}" = set; then : + withval=$with_complex; +fi + + +@%:@ Check whether --with-sparse was given. +if test "${with_sparse+set}" = set; then : + withval=$with_sparse; +fi + + +@%:@ Check whether --with-all was given. +if test "${with_all+set}" = set; then : + withval=$with_all; +fi + + +@%:@ Check whether --with-all was given. +if test "${with_all+set}" = set; then : + withval=$with_all; +fi + + +@%:@ Check whether --with-unroll was given. +if test "${with_unroll+set}" = set; then : + withval=$with_unroll; +fi + + +@%:@ Check whether --with-munroll was given. +if test "${with_munroll+set}" = set; then : + withval=$with_munroll; +fi + + +@%:@ Check whether --with-segmem was given. +if test "${with_segmem+set}" = set; then : + withval=$with_segmem; +fi + + +@%:@ Check whether --with-float was given. +if test "${with_float+set}" = set; then : + withval=$with_float; +fi + + +@%:@ Check whether --with-double was given. +if test "${with_double+set}" = set; then : + withval=$with_double; +fi + +LIBS="$LIBS -lm" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +u_int +int +main () +{ +#include +#ifdef __STDC__ +#include +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + u_int i; i = 1; +else + $as_echo "@%:@define U_INT_DEF 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +echo 'computing machine epsilon(s)' +echo $CC -o macheps dmacheps.c +$CC -o macheps dmacheps.c +cat >>confdefs.h <<_ACEOF +@%:@define D_MACHEPS `macheps` +_ACEOF + +echo $CC -o macheps fmacheps.c +$CC -o macheps fmacheps.c +cat >>confdefs.h <<_ACEOF +@%:@define F_MACHEPS `macheps` +_ACEOF + +echo computing M_MAX_INT +echo $CC -o maxint maxint.c +$CC -o maxint maxint.c +cat >>confdefs.h <<_ACEOF +@%:@define M_MAX_INT `maxint` +_ACEOF + +echo checking char '\\0' vs. float zeros +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +main() { + char *cp = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + double *dp; + dp = (double *)cp; + if ( *dp == 0.0 ) printf("yes\n"); } + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + $as_echo "@%:@define CHAR0ISDBL0 1" >>confdefs.h + +fi +rm -f conftest* + +for ac_func in bcopy bzero +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +@%:@define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +function prototypes +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + extern int test (int i, double x); +else + $as_echo "@%:@define HAVE_PROTOTYPES 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_config_files="$ac_config_files makefile make.mex" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIB@&t@OBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIB@&t@OBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in @%:@( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in @%:@(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD] +@%:@ ---------------------------------------- +@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are +@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the +@%:@ script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} @%:@ as_fn_error + + +@%:@ as_fn_set_status STATUS +@%:@ ----------------------- +@%:@ Set @S|@? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} @%:@ as_fn_set_status + +@%:@ as_fn_exit STATUS +@%:@ ----------------- +@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} @%:@ as_fn_exit + +@%:@ as_fn_unset VAR +@%:@ --------------- +@%:@ Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +@%:@ as_fn_append VAR VALUE +@%:@ ---------------------- +@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take +@%:@ advantage of any shell optimizations that allow amortized linear growth over +@%:@ repeated appends, instead of the typical quadratic growth present in naive +@%:@ implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +@%:@ as_fn_arith ARG... +@%:@ ------------------ +@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the +@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments +@%:@ must be portable across @S|@(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in @%:@((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +@%:@ as_fn_mkdir_p +@%:@ ------------- +@%:@ Create "@S|@as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} @%:@ as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +@%:@ as_fn_executable_p FILE +@%:@ ----------------------- +@%:@ Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} @%:@ as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX +@%:@@%:@ Running $as_me. @%:@@%:@ +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "machine.h") CONFIG_HEADERS="$CONFIG_HEADERS machine.h" ;; + "makefile") CONFIG_FILES="$CONFIG_FILES makefile" ;; + "make.mex") CONFIG_FILES="$CONFIG_FILES make.mex" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + +echo "Extensions to basic version: use configure --with-opt1 --with-opt2" +echo " Option:" +echo " --with-complex incorporate complex functions" +echo " --with-sparse incorporate sparse matrix functions" +echo " --with-all both of the above" +echo " --with-unroll unroll low level loops on vectors" +echo " --with-munroll unroll low level loops on matrices" +echo " --with-float single precision" +echo " --with-double double precision (default)" +echo "Re-run configure with these options if you want them" +# configure.in copyright (C) Brook Milligan and David Stewart, 1993, 2002 diff --git a/autom4te.cache/requests b/autom4te.cache/requests new file mode 100644 index 0000000..460e3b8 --- /dev/null +++ b/autom4te.cache/requests @@ -0,0 +1,77 @@ +# This file was generated. +# It contains the lists of macros which have been traced. +# It can be safely removed. + +@request = ( + bless( [ + '0', + 1, + [ + '/usr/local/Cellar/autoconf/2.69/share/autoconf' + ], + [ + '/usr/local/Cellar/autoconf/2.69/share/autoconf/autoconf/autoconf.m4f', + 'configure.in' + ], + { + '_LT_AC_TAGCONFIG' => 1, + 'AM_PROG_F77_C_O' => 1, + 'AC_INIT' => 1, + 'm4_pattern_forbid' => 1, + '_AM_COND_IF' => 1, + 'AC_CANONICAL_TARGET' => 1, + 'AC_SUBST' => 1, + 'AC_CONFIG_LIBOBJ_DIR' => 1, + 'AC_FC_SRCEXT' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AC_PROG_LIBTOOL' => 1, + 'AM_INIT_AUTOMAKE' => 1, + 'AM_PATH_GUILE' => 1, + 'AC_CONFIG_SUBDIRS' => 1, + 'AM_AUTOMAKE_VERSION' => 1, + 'LT_CONFIG_LTDL_DIR' => 1, + 'AC_REQUIRE_AUX_FILE' => 1, + 'AC_CONFIG_LINKS' => 1, + 'm4_sinclude' => 1, + 'LT_SUPPORTED_TAG' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AM_NLS' => 1, + 'AC_FC_PP_DEFINE' => 1, + 'AM_GNU_GETTEXT_INTL_SUBDIR' => 1, + 'AM_MAKEFILE_INCLUDE' => 1, + '_m4_warn' => 1, + 'AM_PROG_CXX_C_O' => 1, + '_AM_COND_ENDIF' => 1, + '_AM_MAKEFILE_INCLUDE' => 1, + 'AM_ENABLE_MULTILIB' => 1, + 'AM_SILENT_RULES' => 1, + 'AM_PROG_MOC' => 1, + 'AC_CONFIG_FILES' => 1, + 'include' => 1, + 'LT_INIT' => 1, + 'AM_PROG_AR' => 1, + 'AM_GNU_GETTEXT' => 1, + 'AC_LIBSOURCE' => 1, + 'AM_PROG_FC_C_O' => 1, + 'AC_CANONICAL_BUILD' => 1, + 'AC_FC_FREEFORM' => 1, + 'AH_OUTPUT' => 1, + 'AC_FC_PP_SRCEXT' => 1, + '_AM_SUBST_NOTMAKE' => 1, + 'AC_CONFIG_AUX_DIR' => 1, + 'sinclude' => 1, + 'AM_PROG_CC_C_O' => 1, + 'm4_pattern_allow' => 1, + 'AM_XGETTEXT_OPTION' => 1, + 'AC_CANONICAL_SYSTEM' => 1, + 'AM_CONDITIONAL' => 1, + 'AC_CONFIG_HEADERS' => 1, + 'AC_DEFINE_TRACE_LITERAL' => 1, + 'AM_POT_TOOLS' => 1, + 'm4_include' => 1, + '_AM_COND_ELSE' => 1, + 'AC_SUBST_TRACE' => 1 + } + ], 'Autom4te::Request' ) + ); + diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0 new file mode 100644 index 0000000..afbe1f4 --- /dev/null +++ b/autom4te.cache/traces.0 @@ -0,0 +1,425 @@ +m4trace:configure.in:29: -1- AC_INIT([err.c]) +m4trace:configure.in:29: -1- m4_pattern_forbid([^_?A[CHUM]_]) +m4trace:configure.in:29: -1- m4_pattern_forbid([_AC_]) +m4trace:configure.in:29: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) +m4trace:configure.in:29: -1- m4_pattern_allow([^AS_FLAGS$]) +m4trace:configure.in:29: -1- m4_pattern_forbid([^_?m4_]) +m4trace:configure.in:29: -1- m4_pattern_forbid([^dnl$]) +m4trace:configure.in:29: -1- m4_pattern_forbid([^_?AS_]) +m4trace:configure.in:29: -1- AC_SUBST([SHELL]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([SHELL]) +m4trace:configure.in:29: -1- m4_pattern_allow([^SHELL$]) +m4trace:configure.in:29: -1- AC_SUBST([PATH_SEPARATOR]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PATH_SEPARATOR]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PATH_SEPARATOR$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_NAME]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_NAME$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_TARNAME]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_VERSION]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_VERSION$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_STRING]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_STRING$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) +m4trace:configure.in:29: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL], ['AC_PACKAGE_URL'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([PACKAGE_URL]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_URL$]) +m4trace:configure.in:29: -1- AC_SUBST([exec_prefix], [NONE]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([exec_prefix]) +m4trace:configure.in:29: -1- m4_pattern_allow([^exec_prefix$]) +m4trace:configure.in:29: -1- AC_SUBST([prefix], [NONE]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([prefix]) +m4trace:configure.in:29: -1- m4_pattern_allow([^prefix$]) +m4trace:configure.in:29: -1- AC_SUBST([program_transform_name], [s,x,x,]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([program_transform_name]) +m4trace:configure.in:29: -1- m4_pattern_allow([^program_transform_name$]) +m4trace:configure.in:29: -1- AC_SUBST([bindir], ['${exec_prefix}/bin']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([bindir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^bindir$]) +m4trace:configure.in:29: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([sbindir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^sbindir$]) +m4trace:configure.in:29: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([libexecdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^libexecdir$]) +m4trace:configure.in:29: -1- AC_SUBST([datarootdir], ['${prefix}/share']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([datarootdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^datarootdir$]) +m4trace:configure.in:29: -1- AC_SUBST([datadir], ['${datarootdir}']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([datadir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^datadir$]) +m4trace:configure.in:29: -1- AC_SUBST([sysconfdir], ['${prefix}/etc']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([sysconfdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^sysconfdir$]) +m4trace:configure.in:29: -1- AC_SUBST([sharedstatedir], ['${prefix}/com']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([sharedstatedir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^sharedstatedir$]) +m4trace:configure.in:29: -1- AC_SUBST([localstatedir], ['${prefix}/var']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([localstatedir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^localstatedir$]) +m4trace:configure.in:29: -1- AC_SUBST([includedir], ['${prefix}/include']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([includedir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^includedir$]) +m4trace:configure.in:29: -1- AC_SUBST([oldincludedir], ['/usr/include']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([oldincludedir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^oldincludedir$]) +m4trace:configure.in:29: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME], + ['${datarootdir}/doc/${PACKAGE_TARNAME}'], + ['${datarootdir}/doc/${PACKAGE}'])]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([docdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^docdir$]) +m4trace:configure.in:29: -1- AC_SUBST([infodir], ['${datarootdir}/info']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([infodir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^infodir$]) +m4trace:configure.in:29: -1- AC_SUBST([htmldir], ['${docdir}']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([htmldir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^htmldir$]) +m4trace:configure.in:29: -1- AC_SUBST([dvidir], ['${docdir}']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([dvidir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^dvidir$]) +m4trace:configure.in:29: -1- AC_SUBST([pdfdir], ['${docdir}']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([pdfdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^pdfdir$]) +m4trace:configure.in:29: -1- AC_SUBST([psdir], ['${docdir}']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([psdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^psdir$]) +m4trace:configure.in:29: -1- AC_SUBST([libdir], ['${exec_prefix}/lib']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([libdir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^libdir$]) +m4trace:configure.in:29: -1- AC_SUBST([localedir], ['${datarootdir}/locale']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([localedir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^localedir$]) +m4trace:configure.in:29: -1- AC_SUBST([mandir], ['${datarootdir}/man']) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([mandir]) +m4trace:configure.in:29: -1- m4_pattern_allow([^mandir$]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_NAME$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */ +@%:@undef PACKAGE_NAME]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */ +@%:@undef PACKAGE_TARNAME]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_VERSION$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */ +@%:@undef PACKAGE_VERSION]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_STRING$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */ +@%:@undef PACKAGE_STRING]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */ +@%:@undef PACKAGE_BUGREPORT]) +m4trace:configure.in:29: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL]) +m4trace:configure.in:29: -1- m4_pattern_allow([^PACKAGE_URL$]) +m4trace:configure.in:29: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */ +@%:@undef PACKAGE_URL]) +m4trace:configure.in:29: -1- AC_SUBST([DEFS]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([DEFS]) +m4trace:configure.in:29: -1- m4_pattern_allow([^DEFS$]) +m4trace:configure.in:29: -1- AC_SUBST([ECHO_C]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([ECHO_C]) +m4trace:configure.in:29: -1- m4_pattern_allow([^ECHO_C$]) +m4trace:configure.in:29: -1- AC_SUBST([ECHO_N]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([ECHO_N]) +m4trace:configure.in:29: -1- m4_pattern_allow([^ECHO_N$]) +m4trace:configure.in:29: -1- AC_SUBST([ECHO_T]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([ECHO_T]) +m4trace:configure.in:29: -1- m4_pattern_allow([^ECHO_T$]) +m4trace:configure.in:29: -1- AC_SUBST([LIBS]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([LIBS]) +m4trace:configure.in:29: -1- m4_pattern_allow([^LIBS$]) +m4trace:configure.in:29: -1- AC_SUBST([build_alias]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([build_alias]) +m4trace:configure.in:29: -1- m4_pattern_allow([^build_alias$]) +m4trace:configure.in:29: -1- AC_SUBST([host_alias]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([host_alias]) +m4trace:configure.in:29: -1- m4_pattern_allow([^host_alias$]) +m4trace:configure.in:29: -1- AC_SUBST([target_alias]) +m4trace:configure.in:29: -1- AC_SUBST_TRACE([target_alias]) +m4trace:configure.in:29: -1- m4_pattern_allow([^target_alias$]) +m4trace:configure.in:30: -1- AC_CONFIG_HEADERS([machine.h]) +m4trace:configure.in:32: -1- AC_SUBST([PROGS]) +m4trace:configure.in:32: -1- AC_SUBST_TRACE([PROGS]) +m4trace:configure.in:32: -1- m4_pattern_allow([^PROGS$]) +m4trace:configure.in:33: -1- _m4_warn([obsolete], [The macro `AC_PROGRAM_CHECK' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:41: AC_PROGRAM_CHECK is expanded from... +configure.in:33: the top level]) +m4trace:configure.in:33: -1- AC_SUBST([CC]) +m4trace:configure.in:33: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:33: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:34: -1- _m4_warn([obsolete], [The macro `AC_PROGRAM_CHECK' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:41: AC_PROGRAM_CHECK is expanded from... +configure.in:34: the top level]) +m4trace:configure.in:34: -1- AC_SUBST([CC]) +m4trace:configure.in:34: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:34: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([CFLAGS]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CFLAGS]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CFLAGS$]) +m4trace:configure.in:35: -1- AC_SUBST([LDFLAGS]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([LDFLAGS]) +m4trace:configure.in:35: -1- m4_pattern_allow([^LDFLAGS$]) +m4trace:configure.in:35: -1- AC_SUBST([LIBS]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([LIBS]) +m4trace:configure.in:35: -1- m4_pattern_allow([^LIBS$]) +m4trace:configure.in:35: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CPPFLAGS]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CPPFLAGS$]) +m4trace:configure.in:35: -1- AC_SUBST([CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^CC$]) +m4trace:configure.in:35: -1- AC_SUBST([ac_ct_CC]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([ac_ct_CC]) +m4trace:configure.in:35: -1- m4_pattern_allow([^ac_ct_CC$]) +m4trace:configure.in:35: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([EXEEXT]) +m4trace:configure.in:35: -1- m4_pattern_allow([^EXEEXT$]) +m4trace:configure.in:35: -1- AC_SUBST([OBJEXT], [$ac_cv_objext]) +m4trace:configure.in:35: -1- AC_SUBST_TRACE([OBJEXT]) +m4trace:configure.in:35: -1- m4_pattern_allow([^OBJEXT$]) +m4trace:configure.in:36: -1- AC_SUBST([CPP]) +m4trace:configure.in:36: -1- AC_SUBST_TRACE([CPP]) +m4trace:configure.in:36: -1- m4_pattern_allow([^CPP$]) +m4trace:configure.in:36: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.in:36: -1- AC_SUBST_TRACE([CPPFLAGS]) +m4trace:configure.in:36: -1- m4_pattern_allow([^CPPFLAGS$]) +m4trace:configure.in:36: -1- AC_SUBST([CPP]) +m4trace:configure.in:36: -1- AC_SUBST_TRACE([CPP]) +m4trace:configure.in:36: -1- m4_pattern_allow([^CPP$]) +m4trace:configure.in:38: -1- _m4_warn([obsolete], [The macro `AC_AIX' is obsolete. +You should run autoupdate.], [../../lib/autoconf/specific.m4:436: AC_AIX is expanded from... +configure.in:38: the top level]) +m4trace:configure.in:38: -1- AC_SUBST([GREP]) +m4trace:configure.in:38: -1- AC_SUBST_TRACE([GREP]) +m4trace:configure.in:38: -1- m4_pattern_allow([^GREP$]) +m4trace:configure.in:38: -1- AC_SUBST([EGREP]) +m4trace:configure.in:38: -1- AC_SUBST_TRACE([EGREP]) +m4trace:configure.in:38: -1- m4_pattern_allow([^EGREP$]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS]) +m4trace:configure.in:38: -1- m4_pattern_allow([^STDC_HEADERS$]) +m4trace:configure.in:38: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */ +@%:@undef STDC_HEADERS]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_SYS_TYPES_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_SYS_STAT_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STDLIB_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STRING_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_MEMORY_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STRINGS_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_INTTYPES_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STDINT_H]) +m4trace:configure.in:38: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_UNISTD_H]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_SOURCE]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_POSIX_SOURCE$]) +m4trace:configure.in:38: -1- AH_OUTPUT([_POSIX_SOURCE], [/* Define to 1 if you need to in order for `stat\' and other things to work. */ +@%:@undef _POSIX_SOURCE]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_1_SOURCE]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_POSIX_1_SOURCE$]) +m4trace:configure.in:38: -1- AH_OUTPUT([_POSIX_1_SOURCE], [/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +@%:@undef _POSIX_1_SOURCE]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_MINIX]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_MINIX$]) +m4trace:configure.in:38: -1- AH_OUTPUT([_MINIX], [/* Define to 1 if on MINIX. */ +@%:@undef _MINIX]) +m4trace:configure.in:38: -1- AH_OUTPUT([USE_SYSTEM_EXTENSIONS], [/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([__EXTENSIONS__]) +m4trace:configure.in:38: -1- m4_pattern_allow([^__EXTENSIONS__$]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_ALL_SOURCE]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_ALL_SOURCE$]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_GNU_SOURCE]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_GNU_SOURCE$]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_PTHREAD_SEMANTICS]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_POSIX_PTHREAD_SEMANTICS$]) +m4trace:configure.in:38: -1- AC_DEFINE_TRACE_LITERAL([_TANDEM_SOURCE]) +m4trace:configure.in:38: -1- m4_pattern_allow([^_TANDEM_SOURCE$]) +m4trace:configure.in:39: -1- _m4_warn([obsolete], [The macro `AC_MINIX' is obsolete. +You should run autoupdate.], [../../lib/autoconf/specific.m4:441: AC_MINIX is expanded from... +configure.in:39: the top level]) +m4trace:configure.in:40: -1- _m4_warn([obsolete], [The macro `AC_ISC_POSIX' is obsolete. +You should run autoupdate.], [../../lib/autoconf/specific.m4:446: AC_ISC_POSIX is expanded from... +configure.in:40: the top level]) +m4trace:configure.in:44: -3- AC_DEFINE_TRACE_LITERAL([HAVE_PROTOTYPES]) +m4trace:configure.in:44: -3- m4_pattern_allow([^HAVE_PROTOTYPES$]) +m4trace:configure.in:44: -2- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [../../lib/autoconf/general.m4:2615: AC_TRY_COMPILE is expanded from... +configure.in:44: the top level]) +m4trace:configure.in:53: -1- AC_SUBST([RANLIB]) +m4trace:configure.in:53: -1- AC_SUBST_TRACE([RANLIB]) +m4trace:configure.in:53: -1- m4_pattern_allow([^RANLIB$]) +m4trace:configure.in:54: -1- _m4_warn([obsolete], [The macro `AC_HAVE_HEADERS' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:35: AC_HAVE_HEADERS is expanded from... +configure.in:54: the top level]) +m4trace:configure.in:54: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_MEMORY_H]) +m4trace:configure.in:54: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MEMORY_H]) +m4trace:configure.in:54: -1- m4_pattern_allow([^HAVE_MEMORY_H$]) +m4trace:configure.in:55: -1- _m4_warn([obsolete], [The macro `AC_STDC_HEADERS' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:75: AC_STDC_HEADERS is expanded from... +configure.in:55: the top level]) +m4trace:configure.in:55: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS]) +m4trace:configure.in:55: -1- m4_pattern_allow([^STDC_HEADERS$]) +m4trace:configure.in:55: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */ +@%:@undef STDC_HEADERS]) +m4trace:configure.in:56: -2- AC_DEFINE_TRACE_LITERAL([HAVE_COMPLEX_H]) +m4trace:configure.in:56: -2- m4_pattern_allow([^HAVE_COMPLEX_H$]) +m4trace:configure.in:56: -1- _m4_warn([obsolete], [The macro `AC_HEADER_CHECK' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:36: AC_HEADER_CHECK is expanded from... +configure.in:56: the top level]) +m4trace:configure.in:57: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MALLOC_H]) +m4trace:configure.in:57: -2- m4_pattern_allow([^HAVE_MALLOC_H$]) +m4trace:configure.in:57: -1- _m4_warn([obsolete], [The macro `AC_HEADER_CHECK' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:36: AC_HEADER_CHECK is expanded from... +configure.in:57: the top level]) +m4trace:configure.in:58: -2- AC_DEFINE_TRACE_LITERAL([VARARGS]) +m4trace:configure.in:58: -2- m4_pattern_allow([^VARARGS$]) +m4trace:configure.in:58: -1- _m4_warn([obsolete], [The macro `AC_HEADER_CHECK' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:36: AC_HEADER_CHECK is expanded from... +configure.in:58: the top level]) +m4trace:configure.in:59: -1- AC_DEFINE_TRACE_LITERAL([NOT_SEGMENTED]) +m4trace:configure.in:59: -1- m4_pattern_allow([^NOT_SEGMENTED$]) +m4trace:configure.in:60: -1- _m4_warn([obsolete], [The macro `AC_SIZE_T' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:73: AC_SIZE_T is expanded from... +configure.in:60: the top level]) +m4trace:configure.in:60: -1- AC_DEFINE_TRACE_LITERAL([size_t]) +m4trace:configure.in:60: -1- m4_pattern_allow([^size_t$]) +m4trace:configure.in:60: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if does not define. */ +@%:@undef size_t]) +m4trace:configure.in:61: -1- _m4_warn([obsolete], [The macro `AC_CONST' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:55: AC_CONST is expanded from... +configure.in:61: the top level]) +m4trace:configure.in:61: -1- AC_DEFINE_TRACE_LITERAL([const]) +m4trace:configure.in:61: -1- m4_pattern_allow([^const$]) +m4trace:configure.in:61: -1- AH_OUTPUT([const], [/* Define to empty if `const\' does not conform to ANSI C. */ +@%:@undef const]) +m4trace:configure.in:62: -1- _m4_warn([obsolete], [The macro `AC_WORDS_BIGENDIAN' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:83: AC_WORDS_BIGENDIAN is expanded from... +configure.in:62: the top level]) +m4trace:configure.in:62: -1- AH_OUTPUT([WORDS_BIGENDIAN], [/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif]) +m4trace:configure.in:62: -1- AC_DEFINE_TRACE_LITERAL([WORDS_BIGENDIAN]) +m4trace:configure.in:62: -1- m4_pattern_allow([^WORDS_BIGENDIAN$]) +m4trace:configure.in:62: -1- AC_DEFINE_TRACE_LITERAL([AC_APPLE_UNIVERSAL_BUILD]) +m4trace:configure.in:62: -1- m4_pattern_allow([^AC_APPLE_UNIVERSAL_BUILD$]) +m4trace:configure.in:62: -1- AH_OUTPUT([AC_APPLE_UNIVERSAL_BUILD], [/* Define if building universal (internal helper macro) */ +@%:@undef AC_APPLE_UNIVERSAL_BUILD]) +m4trace:configure.in:63: -2- AC_DEFINE_TRACE_LITERAL([COMPLEX]) +m4trace:configure.in:63: -2- m4_pattern_allow([^COMPLEX$]) +m4trace:configure.in:64: -2- AC_DEFINE_TRACE_LITERAL([SPARSE]) +m4trace:configure.in:64: -2- m4_pattern_allow([^SPARSE$]) +m4trace:configure.in:65: -2- AC_DEFINE_TRACE_LITERAL([COMPLEX]) +m4trace:configure.in:65: -2- m4_pattern_allow([^COMPLEX$]) +m4trace:configure.in:66: -2- AC_DEFINE_TRACE_LITERAL([SPARSE]) +m4trace:configure.in:66: -2- m4_pattern_allow([^SPARSE$]) +m4trace:configure.in:67: -2- AC_DEFINE_TRACE_LITERAL([VUNROLL]) +m4trace:configure.in:67: -2- m4_pattern_allow([^VUNROLL$]) +m4trace:configure.in:68: -2- AC_DEFINE_TRACE_LITERAL([MUNROLL]) +m4trace:configure.in:68: -2- m4_pattern_allow([^MUNROLL$]) +m4trace:configure.in:69: -2- AC_DEFINE_TRACE_LITERAL([SEGMENTED]) +m4trace:configure.in:69: -2- m4_pattern_allow([^SEGMENTED$]) +m4trace:configure.in:70: -2- AC_DEFINE_TRACE_LITERAL([REAL_FLT]) +m4trace:configure.in:70: -2- m4_pattern_allow([^REAL_FLT$]) +m4trace:configure.in:71: -2- AC_DEFINE_TRACE_LITERAL([REAL_DBL]) +m4trace:configure.in:71: -2- m4_pattern_allow([^REAL_DBL$]) +m4trace:configure.in:76: -2- AC_DEFINE_TRACE_LITERAL([U_INT_DEF]) +m4trace:configure.in:76: -2- m4_pattern_allow([^U_INT_DEF$]) +m4trace:configure.in:76: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [../../lib/autoconf/general.m4:2615: AC_TRY_COMPILE is expanded from... +configure.in:76: the top level]) +m4trace:configure.in:80: -1- AC_DEFINE_TRACE_LITERAL([D_MACHEPS]) +m4trace:configure.in:80: -1- m4_pattern_allow([^D_MACHEPS$]) +m4trace:configure.in:83: -1- AC_DEFINE_TRACE_LITERAL([F_MACHEPS]) +m4trace:configure.in:83: -1- m4_pattern_allow([^F_MACHEPS$]) +m4trace:configure.in:87: -1- AC_DEFINE_TRACE_LITERAL([M_MAX_INT]) +m4trace:configure.in:87: -1- m4_pattern_allow([^M_MAX_INT$]) +m4trace:configure.in:94: -2- AC_DEFINE_TRACE_LITERAL([CHAR0ISDBL0]) +m4trace:configure.in:94: -2- m4_pattern_allow([^CHAR0ISDBL0$]) +m4trace:configure.in:94: -1- _m4_warn([obsolete], [The macro `AC_PROGRAM_EGREP' is obsolete. +You should run autoupdate.], [../../lib/autoconf/oldnames.m4:42: AC_PROGRAM_EGREP is expanded from... +configure.in:94: the top level]) +m4trace:configure.in:95: -1- _m4_warn([obsolete], [The macro `AC_HAVE_FUNCS' is obsolete. +You should run autoupdate.], [../../lib/autoconf/functions.m4:160: AC_HAVE_FUNCS is expanded from... +configure.in:95: the top level]) +m4trace:configure.in:95: -1- AH_OUTPUT([HAVE_BCOPY], [/* Define to 1 if you have the `bcopy\' function. */ +@%:@undef HAVE_BCOPY]) +m4trace:configure.in:95: -1- AH_OUTPUT([HAVE_BZERO], [/* Define to 1 if you have the `bzero\' function. */ +@%:@undef HAVE_BZERO]) +m4trace:configure.in:96: -2- AC_DEFINE_TRACE_LITERAL([HAVE_PROTOTYPES]) +m4trace:configure.in:96: -2- m4_pattern_allow([^HAVE_PROTOTYPES$]) +m4trace:configure.in:96: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [../../lib/autoconf/general.m4:2615: AC_TRY_COMPILE is expanded from... +configure.in:96: the top level]) +m4trace:configure.in:97: -1- AC_CONFIG_FILES([makefile make.mex]) +m4trace:configure.in:98: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([LIB@&t@OBJS]) +m4trace:configure.in:98: -1- m4_pattern_allow([^LIB@&t@OBJS$]) +m4trace:configure.in:98: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([LTLIBOBJS]) +m4trace:configure.in:98: -1- m4_pattern_allow([^LTLIBOBJS$]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([top_builddir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([top_build_prefix]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([srcdir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([abs_srcdir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([top_srcdir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([abs_top_srcdir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([builddir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([abs_builddir]) +m4trace:configure.in:98: -1- AC_SUBST_TRACE([abs_top_builddir]) diff --git a/bdfactor.c b/bdfactor.c new file mode 100644 index 0000000..2d06b6d --- /dev/null +++ b/bdfactor.c @@ -0,0 +1,819 @@ + + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Band matrix factorisation routines + */ + +/* bdfactor.c 18/11/93 */ +static char rcsid[] = "$Id: "; + +#include +#include +#include "matrix2.h" + + +/* generate band matrix + for a matrix with n columns, + lb subdiagonals and ub superdiagonals; + + Way of saving a band of a matrix: + first we save subdiagonals (from 0 to lb-1); + then main diagonal (in the lb row) + and then superdiagonals (from lb+1 to lb+ub) + in such a way that the elements which were previously + in one column are now also in one column +*/ +#ifndef ANSI_C +BAND *bd_get(lb,ub,n) +int lb, ub, n; +#else +BAND *bd_get(int lb, int ub, int n) +#endif +{ + BAND *A; + + if (lb < 0 || ub < 0 || n <= 0) + error(E_NEG,"bd_get"); + + if ((A = NEW(BAND)) == (BAND *)NULL) + error(E_MEM,"bd_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_BAND,0,sizeof(BAND)); + mem_numvar(TYPE_BAND,1); + } + + lb = A->lb = min(n-1,lb); + ub = A->ub = min(n-1,ub); + A->mat = m_get(lb+ub+1,n); + return A; +} + +/* bd_free -- frees BAND matrix -- returns (-1) on error and 0 otherwise */ +#ifndef ANSI_C +int bd_free(A) +BAND *A; +#else +int bd_free(BAND *A) +#endif +{ + if ( A == (BAND *)NULL || A->lb < 0 || A->ub < 0 ) + /* don't trust it */ + return (-1); + + if (A->mat) m_free(A->mat); + + if (mem_info_is_on()) { + mem_bytes(TYPE_BAND,sizeof(BAND),0); + mem_numvar(TYPE_BAND,-1); + } + + free((char *)A); + return 0; +} + + +/* resize band matrix */ +#ifndef ANSI_C +BAND *bd_resize(A,new_lb,new_ub,new_n) +BAND *A; +int new_lb,new_ub,new_n; +#else +BAND *bd_resize(BAND *A, int new_lb, int new_ub, int new_n) +#endif +{ + int lb,ub,i,j,l,shift,umin; + Real **Av; + + if (new_lb < 0 || new_ub < 0 || new_n <= 0) + error(E_NEG,"bd_resize"); + if ( ! A ) + return bd_get(new_lb,new_ub,new_n); + if ( A->lb+A->ub+1 > A->mat->m ) + error(E_INTERN,"bd_resize"); + + if ( A->lb == new_lb && A->ub == new_ub && A->mat->n == new_n ) + return A; + + lb = A->lb; + ub = A->ub; + Av = A->mat->me; + umin = min(ub,new_ub); + + /* ensure that unused triangles at edges are zero'd */ + + for ( i = 0; i < lb; i++ ) + for ( j = A->mat->n - lb + i; j < A->mat->n; j++ ) + Av[i][j] = 0.0; + for ( i = lb+1,l=1; l <= umin; i++,l++ ) + for ( j = 0; j < l; j++ ) + Av[i][j] = 0.0; + + new_lb = A->lb = min(new_lb,new_n-1); + new_ub = A->ub = min(new_ub,new_n-1); + A->mat = m_resize(A->mat,new_lb+new_ub+1,new_n); + Av = A->mat->me; + + /* if new_lb != lb then move the rows to get the main diag + in the new_lb row */ + + if (new_lb > lb) { + shift = new_lb-lb; + + for (i=lb+umin, l=i+shift; i >= 0; i--,l--) + MEM_COPY(Av[i],Av[l],new_n*sizeof(Real)); + for (l=shift-1; l >= 0; l--) + __zero__(Av[l],new_n); + } + else if (new_lb < lb) { + shift = lb - new_lb; + + for (i=shift, l=0; i <= lb+umin; i++,l++) + MEM_COPY(Av[i],Av[l],new_n*sizeof(Real)); + for (i=lb+umin+1; i <= new_lb+new_ub; i++) + __zero__(Av[i],new_n); + } + + return A; +} + + +/* bd_copy -- copies band matrix A to B, returning B + -- if B is NULL, create + -- B is set to the correct size */ +#ifndef ANSI_C +BAND *bd_copy(A,B) +BAND *A,*B; +#else +BAND *bd_copy(const BAND *A, BAND *B) +#endif +{ + int lb,ub,i,j,n; + + if ( !A ) + error(E_NULL,"bd_copy"); + + if (A == B) return B; + + n = A->mat->n; + if ( !B ) + B = bd_get(A->lb,A->ub,n); + else if (B->lb != A->lb || B->ub != A->ub || B->mat->n != n ) + B = bd_resize(B,A->lb,A->ub,n); + + if (A->mat == B->mat) return B; + ub = B->ub = A->ub; + lb = B->lb = A->lb; + + for ( i=0, j=n-lb; i <= lb; i++, j++ ) + MEM_COPY(A->mat->me[i],B->mat->me[i],j*sizeof(Real)); + + for ( i=lb+1, j=1; i <= lb+ub; i++, j++ ) + MEM_COPY(A->mat->me[i]+j,B->mat->me[i]+j,(n - j)*sizeof(Real)); + + return B; +} + + +/* copy band matrix bA to a square matrix A returning A */ +#ifndef ANSI_C +MAT *band2mat(bA,A) +BAND *bA; +MAT *A; +#else +MAT *band2mat(const BAND *bA, MAT *A) +#endif +{ + int i,j,l,n,n1; + int lb, ub; + Real **bmat; + + if ( !bA ) + error(E_NULL,"band2mat"); + if ( bA->mat == A ) + error(E_INSITU,"band2mat"); + + ub = bA->ub; + lb = bA->lb; + n = bA->mat->n; + n1 = n-1; + bmat = bA->mat->me; + + A = m_resize(A,n,n); + m_zero(A); + + for (j=0; j < n; j++) + for (i=min(n1,j+lb),l=lb+j-i; i >= max(0,j-ub); i--,l++) + A->me[i][j] = bmat[l][j]; + + return A; +} + +/* copy a square matrix to a band matrix with + lb subdiagonals and ub superdiagonals */ +#ifndef ANSI_C +BAND *mat2band(A,lb,ub,bA) +BAND *bA; +MAT *A; +int lb, ub; +#else +BAND *mat2band(const MAT *A, int lb, int ub,BAND *bA) +#endif +{ + int i, j, l, n1; + Real **bmat; + + if (! A ) + error(E_NULL,"mat2band"); + if (ub < 0 || lb < 0) + error(E_SIZES,"mat2band"); + if ( bA != (BAND *)NULL && bA->mat == A ) + error(E_INSITU,"mat2band"); + + n1 = A->n-1; + lb = min(n1,lb); + ub = min(n1,ub); + bA = bd_resize(bA,lb,ub,n1+1); + bmat = bA->mat->me; + + for (j=0; j <= n1; j++) + for (i=min(n1,j+lb),l=lb+j-i; i >= max(0,j-ub); i--,l++) + bmat[l][j] = A->me[i][j]; + + return bA; +} + + + +/* transposition of matrix in; + out - matrix after transposition; + can be done in situ +*/ +#ifndef ANSI_C +BAND *bd_transp(in,out) +BAND *in, *out; +#else +BAND *bd_transp(const BAND *in, BAND *out) +#endif +{ + int i, j, jj, l, k, lb, ub, lub, n, n1; + int in_situ; + Real **in_v, **out_v; + + if ( in == (BAND *)NULL || in->mat == (MAT *)NULL ) + error(E_NULL,"bd_transp"); + + lb = in->lb; + ub = in->ub; + lub = lb+ub; + n = in->mat->n; + n1 = n-1; + + in_situ = ( in == out ); + if ( ! in_situ ) + out = bd_resize(out,ub,lb,n); + else + { /* only need to swap lb and ub fields */ + out->lb = ub; + out->ub = lb; + } + + in_v = in->mat->me; + + if (! in_situ) { + int sh_in,sh_out; + + out_v = out->mat->me; + for (i=0, l=lub, k=lb-i; i <= lub; i++,l--,k--) { + sh_in = max(-k,0); + sh_out = max(k,0); + MEM_COPY(&(in_v[i][sh_in]),&(out_v[l][sh_out]), + (n-sh_in-sh_out)*sizeof(Real)); + /********************************** + for (j=n1-sh_out, jj=n1-sh_in; j >= sh_in; j--,jj--) { + out_v[l][jj] = in_v[i][j]; + } + **********************************/ + } + } + else if (ub == lb) { + Real tmp; + + for (i=0, l=lub, k=lb-i; i < lb; i++,l--,k--) { + for (j=n1-k, jj=n1; j >= 0; j--,jj--) { + tmp = in_v[l][jj]; + in_v[l][jj] = in_v[i][j]; + in_v[i][j] = tmp; + } + } + } + else if (ub > lb) { /* hence i-ub <= 0 & l-lb >= 0 */ + int p,pp,lbi; + + for (i=0, l=lub; i < (lub+1)/2; i++,l--) { + lbi = lb-i; + for (j=l-lb, jj=0, p=max(-lbi,0), pp = max(l-ub,0); j <= n1; + j++,jj++,p++,pp++) { + in_v[l][pp] = in_v[i][p]; + in_v[i][jj] = in_v[l][j]; + } + for ( ; p <= n1-max(lbi,0); p++,pp++) + in_v[l][pp] = in_v[i][p]; + } + + if (lub%2 == 0) { /* shift only */ + i = lub/2; + for (j=max(i-lb,0), jj=0; jj <= n1-ub+i; j++,jj++) + in_v[i][jj] = in_v[i][j]; + } + } + else { /* ub < lb, hence ub-l <= 0 & lb-i >= 0 */ + int p,pp,ubi; + + for (i=0, l=lub; i < (lub+1)/2; i++,l--) { + ubi = i-ub; + for (j=n1-max(lb-l,0), jj=n1-max(-ubi,0), p=n1-lb+i, pp=n1; + p >= 0; j--, jj--, pp--, p--) { + in_v[i][jj] = in_v[l][j]; + in_v[l][pp] = in_v[i][p]; + } + for ( ; jj >= max(ubi,0); j--, jj--) + in_v[i][jj] = in_v[l][j]; + } + + if (lub%2 == 0) { /* shift only */ + i = lub/2; + for (j=n1-lb+i, jj=n1-max(ub-i,0); j >= 0; j--, jj--) + in_v[i][jj] = in_v[i][j]; + } + } + + return out; +} + +/* bdv_mltadd -- band matrix-vector multiply and add + -- returns out <- x + s.bA.y + -- if y is NULL then create y (as zero vector) + -- error if either A or x is NULL */ +#ifndef ANSI_C +VEC *bdv_mltadd(x,y,bA,s,out) + BAND *bA; + VEC *x, *y; + double s; + VEC *out; +#else +VEC *bdv_mltadd(const VEC *x, const VEC *y, const BAND *bA, + double s, VEC *out) +#endif +{ + int i, j; + + if ( ! bA || ! x || ! y ) + error(E_NULL,"bdv_mltadd"); + if ( bA->mat->n != x->dim || y->dim != x->dim ) + error(E_SIZES,"bdv_mltadd"); + if ( ! out || out->dim != x->dim ) + out = v_resize(out,x->dim); + out = v_copy(x,out); + + for ( j = 0; j < x->dim; j++ ) + for ( i = max(j-bA->ub,0); i <= j+bA->lb && i < x->dim; i++ ) + out->ve[i] += s*bd_get_val(bA,i,j)*y->ve[j]; + + return out; +} + +/* vbd_mltadd -- band matrix-vector multiply and add + -- returns out^T <- x^T + s.y^T.bA + -- if out is NULL then create out (as zero vector) + -- error if either bA or x is NULL */ +#ifndef ANSI_C +VEC *vbd_mltadd(x,y,bA,s,out) + BAND *bA; + VEC *x, *y; + double s; + VEC *out; +#else +VEC *vbd_mltadd(const VEC *x, const VEC *y, const BAND *bA, + double s, VEC *out) +#endif +{ + int i, j; + + if ( ! bA || ! x || ! y ) + error(E_NULL,"vbd_mltadd"); + if ( bA->mat->n != x->dim || y->dim != x->dim ) + error(E_SIZES,"vbd_mltadd"); + if ( ! out || out->dim != x->dim ) + out = v_resize(out,x->dim); + out = v_copy(x,out); + + for ( j = 0; j < x->dim; j++ ) + for ( i = max(j-bA->ub,0); i <= j+bA->lb && i < x->dim; i++ ) + out->ve[j] += s*bd_get_val(bA,i,j)*y->ve[i]; + + return out; +} + +/* bd_zero -- zeros band matrix A which is returned */ +#ifndef ANSI_C +BAND *bd_zero(A) +BAND *A; +#else +BAND *bd_zero(BAND *A) +#endif +{ + if ( ! A ) + error(E_NULL,"bd_zero"); + + m_zero(A->mat); + return A; +} + +/* bds_mltadd -- returns OUT <- A+alpha*B + -- OUT is created (as zero) if NULL + -- if OUT is not the correct size, it is re-sized before the operation + -- if A or B are null, and error is generated */ +#ifndef ANSI_C +BAND *bds_mltadd(A,B,alpha,OUT) +BAND *A, *B, *OUT; +Real alpha; +#else +BAND *bds_mltadd(const BAND *A, const BAND *B, double alpha, BAND *OUT) +#endif +{ + int i; + + if ( ! A || ! B ) + error(E_NULL,"bds_mltadd"); + if ( A->mat->n != B->mat->n ) + error(E_SIZES,"bds_mltadd"); + if ( A == OUT || B == OUT ) + error(E_INSITU,"bds_mltadd"); + + OUT = bd_copy(A,OUT); + OUT = bd_resize(OUT,max(A->lb,B->lb),max(A->ub,B->ub),A->mat->n); + for ( i = 0; i <= B->lb + B->ub; i++ ) + __mltadd__(OUT->mat->me[i+OUT->lb-B->lb],B->mat->me[i],alpha,B->mat->n); + + return OUT; +} + +/* sbd_mlt -- returns OUT <- s.A */ +#ifndef ANSI_C +BAND *sbd_mlt(Real s, BAND *A, BAND *OUT) +#else +BAND *sbd_mlt(Real s, const BAND *A, BAND *OUT) +#endif +{ + if ( ! A ) + error(E_NULL,"sbd_mlt"); + + OUT = bd_resize(OUT,A->lb,A->ub,A->mat->n); + sm_mlt(s,A->mat,OUT->mat); + + return OUT; +} + +/* bdLUfactor -- gaussian elimination with partial pivoting + -- on entry, the matrix A in band storage with elements + in rows 0 to lb+ub; + The jth column of A is stored in the jth column of + band A (bA) as follows: + bA->mat->me[lb+j-i][j] = A->me[i][j] for + max(0,j-lb) <= i <= min(A->n-1,j+ub); + -- on exit: U is stored as an upper triangular matrix + with lb+ub superdiagonals in rows lb to 2*lb+ub, + and the matrix L is stored in rows 0 to lb-1. + Matrix U is permuted, whereas L is not permuted !!! + Therefore we save some memory. + */ +#ifndef ANSI_C +BAND *bdLUfactor(bA,pivot) +BAND *bA; +PERM *pivot; +#else +BAND *bdLUfactor(BAND *bA, PERM *pivot) +#endif +{ + int i, j, k, l, n, n1, lb, ub, lub, k_end, k_lub; + int i_max, shift; + Real **bA_v; + Real max1, temp; + + if ( bA==(BAND *)NULL || pivot==(PERM *)NULL ) + error(E_NULL,"bdLUfactor"); + + lb = bA->lb; + ub = bA->ub; + lub = lb+ub; + n = bA->mat->n; + n1 = n-1; + lub = lb+ub; + + if ( pivot->size != n ) + error(E_SIZES,"bdLUfactor"); + + + /* initialise pivot with identity permutation */ + for ( i=0; i < n; i++ ) + pivot->pe[i] = i; + + /* extend band matrix */ + /* extended part is filled with zeros */ + bA = bd_resize(bA,lb,min(n1,lub),n); + bA_v = bA->mat->me; + + + /* main loop */ + + for ( k=0; k < n1; k++ ) + { + k_end = max(0,lb+k-n1); + k_lub = min(k+lub,n1); + + /* find the best pivot row */ + + max1 = 0.0; + i_max = -1; + for ( i=lb; i >= k_end; i-- ) { + temp = fabs(bA_v[i][k]); + if ( temp > max1 ) + { max1 = temp; i_max = i; } + } + + /* if no pivot then ignore column k... */ + if ( i_max == -1 ) + continue; + + /* do we pivot ? */ + if ( i_max != lb ) /* yes we do... */ + { + /* save transposition using non-shifted indices */ + shift = lb-i_max; + px_transp(pivot,k+shift,k); + for ( i=lb, j=k; j <= k_lub; i++,j++ ) + { + temp = bA_v[i][j]; + bA_v[i][j] = bA_v[i-shift][j]; + bA_v[i-shift][j] = temp; + } + } + + /* row operations */ + for ( i=lb-1; i >= k_end; i-- ) { + temp = bA_v[i][k] /= bA_v[lb][k]; + shift = lb-i; + for ( j=k+1,l=i+1; j <= k_lub; l++,j++ ) + bA_v[l][j] -= temp*bA_v[l+shift][j]; + } + } + + return bA; +} + + +/* bdLUsolve -- given an LU factorisation in bA, solve bA*x=b */ +/* pivot is changed upon return */ +#ifndef ANSI_C +VEC *bdLUsolve(bA,pivot,b,x) +BAND *bA; +PERM *pivot; +VEC *b,*x; +#else +VEC *bdLUsolve(const BAND *bA, PERM *pivot, const VEC *b, VEC *x) +#endif +{ + int i,j,l,n,n1,pi,lb,ub,jmin, maxj; + Real c; + Real **bA_v; + + if ( bA==(BAND *)NULL || b==(VEC *)NULL || pivot==(PERM *)NULL ) + error(E_NULL,"bdLUsolve"); + if ( bA->mat->n != b->dim || bA->mat->n != pivot->size) + error(E_SIZES,"bdLUsolve"); + + lb = bA->lb; + ub = bA->ub; + n = b->dim; + n1 = n-1; + bA_v = bA->mat->me; + + x = v_resize(x,b->dim); + px_vec(pivot,b,x); + + /* solve Lx = b; implicit diagonal = 1 + L is not permuted, therefore it must be permuted now + */ + + px_inv(pivot,pivot); + for (j=0; j < n; j++) { + jmin = j+1; + c = x->ve[j]; + maxj = max(0,j+lb-n1); + for (i=jmin,l=lb-1; l >= maxj; i++,l--) { + if ( (pi = pivot->pe[i]) < jmin) + pi = pivot->pe[i] = pivot->pe[pi]; + x->ve[pi] -= bA_v[l][j]*c; + } + } + + /* solve Ux = b; explicit diagonal */ + + x->ve[n1] /= bA_v[lb][n1]; + for (i=n-2; i >= 0; i--) { + c = x->ve[i]; + for (j=min(n1,i+ub), l=lb+j-i; j > i; j--,l--) + c -= bA_v[l][j]*x->ve[j]; + x->ve[i] = c/bA_v[lb][i]; + } + + return (x); +} + +/* LDLfactor -- L.D.L' factorisation of A in-situ; + A is a band matrix + it works using only lower bandwidth & main diagonal + so it is possible to set A->ub = 0 + */ +#ifndef ANSI_C +BAND *bdLDLfactor(A) +BAND *A; +#else +BAND *bdLDLfactor(BAND *A) +#endif +{ + int i,j,k,n,n1,lb,ki,jk,ji,lbkm,lbkp; + Real **Av; + Real c, cc; + + if ( ! A ) + error(E_NULL,"bdLDLfactor"); + + if (A->lb == 0) return A; + + lb = A->lb; + n = A->mat->n; + n1 = n-1; + Av = A->mat->me; + + for (k=0; k < n; k++) { + lbkm = lb-k; + lbkp = lb+k; + + /* matrix D */ + c = Av[lb][k]; + for (j=max(0,-lbkm), jk=lbkm+j; j < k; j++, jk++) { + cc = Av[jk][j]; + c -= Av[lb][j]*cc*cc; + } + if (c == 0.0) + error(E_SING,"bdLDLfactor"); + Av[lb][k] = c; + + /* matrix L */ + + for (i=min(n1,lbkp), ki=lbkp-i; i > k; i--,ki++) { + c = Av[ki][k]; + for (j=max(0,i-lb), ji=lb+j-i, jk=lbkm+j; j < k; + j++, ji++, jk++) + c -= Av[lb][j]*Av[ji][j]*Av[jk][j]; + Av[ki][k] = c/Av[lb][k]; + } + } + + return A; +} + +/* solve A*x = b, where A is factorized by + Choleski LDL^T factorization */ +#ifndef ANSI_C +VEC *bdLDLsolve(A,b,x) +BAND *A; +VEC *b, *x; +#else +VEC *bdLDLsolve(const BAND *A, const VEC *b, VEC *x) +#endif +{ + int i,j,l,n,n1,lb,ilb; + Real **Av, *Avlb; + Real c; + + if ( ! A || ! b ) + error(E_NULL,"bdLDLsolve"); + if ( A->mat->n != b->dim ) + error(E_SIZES,"bdLDLsolve"); + + n = A->mat->n; + n1 = n-1; + x = v_resize(x,n); + lb = A->lb; + Av = A->mat->me; + Avlb = Av[lb]; + + /* solve L*y = b */ + x->ve[0] = b->ve[0]; + for (i=1; i < n; i++) { + ilb = i-lb; + c = b->ve[i]; + for (j=max(0,ilb), l=j-ilb; j < i; j++,l++) + c -= Av[l][j]*x->ve[j]; + x->ve[i] = c; + } + + /* solve D*z = y */ + for (i=0; i < n; i++) + x->ve[i] /= Avlb[i]; + + /* solve L^T*x = z */ + for (i=n-2; i >= 0; i--) { + ilb = i+lb; + c = x->ve[i]; + for (j=min(n1,ilb), l=ilb-j; j > i; j--,l++) + c -= Av[l][i]*x->ve[j]; + x->ve[i] = c; + } + + return x; +} + + +/* ****************************************************** + This function is a contribution from Ruediger Franke. + His e-mail addres is: Ruediger.Franke@rz.tu-ilmenau.de + + ****************************************************** +*/ + +/* bd_mv_mlt -- + * computes out = A * x + * may not work in situ (x != out) + */ + +VEC *bd_mv_mlt(A, x, out) +BAND *A; +VEC *x, *out; +{ + int i, j, j_end, k; + int start_idx, end_idx; + int n, m, lb, ub; + Real **A_me; + Real *x_ve; + Real sum; + + if (!A || !x) + error(E_NULL,"bd_mv_mlt"); + if (x->dim != A->mat->n) + error(E_SIZES,"bd_mv_mlt"); + if (!out || out->dim != A->mat->n) + out = v_resize(out, A->mat->n); + if (out == x) + error(E_INSITU,"bd_mv_mlt"); + + n = A->mat->n; + m = A->mat->m; + lb = A->lb; + ub = A->ub; + A_me = A->mat->me; + start_idx = lb; + end_idx = m + n-1 - ub; + for (i=0; ive + k; + sum = 0.0; + for (; j < j_end; j++, k++) + sum += A_me[j][k] * *x_ve++; + out->ve[i] = sum; + } + + return out; +} + + + diff --git a/bkpfacto.c b/bkpfacto.c new file mode 100644 index 0000000..8eecdb5 --- /dev/null +++ b/bkpfacto.c @@ -0,0 +1,324 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. +*/ + +static char rcsid[] = "$Id: bkpfacto.c,v 1.7 1994/01/13 05:45:50 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + +#define btos(x) ((x) ? "TRUE" : "FALSE") + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +#define alpha 0.6403882032022076 /* = (1+sqrt(17))/8 */ + +/* sqr -- returns square of x -- utility function */ +double sqr(x) +double x; +{ return x*x; } + +/* interchange -- a row/column swap routine */ +static void interchange(A,i,j) +MAT *A; /* assumed != NULL & also SQUARE */ +int i, j; /* assumed in range */ +{ + Real **A_me, tmp; + int k, n; + + A_me = A->me; n = A->n; + if ( i == j ) + return; + if ( i > j ) + { k = i; i = j; j = k; } + for ( k = 0; k < i; k++ ) + { + /* tmp = A_me[k][i]; */ + tmp = m_entry(A,k,i); + /* A_me[k][i] = A_me[k][j]; */ + m_set_val(A,k,i,m_entry(A,k,j)); + /* A_me[k][j] = tmp; */ + m_set_val(A,k,j,tmp); + } + for ( k = j+1; k < n; k++ ) + { + /* tmp = A_me[j][k]; */ + tmp = m_entry(A,j,k); + /* A_me[j][k] = A_me[i][k]; */ + m_set_val(A,j,k,m_entry(A,i,k)); + /* A_me[i][k] = tmp; */ + m_set_val(A,i,k,tmp); + } + for ( k = i+1; k < j; k++ ) + { + /* tmp = A_me[k][j]; */ + tmp = m_entry(A,k,j); + /* A_me[k][j] = A_me[i][k]; */ + m_set_val(A,k,j,m_entry(A,i,k)); + /* A_me[i][k] = tmp; */ + m_set_val(A,i,k,tmp); + } + /* tmp = A_me[i][i]; */ + tmp = m_entry(A,i,i); + /* A_me[i][i] = A_me[j][j]; */ + m_set_val(A,i,i,m_entry(A,j,j)); + /* A_me[j][j] = tmp; */ + m_set_val(A,j,j,tmp); +} + +/* BKPfactor -- Bunch-Kaufman-Parlett factorisation of A in-situ + -- A is factored into the form P'AP = MDM' where + P is a permutation matrix, M lower triangular and D is block + diagonal with blocks of size 1 or 2 + -- P is stored in pivot; blocks[i]==i iff D[i][i] is a block */ +#ifndef ANSI_C +MAT *BKPfactor(A,pivot,blocks) +MAT *A; +PERM *pivot, *blocks; +#else +MAT *BKPfactor(MAT *A, PERM *pivot, PERM *blocks) +#endif +{ + int i, j, k, n, onebyone, r; + Real **A_me, aii, aip1, aip1i, lambda, sigma, tmp; + Real det, s, t; + + if ( ! A || ! pivot || ! blocks ) + error(E_NULL,"BKPfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"BKPfactor"); + if ( A->m != pivot->size || pivot->size != blocks->size ) + error(E_SIZES,"BKPfactor"); + + n = A->n; + A_me = A->me; + px_ident(pivot); px_ident(blocks); + + for ( i = 0; i < n; i = onebyone ? i+1 : i+2 ) + { + /* printf("# Stage: %d\n",i); */ + aii = fabs(m_entry(A,i,i)); + lambda = 0.0; r = (i+1 < n) ? i+1 : i; + for ( k = i+1; k < n; k++ ) + { + tmp = fabs(m_entry(A,i,k)); + if ( tmp >= lambda ) + { + lambda = tmp; + r = k; + } + } + /* printf("# lambda = %g, r = %d\n", lambda, r); */ + /* printf("# |A[%d][%d]| = %g\n",r,r,fabs(m_entry(A,r,r))); */ + + /* determine if 1x1 or 2x2 block, and do pivoting if needed */ + if ( aii >= alpha*lambda ) + { + onebyone = TRUE; + goto dopivot; + } + /* compute sigma */ + sigma = 0.0; + for ( k = i; k < n; k++ ) + { + if ( k == r ) + continue; + tmp = ( k > r ) ? fabs(m_entry(A,r,k)) : + fabs(m_entry(A,k,r)); + if ( tmp > sigma ) + sigma = tmp; + } + if ( aii*sigma >= alpha*sqr(lambda) ) + onebyone = TRUE; + else if ( fabs(m_entry(A,r,r)) >= alpha*sigma ) + { + /* printf("# Swapping rows/cols %d and %d\n",i,r); */ + interchange(A,i,r); + px_transp(pivot,i,r); + onebyone = TRUE; + } + else + { + /* printf("# Swapping rows/cols %d and %d\n",i+1,r); */ + interchange(A,i+1,r); + px_transp(pivot,i+1,r); + px_transp(blocks,i,i+1); + onebyone = FALSE; + } + /* printf("onebyone = %s\n",btos(onebyone)); */ + /* printf("# Matrix so far (@checkpoint A) =\n"); */ + /* m_output(A); */ + /* printf("# pivot =\n"); px_output(pivot); */ + /* printf("# blocks =\n"); px_output(blocks); */ + +dopivot: + if ( onebyone ) + { /* do one by one block */ + if ( m_entry(A,i,i) != 0.0 ) + { + aii = m_entry(A,i,i); + for ( j = i+1; j < n; j++ ) + { + tmp = m_entry(A,i,j)/aii; + for ( k = j; k < n; k++ ) + m_sub_val(A,j,k,tmp*m_entry(A,i,k)); + m_set_val(A,i,j,tmp); + } + } + } + else /* onebyone == FALSE */ + { /* do two by two block */ + det = m_entry(A,i,i)*m_entry(A,i+1,i+1)-sqr(m_entry(A,i,i+1)); + /* Must have det < 0 */ + /* printf("# det = %g\n",det); */ + aip1i = m_entry(A,i,i+1)/det; + aii = m_entry(A,i,i)/det; + aip1 = m_entry(A,i+1,i+1)/det; + for ( j = i+2; j < n; j++ ) + { + s = - aip1i*m_entry(A,i+1,j) + aip1*m_entry(A,i,j); + t = - aip1i*m_entry(A,i,j) + aii*m_entry(A,i+1,j); + for ( k = j; k < n; k++ ) + m_sub_val(A,j,k,m_entry(A,i,k)*s + m_entry(A,i+1,k)*t); + m_set_val(A,i,j,s); + m_set_val(A,i+1,j,t); + } + } + /* printf("# Matrix so far (@checkpoint B) =\n"); */ + /* m_output(A); */ + /* printf("# pivot =\n"); px_output(pivot); */ + /* printf("# blocks =\n"); px_output(blocks); */ + } + + /* set lower triangular half */ + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < i; j++ ) + m_set_val(A,i,j,m_entry(A,j,i)); + + return A; +} + +/* BKPsolve -- solves A.x = b where A has been factored a la BKPfactor() + -- returns x, which is created if NULL */ +#ifndef ANSI_C +VEC *BKPsolve(A,pivot,block,b,x) +MAT *A; +PERM *pivot, *block; +VEC *b, *x; +#else +VEC *BKPsolve(const MAT *A, PERM *pivot, const PERM *block, + const VEC *b, VEC *x) +#endif +{ + STATIC VEC *tmp=VNULL; /* dummy storage needed */ + int i, j, n, onebyone; + Real **A_me, a11, a12, a22, b1, b2, det, sum, *tmp_ve, tmp_diag; + + if ( ! A || ! pivot || ! block || ! b ) + error(E_NULL,"BKPsolve"); + if ( A->m != A->n ) + error(E_SQUARE,"BKPsolve"); + n = A->n; + if ( b->dim != n || pivot->size != n || block->size != n ) + error(E_SIZES,"BKPsolve"); + x = v_resize(x,n); + tmp = v_resize(tmp,n); + MEM_STAT_REG(tmp,TYPE_VEC); + + A_me = A->me; tmp_ve = tmp->ve; + + px_vec(pivot,b,tmp); + /* solve for lower triangular part */ + for ( i = 0; i < n; i++ ) + { + sum = v_entry(tmp,i); + if ( block->pe[i] < i ) + for ( j = 0; j < i-1; j++ ) + sum -= m_entry(A,i,j)*v_entry(tmp,j); + else + for ( j = 0; j < i; j++ ) + sum -= m_entry(A,i,j)*v_entry(tmp,j); + v_set_val(tmp,i,sum); + } + /* printf("# BKPsolve: solving L part: tmp =\n"); v_output(tmp); */ + /* solve for diagonal part */ + for ( i = 0; i < n; i = onebyone ? i+1 : i+2 ) + { + onebyone = ( block->pe[i] == i ); + if ( onebyone ) + { + tmp_diag = m_entry(A,i,i); + if ( tmp_diag == 0.0 ) + error(E_SING,"BKPsolve"); + /* tmp_ve[i] /= tmp_diag; */ + v_set_val(tmp,i,v_entry(tmp,i) / tmp_diag); + } + else + { + a11 = m_entry(A,i,i); + a22 = m_entry(A,i+1,i+1); + a12 = m_entry(A,i+1,i); + b1 = v_entry(tmp,i); b2 = v_entry(tmp,i+1); + det = a11*a22-a12*a12; /* < 0 : see BKPfactor() */ + if ( det == 0.0 ) + error(E_SING,"BKPsolve"); + det = 1/det; + v_set_val(tmp,i,det*(a22*b1-a12*b2)); + v_set_val(tmp,i+1,det*(a11*b2-a12*b1)); + } + } + /* printf("# BKPsolve: solving D part: tmp =\n"); v_output(tmp); */ + /* solve for transpose of lower traingular part */ + for ( i = n-1; i >= 0; i-- ) + { /* use symmetry of factored form to get stride 1 */ + sum = v_entry(tmp,i); + if ( block->pe[i] > i ) + for ( j = i+2; j < n; j++ ) + sum -= m_entry(A,i,j)*v_entry(tmp,j); + else + for ( j = i+1; j < n; j++ ) + sum -= m_entry(A,i,j)*v_entry(tmp,j); + v_set_val(tmp,i,sum); + } + + /* printf("# BKPsolve: solving L^T part: tmp =\n");v_output(tmp); */ + /* and do final permutation */ + x = pxinv_vec(pivot,tmp,x); + +#ifdef THREADSAFE + V_FREE(tmp); +#endif + + return x; +} + + + diff --git a/chfactor.c b/chfactor.c new file mode 100644 index 0000000..f60e4e9 --- /dev/null +++ b/chfactor.c @@ -0,0 +1,242 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. +*/ + +/* CHfactor.c 1.2 11/25/87 */ +static char rcsid[] = "$Id: chfactor.c,v 1.2 1994/01/13 05:36:36 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* CHfactor -- Cholesky L.L' factorisation of A in-situ */ +#ifndef ANSI_C +MAT *CHfactor(A) +MAT *A; +#else +MAT *CHfactor(MAT *A) +#endif +{ + unsigned int i, j, k, n; + Real **A_ent, *A_piv, *A_row, sum, tmp; + + if ( A==(MAT *)NULL ) + error(E_NULL,"CHfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"CHfactor"); + n = A->n; A_ent = A->me; + + for ( k=0; km != A->n || A->n != b->dim ) + error(E_SIZES,"CHsolve"); + x = v_resize(x,b->dim); + Lsolve(A,b,x,0.0); + Usolve(A,x,x,0.0); + + return (x); +} + +/* LDLfactor -- L.D.L' factorisation of A in-situ */ +#ifndef ANSI_C +MAT *LDLfactor(A) +MAT *A; +#else +MAT *LDLfactor(MAT *A) +#endif +{ + unsigned int i, k, n, p; + Real **A_ent; + Real d, sum; + STATIC VEC *r = VNULL; + + if ( ! A ) + error(E_NULL,"LDLfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"LDLfactor"); + n = A->n; A_ent = A->me; + r = v_resize(r,n); + MEM_STAT_REG(r,TYPE_VEC); + + for ( k = 0; k < n; k++ ) + { + sum = 0.0; + for ( p = 0; p < k; p++ ) + { + r->ve[p] = A_ent[p][p]*A_ent[k][p]; + sum += r->ve[p]*A_ent[k][p]; + } + d = A_ent[k][k] -= sum; + + if ( d == 0.0 ) + error(E_SING,"LDLfactor"); + for ( i = k+1; i < n; i++ ) + { + sum = __ip__(A_ent[i],r->ve,(int)k); + /**************************************** + sum = 0.0; + for ( p = 0; p < k; p++ ) + sum += A_ent[i][p]*r->ve[p]; + ****************************************/ + A_ent[i][k] = (A_ent[i][k] - sum)/d; + } + } + +#ifdef THREADSAFE + V_FREE(r); +#endif + + return A; +} + +/* LDLsolve -- solves linear system A.x = b with A factored by LDLfactor() + -- returns x, which is created if it is NULL on entry */ +#ifndef ANSI_C +VEC *LDLsolve(LDL,b,x) +MAT *LDL; +VEC *b, *x; +#else +VEC *LDLsolve(const MAT *LDL, const VEC *b, VEC *x) +#endif +{ + if ( ! LDL || ! b ) + error(E_NULL,"LDLsolve"); + if ( LDL->m != LDL->n ) + error(E_SQUARE,"LDLsolve"); + if ( LDL->m != b->dim ) + error(E_SIZES,"LDLsolve"); + x = v_resize(x,b->dim); + + Lsolve(LDL,b,x,1.0); + Dsolve(LDL,x,x); + LTsolve(LDL,x,x,1.0); + + return x; +} + +/* MCHfactor -- Modified Cholesky L.L' factorisation of A in-situ */ +#ifndef ANSI_C +MAT *MCHfactor(A,tol) +MAT *A; +double tol; +#else +MAT *MCHfactor(MAT *A, double tol) +#endif +{ + unsigned int i, j, k, n; + Real **A_ent, *A_piv, *A_row, sum, tmp; + + if ( A==(MAT *)NULL ) + error(E_NULL,"MCHfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"MCHfactor"); + if ( tol <= 0.0 ) + error(E_RANGE,"MCHfactor"); + n = A->n; A_ent = A->me; + + for ( k=0; k&5 +i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) +Copyright (C) 2007 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +configure:2562: $? = 0 +configure:2551: gcc -v >&5 +Using built-in specs. +Target: i686-apple-darwin11 +Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.11~148/src/configure --disable-checking --enable-werror --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.11~148/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1 +Thread model: posix +gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) +configure:2562: $? = 0 +configure:2551: gcc -V >&5 +llvm-gcc-4.2: argument to `-V' is missing +configure:2562: $? = 1 +configure:2551: gcc -qversion >&5 +i686-apple-darwin11-llvm-gcc-4.2: no input files +configure:2562: $? = 1 +configure:2582: checking whether the C compiler works +configure:2604: gcc conftest.c >&5 +configure:2608: $? = 0 +configure:2656: result: yes +configure:2659: checking for C compiler default output file name +configure:2661: result: a.out +configure:2667: checking for suffix of executables +configure:2674: gcc -o conftest conftest.c >&5 +configure:2678: $? = 0 +configure:2700: result: +configure:2722: checking whether we are cross compiling +configure:2730: gcc -o conftest conftest.c >&5 +configure:2734: $? = 0 +configure:2741: ./conftest +configure:2745: $? = 0 +configure:2760: result: no +configure:2765: checking for suffix of object files +configure:2787: gcc -c conftest.c >&5 +configure:2791: $? = 0 +configure:2812: result: o +configure:2816: checking whether we are using the GNU C compiler +configure:2835: gcc -c conftest.c >&5 +configure:2835: $? = 0 +configure:2844: result: yes +configure:2853: checking whether gcc accepts -g +configure:2873: gcc -c -g conftest.c >&5 +configure:2873: $? = 0 +configure:2914: result: yes +configure:2931: checking for gcc option to accept ISO C89 +configure:2994: gcc -c -g -O2 conftest.c >&5 +configure:2994: $? = 0 +configure:3007: result: none needed +configure:3032: checking how to run the C preprocessor +configure:3063: gcc -E conftest.c +configure:3063: $? = 0 +configure:3077: gcc -E conftest.c +conftest.c:9:28: error: ac_nonexistent.h: No such file or directory +configure:3077: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| /* end confdefs.h. */ +| #include +configure:3102: result: gcc -E +configure:3122: gcc -E conftest.c +configure:3122: $? = 0 +configure:3136: gcc -E conftest.c +conftest.c:9:28: error: ac_nonexistent.h: No such file or directory +configure:3136: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| /* end confdefs.h. */ +| #include +configure:3168: checking for gcc option to accept ISO C99 +configure:3317: gcc -c -g -O2 conftest.c >&5 +conftest.c:59: error: expected ';', ',' or ')' before 'text' +conftest.c: In function 'main': +conftest.c:113: error: nested functions are disabled, use -fnested-functions to re-enable +conftest.c:113: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'newvar' +conftest.c:113: error: 'newvar' undeclared (first use in this function) +conftest.c:113: error: (Each undeclared identifier is reported only once +conftest.c:113: error: for each function it appears in.) +conftest.c:123: error: 'for' loop initial declaration used outside C99 mode +configure:3317: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| /* end confdefs.h. */ +| #include +| #include +| #include +| #include +| #include +| +| // Check varargs macros. These examples are taken from C99 6.10.3.5. +| #define debug(...) fprintf (stderr, __VA_ARGS__) +| #define showlist(...) puts (#__VA_ARGS__) +| #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +| static void +| test_varargs_macros (void) +| { +| int x = 1234; +| int y = 5678; +| debug ("Flag"); +| debug ("X = %d\n", x); +| showlist (The first, second, and third items.); +| report (x>y, "x is %d but y is %d", x, y); +| } +| +| // Check long long types. +| #define BIG64 18446744073709551615ull +| #define BIG32 4294967295ul +| #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +| #if !BIG_OK +| your preprocessor is broken; +| #endif +| #if BIG_OK +| #else +| your preprocessor is broken; +| #endif +| static long long int bignum = -9223372036854775807LL; +| static unsigned long long int ubignum = BIG64; +| +| struct incomplete_array +| { +| int datasize; +| double data[]; +| }; +| +| struct named_init { +| int number; +| const wchar_t *name; +| double average; +| }; +| +| typedef const char *ccp; +| +| static inline int +| test_restrict (ccp restrict text) +| { +| // See if C++-style comments work. +| // Iterate through items via the restricted pointer. +| // Also check for declarations in for loops. +| for (unsigned int i = 0; *(text+i) != '\0'; ++i) +| continue; +| return 0; +| } +| +| // Check varargs and va_copy. +| static void +| test_varargs (const char *format, ...) +| { +| va_list args; +| va_start (args, format); +| va_list args_copy; +| va_copy (args_copy, args); +| +| const char *str; +| int number; +| float fnumber; +| +| while (*format) +| { +| switch (*format++) +| { +| case 's': // string +| str = va_arg (args_copy, const char *); +| break; +| case 'd': // int +| number = va_arg (args_copy, int); +| break; +| case 'f': // float +| fnumber = va_arg (args_copy, double); +| break; +| default: +| break; +| } +| } +| va_end (args_copy); +| va_end (args); +| } +| +| int +| main () +| { +| +| // Check bool. +| _Bool success = false; +| +| // Check restrict. +| if (test_restrict ("String literal") == 0) +| success = true; +| char *restrict newvar = "Another string"; +| +| // Check varargs. +| test_varargs ("s, d' f .", "string", 65, 34.234); +| test_varargs_macros (); +| +| // Check flexible array members. +| struct incomplete_array *ia = +| malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); +| ia->datasize = 10; +| for (int i = 0; i < ia->datasize; ++i) +| ia->data[i] = i * 1.234; +| +| // Check named initializers. +| struct named_init ni = { +| .number = 34, +| .name = L"Test wide string", +| .average = 543.34343, +| }; +| +| ni.number = 58; +| +| int dynamic_array[ni.number]; +| dynamic_array[ni.number - 1] = 543; +| +| // work around unused variable warnings +| return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' +| || dynamic_array[ni.number - 1] != 543); +| +| ; +| return 0; +| } +configure:3317: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3317: $? = 0 +configure:3337: result: -std=gnu99 +configure:3438: checking for gcc -std=gnu99 option to accept ISO Standard C +configure:3452: result: -std=gnu99 +configure:3458: checking for grep that handles long lines and -e +configure:3516: result: /usr/bin/grep +configure:3521: checking for egrep +configure:3583: result: /usr/bin/grep -E +configure:3588: checking for ANSI C header files +configure:3608: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3608: $? = 0 +configure:3681: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5 +configure:3681: $? = 0 +configure:3681: ./conftest +configure:3681: $? = 0 +configure:3692: result: yes +configure:3705: checking for sys/types.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for sys/stat.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for stdlib.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for string.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for memory.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for strings.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for inttypes.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for stdint.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3705: checking for unistd.h +configure:3705: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3705: $? = 0 +configure:3705: result: yes +configure:3718: checking minix/config.h usability +configure:3718: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +conftest.c:52:26: error: minix/config.h: No such file or directory +configure:3718: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| #include +configure:3718: result: no +configure:3718: checking minix/config.h presence +configure:3718: gcc -E conftest.c +conftest.c:19:26: error: minix/config.h: No such file or directory +configure:3718: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| /* end confdefs.h. */ +| #include +configure:3718: result: no +configure:3718: checking for minix/config.h +configure:3718: result: no +configure:3739: checking whether it is safe to define __EXTENSIONS__ +configure:3757: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:3757: $? = 0 +configure:3764: result: yes +configure:3780: checking for library containing strerror +configure:3811: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5 +configure:3811: $? = 0 +configure:3828: result: none required +configure:3879: checking for ranlib +configure:3895: found /usr/bin/ranlib +configure:3906: result: ranlib +configure:3930: checking for memory.h +configure:3930: result: yes +configure:3940: checking for ANSI C header files +configure:4044: result: yes +configure:4052: checking complex.h usability +configure:4052: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:4052: $? = 0 +configure:4052: result: yes +configure:4052: checking complex.h presence +configure:4052: gcc -E conftest.c +configure:4052: $? = 0 +configure:4052: result: yes +configure:4052: checking for complex.h +configure:4052: result: yes +configure:4059: checking malloc.h usability +configure:4059: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +conftest.c:60:20: error: malloc.h: No such file or directory +configure:4059: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| #include +configure:4059: result: no +configure:4059: checking malloc.h presence +configure:4059: gcc -E conftest.c +conftest.c:27:20: error: malloc.h: No such file or directory +configure:4059: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| /* end confdefs.h. */ +| #include +configure:4059: result: no +configure:4059: checking for malloc.h +configure:4059: result: no +configure:4066: checking varargs.h usability +configure:4066: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +In file included from conftest.c:60: +/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/include/varargs.h:4:2: error: #error "GCC no longer implements ." +/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/include/varargs.h:5:2: error: #error "Revise your code to use ." +configure:4066: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| #include +configure:4066: result: no +configure:4066: checking varargs.h presence +configure:4066: gcc -E conftest.c +In file included from conftest.c:27: +/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/include/varargs.h:4:2: error: #error "GCC no longer implements ." +/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/include/varargs.h:5:2: error: #error "Revise your code to use ." +configure:4066: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| /* end confdefs.h. */ +| #include +configure:4066: result: no +configure:4066: checking for varargs.h +configure:4066: result: no +configure:4075: checking for size_t +configure:4075: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:4075: $? = 0 +configure:4075: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +conftest.c: In function 'main': +conftest.c:64: error: expected expression before ')' token +configure:4075: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| #define NOT_SEGMENTED 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| int +| main () +| { +| if (sizeof ((size_t))) +| return 0; +| ; +| return 0; +| } +configure:4075: result: yes +configure:4086: checking for an ANSI C-conforming const +configure:4152: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:4152: $? = 0 +configure:4159: result: yes +configure:4167: checking whether byte ordering is bigendian +configure:4182: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:4182: $? = 0 +configure:4227: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +configure:4227: $? = 0 +configure:4245: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +conftest.c: In function 'main': +conftest.c:35: error: 'not' undeclared (first use in this function) +conftest.c:35: error: (Each undeclared identifier is reported only once +conftest.c:35: error: for each function it appears in.) +conftest.c:35: error: expected ';' before 'big' +configure:4245: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| #define NOT_SEGMENTED 1 +| /* end confdefs.h. */ +| #include +| #include +| +| int +| main () +| { +| #if BYTE_ORDER != BIG_ENDIAN +| not big endian +| #endif +| +| ; +| return 0; +| } +configure:4373: result: no +configure:4460: gcc -std=gnu99 -c -g -O2 conftest.c >&5 +conftest.c:29: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' +configure:4460: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define HAVE_MEMORY_H 1 +| #define STDC_HEADERS 1 +| #define HAVE_COMPLEX_H 1 +| #define NOT_SEGMENTED 1 +| /* end confdefs.h. */ +| u_int +| int +| main () +| { +| #include +| #ifdef __STDC__ +| #include +| #endif +| ; +| return 0; +| } +configure:4507: checking for bcopy +configure:4507: gcc -std=gnu99 -o conftest -g -O2 conftest.c -lm >&5 +conftest.c:56: warning: conflicting types for built-in function 'bcopy' +configure:4507: $? = 0 +configure:4507: result: yes +configure:4507: checking for bzero +configure:4507: gcc -std=gnu99 -o conftest -g -O2 conftest.c -lm >&5 +conftest.c:57: warning: conflicting types for built-in function 'bzero' +configure:4507: $? = 0 +configure:4507: result: yes + +## ---------------- ## +## Cache variables. ## +## ---------------- ## + +ac_cv_c_bigendian=no +ac_cv_c_compiler_gnu=yes +ac_cv_c_const=yes +ac_cv_env_CC_set= +ac_cv_env_CC_value= +ac_cv_env_CFLAGS_set= +ac_cv_env_CFLAGS_value= +ac_cv_env_CPPFLAGS_set= +ac_cv_env_CPPFLAGS_value= +ac_cv_env_CPP_set= +ac_cv_env_CPP_value= +ac_cv_env_LDFLAGS_set= +ac_cv_env_LDFLAGS_value= +ac_cv_env_LIBS_set= +ac_cv_env_LIBS_value= +ac_cv_env_build_alias_set= +ac_cv_env_build_alias_value= +ac_cv_env_host_alias_set= +ac_cv_env_host_alias_value= +ac_cv_env_target_alias_set= +ac_cv_env_target_alias_value= +ac_cv_func_bcopy=yes +ac_cv_func_bzero=yes +ac_cv_header_complex_h=yes +ac_cv_header_inttypes_h=yes +ac_cv_header_malloc_h=no +ac_cv_header_memory_h=yes +ac_cv_header_minix_config_h=no +ac_cv_header_stdc=yes +ac_cv_header_stdint_h=yes +ac_cv_header_stdlib_h=yes +ac_cv_header_string_h=yes +ac_cv_header_strings_h=yes +ac_cv_header_sys_stat_h=yes +ac_cv_header_sys_types_h=yes +ac_cv_header_unistd_h=yes +ac_cv_header_varargs_h=no +ac_cv_objext=o +ac_cv_path_EGREP='/usr/bin/grep -E' +ac_cv_path_GREP=/usr/bin/grep +ac_cv_prog_CC= +ac_cv_prog_CPP='gcc -E' +ac_cv_prog_ac_ct_CC=gcc +ac_cv_prog_ac_ct_RANLIB=ranlib +ac_cv_prog_cc_c89= +ac_cv_prog_cc_c99=-std=gnu99 +ac_cv_prog_cc_g=yes +ac_cv_prog_cc_stdc=-std=gnu99 +ac_cv_safe_to_define___extensions__=yes +ac_cv_search_strerror='none required' +ac_cv_type_size_t=yes + +## ----------------- ## +## Output variables. ## +## ----------------- ## + +CC='gcc -std=gnu99' +CFLAGS='-g -O2' +CPP='gcc -E' +CPPFLAGS='' +DEFS='' +ECHO_C='\c' +ECHO_N='' +ECHO_T='' +EGREP='/usr/bin/grep -E' +EXEEXT='' +GREP='/usr/bin/grep' +LDFLAGS='' +LIBOBJS='' +LIBS=' -lm' +LTLIBOBJS='' +OBJEXT='o' +PACKAGE_BUGREPORT='' +PACKAGE_NAME='' +PACKAGE_STRING='' +PACKAGE_TARNAME='' +PACKAGE_URL='' +PACKAGE_VERSION='' +PATH_SEPARATOR=':' +PROGS='' +RANLIB='ranlib' +SHELL='/bin/sh' +ac_ct_CC='gcc' +bindir='${exec_prefix}/bin' +build_alias='' +datadir='${datarootdir}' +datarootdir='${prefix}/share' +docdir='${datarootdir}/doc/${PACKAGE}' +dvidir='${docdir}' +exec_prefix='NONE' +host_alias='' +htmldir='${docdir}' +includedir='${prefix}/include' +infodir='${datarootdir}/info' +libdir='${exec_prefix}/lib' +libexecdir='${exec_prefix}/libexec' +localedir='${datarootdir}/locale' +localstatedir='${prefix}/var' +mandir='${datarootdir}/man' +oldincludedir='/usr/include' +pdfdir='${docdir}' +prefix='NONE' +program_transform_name='s,x,x,' +psdir='${docdir}' +sbindir='${exec_prefix}/sbin' +sharedstatedir='${prefix}/com' +sysconfdir='${prefix}/etc' +target_alias='' + +## ----------- ## +## confdefs.h. ## +## ----------- ## + +/* confdefs.h */ +#define PACKAGE_NAME "" +#define PACKAGE_TARNAME "" +#define PACKAGE_VERSION "" +#define PACKAGE_STRING "" +#define PACKAGE_BUGREPORT "" +#define PACKAGE_URL "" +#define STDC_HEADERS 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define __EXTENSIONS__ 1 +#define _ALL_SOURCE 1 +#define _GNU_SOURCE 1 +#define _POSIX_PTHREAD_SEMANTICS 1 +#define _TANDEM_SOURCE 1 +#define HAVE_MEMORY_H 1 +#define STDC_HEADERS 1 +#define HAVE_COMPLEX_H 1 +#define NOT_SEGMENTED 1 +#define U_INT_DEF 1 +#define D_MACHEPS +#define F_MACHEPS +#define M_MAX_INT +#define CHAR0ISDBL0 1 +#define HAVE_BCOPY 1 +#define HAVE_BZERO 1 + +configure: exit 258 diff --git a/configure b/configure new file mode 100755 index 0000000..12af4d2 --- /dev/null +++ b/configure @@ -0,0 +1,5820 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="err.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +RANLIB +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +PROGS +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_complex +with_sparse +with_all +with_unroll +with_munroll +with_segmem +with_float +with_double +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) +$as_echo "#define COMPLEX 1" >>confdefs.h + +$as_echo "#define SPARSE 1" >>confdefs.h + +$as_echo "#define VUNROLL 1" >>confdefs.h + +$as_echo "#define MUNROLL 1" >>confdefs.h + +$as_echo "#define SEGMENTED 1" >>confdefs.h + +$as_echo "#define REAL_FLT 1" >>confdefs.h + +$as_echo "#define REAL_DBL 1" >>confdefs.h + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers machine.h" + +PROGS="" +# Extract the first word of "acc", so it can be a program name with args. +set dummy acc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="acc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="""" +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="gcc" +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + case $ac_cv_prog_cc_stdc in #( + no) : + ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 +else + ac_cv_prog_cc_stdc=no +fi + +fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 +$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } + if ${ac_cv_prog_cc_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +fi + + case $ac_cv_prog_cc_stdc in #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; #( + '') : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 +$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; +esac + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +for ac_header in memory.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "memory.h" "ac_cv_header_memory_h" "$ac_includes_default" +if test "x$ac_cv_header_memory_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MEMORY_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +ac_fn_c_check_header_mongrel "$LINENO" "complex.h" "ac_cv_header_complex_h" "$ac_includes_default" +if test "x$ac_cv_header_complex_h" = xyes; then : + $as_echo "#define HAVE_COMPLEX_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" +if test "x$ac_cv_header_malloc_h" = xyes; then : + $as_echo "#define HAVE_MALLOC_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "varargs.h" "ac_cv_header_varargs_h" "$ac_includes_default" +if test "x$ac_cv_header_varargs_h" = xyes; then : + $as_echo "#define VARARGS 1" >>confdefs.h + +fi + + +$as_echo "#define NOT_SEGMENTED 1" >>confdefs.h + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# Check whether --with-complex was given. +if test "${with_complex+set}" = set; then : + withval=$with_complex; +fi + + +# Check whether --with-sparse was given. +if test "${with_sparse+set}" = set; then : + withval=$with_sparse; +fi + + +# Check whether --with-all was given. +if test "${with_all+set}" = set; then : + withval=$with_all; +fi + + +# Check whether --with-all was given. +if test "${with_all+set}" = set; then : + withval=$with_all; +fi + + +# Check whether --with-unroll was given. +if test "${with_unroll+set}" = set; then : + withval=$with_unroll; +fi + + +# Check whether --with-munroll was given. +if test "${with_munroll+set}" = set; then : + withval=$with_munroll; +fi + + +# Check whether --with-segmem was given. +if test "${with_segmem+set}" = set; then : + withval=$with_segmem; +fi + + +# Check whether --with-float was given. +if test "${with_float+set}" = set; then : + withval=$with_float; +fi + + +# Check whether --with-double was given. +if test "${with_double+set}" = set; then : + withval=$with_double; +fi + +LIBS="$LIBS -lm" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +u_int +int +main () +{ +#include +#ifdef __STDC__ +#include +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + u_int i; i = 1; +else + $as_echo "#define U_INT_DEF 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +echo 'computing machine epsilon(s)' +echo $CC -o macheps dmacheps.c +$CC -o macheps dmacheps.c +cat >>confdefs.h <<_ACEOF +#define D_MACHEPS `macheps` +_ACEOF + +echo $CC -o macheps fmacheps.c +$CC -o macheps fmacheps.c +cat >>confdefs.h <<_ACEOF +#define F_MACHEPS `macheps` +_ACEOF + +echo computing M_MAX_INT +echo $CC -o maxint maxint.c +$CC -o maxint maxint.c +cat >>confdefs.h <<_ACEOF +#define M_MAX_INT `maxint` +_ACEOF + +echo checking char '\\0' vs. float zeros +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +main() { + char *cp = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + double *dp; + dp = (double *)cp; + if ( *dp == 0.0 ) printf("yes\n"); } + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + $as_echo "#define CHAR0ISDBL0 1" >>confdefs.h + +fi +rm -f conftest* + +for ac_func in bcopy bzero +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +function prototypes +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + extern int test (int i, double x); +else + $as_echo "#define HAVE_PROTOTYPES 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_config_files="$ac_config_files makefile make.mex" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "machine.h") CONFIG_HEADERS="$CONFIG_HEADERS machine.h" ;; + "makefile") CONFIG_FILES="$CONFIG_FILES makefile" ;; + "make.mex") CONFIG_FILES="$CONFIG_FILES make.mex" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + +echo "Extensions to basic version: use configure --with-opt1 --with-opt2" +echo " Option:" +echo " --with-complex incorporate complex functions" +echo " --with-sparse incorporate sparse matrix functions" +echo " --with-all both of the above" +echo " --with-unroll unroll low level loops on vectors" +echo " --with-munroll unroll low level loops on matrices" +echo " --with-float single precision" +echo " --with-double double precision (default)" +echo "Re-run configure with these options if you want them" +# configure.in copyright (C) Brook Milligan and David Stewart, 1993, 2002 diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..fa5a367 --- /dev/null +++ b/configure.in @@ -0,0 +1,109 @@ +dnl Meschach autoconf script +dnl Copyright (C) Brook Milligan and David Stewart, 1993, 2002 +dnl $Id: configure.in,v 1.3 1994/03/08 05:41:32 des Exp $ +dnl +dnl I want to use this to see if the compiler can be made ANSI C compatible +dnl AC_PROG_CC_STDC +dnl Brook Milligan's prototype check +dnl Check if $(CC) supports prototypes +define(LOCAL_HAVE_PROTOTYPES, +[AC_TRY_COMPILE([function prototypes], , +[extern int test (int i, double x);], +AC_DEFINE(HAVE_PROTOTYPES))])dnl +dnl +dnl Brook Milligan's compiler check +dnl Check for the sun ansi c compiler, acc +define(LOCAL_PROG_ACC, +[AC_BEFORE([$0], [AC_PROG_CPP])AC_PROVIDE([$0])dnl +AC_PROGRAM_CHECK(CC, acc, acc, "")])dnl +dnl David Stewart's modified compiler check +define(LOCAL_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])AC_PROVIDE([$0])dnl +AC_PROGRAM_CHECK(CC, acc, acc, cc)])dnl +dnl +dnl +dnl +dnl ---------------------------------------------------------------------- +dnl Start of configure.in proper +dnl ---------------------------------------------------------------------- +AC_INIT(err.c) +AC_CONFIG_HEADER(machine.h) +PROGS="" +AC_SUBST(PROGS)dnl +LOCAL_PROG_ACC +AC_PROGRAM_CHECK(CC, cc, cc, gcc) +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CC_STDC +AC_AIX +AC_MINIX +AC_ISC_POSIX +dnl +dnl Brook Milligan's prototype check +dnl Check if $(CC) supports prototypes in function declarations and structures +define(LOCAL_HAVE_PROTOTYPES, +[AC_TRY_COMPILE([function prototypes], , +[extern int test (int i, double x);], +AC_DEFINE(HAVE_PROTOTYPES)) +AC_TRY_COMPILE([function prototypes in structures], , +[struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);};], +AC_DEFINE(HAVE_PROTOTYPES_IN_STRUCT))])dnl +dnl +AC_PROG_RANLIB +AC_HAVE_HEADERS(memory.h) +AC_STDC_HEADERS +AC_HEADER_CHECK(complex.h, AC_DEFINE(HAVE_COMPLEX_H),) +AC_HEADER_CHECK(malloc.h, AC_DEFINE(HAVE_MALLOC_H),) +AC_HEADER_CHECK(varargs.h, AC_DEFINE(VARARGS),) +AC_DEFINE(NOT_SEGMENTED) +AC_SIZE_T +AC_CONST +AC_WORDS_BIGENDIAN +AC_ARG_WITH(complex, AC_DEFINE(COMPLEX)) +AC_ARG_WITH(sparse, AC_DEFINE(SPARSE)) +AC_ARG_WITH(all, AC_DEFINE(COMPLEX)) +AC_ARG_WITH(all, AC_DEFINE(SPARSE)) +AC_ARG_WITH(unroll, AC_DEFINE(VUNROLL)) +AC_ARG_WITH(munroll, AC_DEFINE(MUNROLL)) +AC_ARG_WITH(segmem, AC_DEFINE(SEGMENTED)) +AC_ARG_WITH(float, AC_DEFINE(REAL_FLT)) +AC_ARG_WITH(double, AC_DEFINE(REAL_DBL)) +LIBS="$LIBS -lm" +AC_TRY_COMPILE([u_int],[#include +#ifdef __STDC__ +#include +#endif],[u_int i; i = 1;],AC_DEFINE(U_INT_DEF)) +echo 'computing machine epsilon(s)' +echo $CC -o macheps dmacheps.c +$CC -o macheps dmacheps.c +AC_DEFINE_UNQUOTED(D_MACHEPS,`macheps`) +echo $CC -o macheps fmacheps.c +$CC -o macheps fmacheps.c +AC_DEFINE_UNQUOTED(F_MACHEPS,`macheps`) +echo computing M_MAX_INT +echo $CC -o maxint maxint.c +$CC -o maxint maxint.c +AC_DEFINE_UNQUOTED(M_MAX_INT,`maxint`) +echo checking char '\\0' vs. float zeros +AC_PROGRAM_EGREP(yes,[main() { + char *cp = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + double *dp; + dp = (double *)cp; + if ( *dp == 0.0 ) printf("yes\n"); } +],AC_DEFINE(CHAR0ISDBL0)) +AC_HAVE_FUNCS(bcopy bzero) +LOCAL_HAVE_PROTOTYPES +AC_CONFIG_FILES([makefile make.mex]) +AC_OUTPUT +echo "Extensions to basic version: use configure --with-opt1 --with-opt2" +echo " Option:" +echo " --with-complex incorporate complex functions" +echo " --with-sparse incorporate sparse matrix functions" +echo " --with-all both of the above" +echo " --with-unroll unroll low level loops on vectors" +echo " --with-munroll unroll low level loops on matrices" +echo " --with-float single precision" +echo " --with-double double precision (default)" +echo "Re-run configure with these options if you want them" +# configure.in copyright (C) Brook Milligan and David Stewart, 1993, 2002 diff --git a/conjgrad.c b/conjgrad.c new file mode 100644 index 0000000..9d8b0b2 --- /dev/null +++ b/conjgrad.c @@ -0,0 +1,349 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Conjugate gradient routines file + Uses sparse matrix input & sparse Cholesky factorisation in pccg(). + + All the following routines use routines to define a matrix + rather than use any explicit representation + (with the exeception of the pccg() pre-conditioner) + The matrix A is defined by + + VEC *(*A)(void *params, VEC *x, VEC *y) + + where y = A.x on exit, and y is returned. The params argument is + intended to make it easier to re-use & modify such routines. + + If we have a sparse matrix data structure + SPMAT *A_mat; + then these can be used by passing sp_mv_mlt as the function, and + A_mat as the param. +*/ + +#include +#include +#include "matrix.h" +#include "sparse.h" +static char rcsid[] = "$Id: conjgrad.c,v 1.4 1994/01/13 05:36:45 des Exp $"; + + +/* #define MAX_ITER 10000 */ +static int max_iter = 10000; +int cg_num_iters; + +/* matrix-as-routine type definition */ +/* #ifdef ANSI_C */ +/* typedef VEC *(*MTX_FN)(void *params, VEC *x, VEC *out); */ +/* #else */ +typedef VEC *(*MTX_FN)(); +/* #endif */ +#ifdef ANSI_C +VEC *spCHsolve(SPMAT *,VEC *,VEC *); +#else +VEC *spCHsolve(); +#endif + +/* cg_set_maxiter -- sets maximum number of iterations if numiter > 1 + -- just returns current max_iter otherwise + -- returns old maximum */ +int cg_set_maxiter(numiter) +int numiter; +{ + int temp; + + if ( numiter < 2 ) + return max_iter; + temp = max_iter; + max_iter = numiter; + return temp; +} + + +/* pccg -- solves A.x = b using pre-conditioner M + (assumed factored a la spCHfctr()) + -- results are stored in x (if x != NULL), which is returned */ +VEC *pccg(A,A_params,M_inv,M_params,b,eps,x) +MTX_FN A, M_inv; +VEC *b, *x; +double eps; +void *A_params, *M_params; +{ + VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL; + int k; + Real alpha, beta, ip, old_ip, norm_b; + + if ( ! A || ! b ) + error(E_NULL,"pccg"); + if ( x == b ) + error(E_INSITU,"pccg"); + x = v_resize(x,b->dim); + if ( eps <= 0.0 ) + eps = MACHEPS; + + r = v_get(b->dim); + p = v_get(b->dim); + q = v_get(b->dim); + z = v_get(b->dim); + + norm_b = v_norm2(b); + + v_zero(x); + r = v_copy(b,r); + old_ip = 0.0; + for ( k = 0; ; k++ ) + { + if ( v_norm2(r) < eps*norm_b ) + break; + if ( k > max_iter ) + error(E_ITER,"pccg"); + if ( M_inv ) + (*M_inv)(M_params,r,z); + else + v_copy(r,z); /* M == identity */ + ip = in_prod(z,r); + if ( k ) /* if ( k > 0 ) ... */ + { + beta = ip/old_ip; + p = v_mltadd(z,p,beta,p); + } + else /* if ( k == 0 ) ... */ + { + beta = 0.0; + p = v_copy(z,p); + old_ip = 0.0; + } + q = (*A)(A_params,p,q); + alpha = ip/in_prod(p,q); + x = v_mltadd(x,p,alpha,x); + r = v_mltadd(r,q,-alpha,r); + old_ip = ip; + } + cg_num_iters = k; + + V_FREE(p); + V_FREE(q); + V_FREE(r); + V_FREE(z); + + return x; +} + +/* sp_pccg -- a simple interface to pccg() which uses sparse matrix + data structures + -- assumes that LLT contains the Cholesky factorisation of the + actual pre-conditioner */ +VEC *sp_pccg(A,LLT,b,eps,x) +SPMAT *A, *LLT; +VEC *b, *x; +double eps; +{ return pccg(sp_mv_mlt,A,spCHsolve,LLT,b,eps,x); } + + +/* + Routines for performing the CGS (Conjugate Gradient Squared) + algorithm of P. Sonneveld: + "CGS, a fast Lanczos-type solver for nonsymmetric linear + systems", SIAM J. Sci. & Stat. Comp. v. 10, pp. 36--52 +*/ + +/* cgs -- uses CGS to compute a solution x to A.x=b + -- the matrix A is not passed explicitly, rather a routine + A is passed where A(x,Ax,params) computes + Ax = A.x + -- the computed solution is passed */ +VEC *cgs(A,A_params,b,r0,tol,x) +MTX_FN A; +VEC *x, *b; +VEC *r0; /* tilde r0 parameter -- should be random??? */ +double tol; /* error tolerance used */ +void *A_params; +{ + VEC *p, *q, *r, *u, *v, *tmp1, *tmp2; + Real alpha, beta, norm_b, rho, old_rho, sigma; + int iter; + + if ( ! A || ! x || ! b || ! r0 ) + error(E_NULL,"cgs"); + if ( x->dim != b->dim || r0->dim != x->dim ) + error(E_SIZES,"cgs"); + if ( tol <= 0.0 ) + tol = MACHEPS; + + p = v_get(x->dim); + q = v_get(x->dim); + r = v_get(x->dim); + u = v_get(x->dim); + v = v_get(x->dim); + tmp1 = v_get(x->dim); + tmp2 = v_get(x->dim); + + norm_b = v_norm2(b); + (*A)(A_params,x,tmp1); + v_sub(b,tmp1,r); + v_zero(p); v_zero(q); + old_rho = 1.0; + + iter = 0; + while ( v_norm2(r) > tol*norm_b ) + { + if ( ++iter > max_iter ) break; + /* error(E_ITER,"cgs"); */ + rho = in_prod(r0,r); + if ( old_rho == 0.0 ) + error(E_SING,"cgs"); + beta = rho/old_rho; + v_mltadd(r,q,beta,u); + v_mltadd(q,p,beta,tmp1); + v_mltadd(u,tmp1,beta,p); + + (*A)(A_params,p,v); + + sigma = in_prod(r0,v); + if ( sigma == 0.0 ) + error(E_SING,"cgs"); + alpha = rho/sigma; + v_mltadd(u,v,-alpha,q); + v_add(u,q,tmp1); + + (*A)(A_params,tmp1,tmp2); + + v_mltadd(r,tmp2,-alpha,r); + v_mltadd(x,tmp1,alpha,x); + + old_rho = rho; + } + cg_num_iters = iter; + + V_FREE(p); V_FREE(q); V_FREE(r); + V_FREE(u); V_FREE(v); + V_FREE(tmp1); V_FREE(tmp2); + + return x; +} + +/* sp_cgs -- simple interface for SPMAT data structures */ +VEC *sp_cgs(A,b,r0,tol,x) +SPMAT *A; +VEC *b, *r0, *x; +double tol; +{ return cgs(sp_mv_mlt,A,b,r0,tol,x); } + +/* + Routine for performing LSQR -- the least squares QR algorithm + of Paige and Saunders: + "LSQR: an algorithm for sparse linear equations and + sparse least squares", ACM Trans. Math. Soft., v. 8 + pp. 43--71 (1982) +*/ +/* lsqr -- sparse CG-like least squares routine: + -- finds min_x ||A.x-b||_2 using A defined through A & AT + -- returns x (if x != NULL) */ +VEC *lsqr(A,AT,A_params,b,tol,x) +MTX_FN A, AT; /* AT is A transposed */ +VEC *x, *b; +double tol; /* error tolerance used */ +void *A_params; +{ + VEC *u, *v, *w, *tmp; + Real alpha, beta, norm_b, phi, phi_bar, + rho, rho_bar, rho_max, theta; + Real s, c; /* for Givens' rotations */ + int iter, m, n; + + if ( ! b || ! x ) + error(E_NULL,"lsqr"); + if ( tol <= 0.0 ) + tol = MACHEPS; + + m = b->dim; n = x->dim; + u = v_get((unsigned int)m); + v = v_get((unsigned int)n); + w = v_get((unsigned int)n); + tmp = v_get((unsigned int)n); + norm_b = v_norm2(b); + + v_zero(x); + beta = v_norm2(b); + if ( beta == 0.0 ) + return x; + sv_mlt(1.0/beta,b,u); + tracecatch((*AT)(A_params,u,v),"lsqr"); + alpha = v_norm2(v); + if ( alpha == 0.0 ) + return x; + sv_mlt(1.0/alpha,v,v); + v_copy(v,w); + phi_bar = beta; rho_bar = alpha; + + rho_max = 1.0; + iter = 0; + do { + if ( ++iter > max_iter ) + error(E_ITER,"lsqr"); + + tmp = v_resize(tmp,m); + tracecatch((*A) (A_params,v,tmp),"lsqr"); + + v_mltadd(tmp,u,-alpha,u); + beta = v_norm2(u); sv_mlt(1.0/beta,u,u); + + tmp = v_resize(tmp,n); + tracecatch((*AT)(A_params,u,tmp),"lsqr"); + v_mltadd(tmp,v,-beta,v); + alpha = v_norm2(v); sv_mlt(1.0/alpha,v,v); + + rho = sqrt(rho_bar*rho_bar+beta*beta); + if ( rho > rho_max ) + rho_max = rho; + c = rho_bar/rho; + s = beta/rho; + theta = s*alpha; + rho_bar = -c*alpha; + phi = c*phi_bar; + phi_bar = s*phi_bar; + + /* update x & w */ + if ( rho == 0.0 ) + error(E_SING,"lsqr"); + v_mltadd(x,w,phi/rho,x); + v_mltadd(v,w,-theta/rho,w); + } while ( fabs(phi_bar*alpha*c) > tol*norm_b/rho_max ); + + cg_num_iters = iter; + + V_FREE(tmp); V_FREE(u); V_FREE(v); V_FREE(w); + + return x; +} + +/* sp_lsqr -- simple interface for SPMAT data structures */ +VEC *sp_lsqr(A,b,tol,x) +SPMAT *A; +VEC *b, *x; +double tol; +{ return lsqr(sp_mv_mlt,sp_vm_mlt,A,b,tol,x); } + diff --git a/copy.c b/copy.c new file mode 100644 index 0000000..b2b360b --- /dev/null +++ b/copy.c @@ -0,0 +1,246 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +static char rcsid[] = "$Id: copy.c,v 1.2 1994/01/13 05:37:14 des Exp $"; +#include +#include "matrix.h" + + + +/* _m_copy -- copies matrix into new area + -- out(i0:m,j0:n) <- in(i0:m,j0:n) */ +#ifndef ANSI_C +MAT *_m_copy(in,out,i0,j0) +MAT *in,*out; +unsigned int i0,j0; +#else +MAT *_m_copy(const MAT *in, MAT *out, unsigned int i0, unsigned int j0) +#endif +{ + unsigned int i /* ,j */; + + if ( in==MNULL ) + error(E_NULL,"_m_copy"); + if ( in==out ) + return (out); + if ( out==MNULL || out->m < in->m || out->n < in->n ) + out = m_resize(out,in->m,in->n); + + for ( i=i0; i < in->m; i++ ) + MEM_COPY(&(in->me[i][j0]),&(out->me[i][j0]), + (in->n - j0)*sizeof(Real)); + /* for ( j=j0; j < in->n; j++ ) + out->me[i][j] = in->me[i][j]; */ + + return (out); +} + +/* _v_copy -- copies vector into new area + -- out(i0:dim) <- in(i0:dim) */ +#ifndef ANSI_C +VEC *_v_copy(in,out,i0) +VEC *in,*out; +unsigned int i0; +#else +VEC *_v_copy(const VEC *in, VEC *out, unsigned int i0) +#endif +{ + /* unsigned int i,j; */ + + if ( in==VNULL ) + error(E_NULL,"_v_copy"); + if ( in==out ) + return (out); + if ( out==VNULL || out->dim < in->dim ) + out = v_resize(out,in->dim); + + MEM_COPY(&(in->ve[i0]),&(out->ve[i0]),(in->dim - i0)*sizeof(Real)); + /* for ( i=i0; i < in->dim; i++ ) + out->ve[i] = in->ve[i]; */ + + return (out); +} + +/* px_copy -- copies permutation 'in' to 'out' + -- out is resized to in->size */ +#ifndef ANSI_C +PERM *px_copy(in,out) +PERM *in,*out; +#else +PERM *px_copy(const PERM *in, PERM *out) +#endif +{ + /* int i; */ + + if ( in == PNULL ) + error(E_NULL,"px_copy"); + if ( in == out ) + return out; + if ( out == PNULL || out->size != in->size ) + out = px_resize(out,in->size); + + MEM_COPY(in->pe,out->pe,in->size*sizeof(unsigned int)); + /* for ( i = 0; i < in->size; i++ ) + out->pe[i] = in->pe[i]; */ + + return out; +} + +/* + The .._move() routines are for moving blocks of memory around + within Meschach data structures and for re-arranging matrices, + vectors etc. +*/ + +/* m_move -- copies selected pieces of a matrix + -- moves the m0 x n0 submatrix with top-left cor-ordinates (i0,j0) + to the corresponding submatrix of out with top-left co-ordinates + (i1,j1) + -- out is resized (& created) if necessary */ +#ifndef ANSI_C +MAT *m_move(in,i0,j0,m0,n0,out,i1,j1) +MAT *in, *out; +int i0, j0, m0, n0, i1, j1; +#else +MAT *m_move(const MAT *in, int i0,int j0, int m0,int n0, + MAT *out, int i1, int j1) +#endif +{ + int i; + + if ( ! in ) + error(E_NULL,"m_move"); + if ( i0 < 0 || j0 < 0 || i1 < 0 || j1 < 0 || m0 < 0 || n0 < 0 || + i0+m0 > in->m || j0+n0 > in->n ) + error(E_BOUNDS,"m_move"); + + if ( ! out ) + out = m_resize(out,i1+m0,j1+n0); + else if ( i1+m0 > out->m || j1+n0 > out->n ) + out = m_resize(out,max(out->m,i1+m0),max(out->n,j1+n0)); + + for ( i = 0; i < m0; i++ ) + MEM_COPY(&(in->me[i0+i][j0]),&(out->me[i1+i][j1]), + n0*sizeof(Real)); + + return out; +} + +/* v_move -- copies selected pieces of a vector + -- moves the length dim0 subvector with initial index i0 + to the corresponding subvector of out with initial index i1 + -- out is resized if necessary */ +#ifndef ANSI_C +VEC *v_move(in,i0,dim0,out,i1) +VEC *in, *out; +int i0, dim0, i1; +#else +VEC *v_move(const VEC *in, int i0, int dim0, + VEC *out, int i1) +#endif +{ + if ( ! in ) + error(E_NULL,"v_move"); + if ( i0 < 0 || dim0 < 0 || i1 < 0 || + i0+dim0 > in->dim ) + error(E_BOUNDS,"v_move"); + + if ( (! out) || i1+dim0 > out->dim ) + out = v_resize(out,i1+dim0); + + MEM_COPY(&(in->ve[i0]),&(out->ve[i1]),dim0*sizeof(Real)); + + return out; +} + +/* mv_move -- copies selected piece of matrix to a vector + -- moves the m0 x n0 submatrix with top-left co-ordinate (i0,j0) to + the subvector with initial index i1 (and length m0*n0) + -- rows are copied contiguously + -- out is resized if necessary */ +#ifndef ANSI_C +VEC *mv_move(in,i0,j0,m0,n0,out,i1) +MAT *in; +VEC *out; +int i0, j0, m0, n0, i1; +#else +VEC *mv_move(const MAT *in, int i0,int j0, int m0, int n0, + VEC *out, int i1) +#endif +{ + int dim1, i; + + if ( ! in ) + error(E_NULL,"mv_move"); + if ( i0 < 0 || j0 < 0 || m0 < 0 || n0 < 0 || i1 < 0 || + i0+m0 > in->m || j0+n0 > in->n ) + error(E_BOUNDS,"mv_move"); + + dim1 = m0*n0; + if ( (! out) || i1+dim1 > out->dim ) + out = v_resize(out,i1+dim1); + + for ( i = 0; i < m0; i++ ) + MEM_COPY(&(in->me[i0+i][j0]),&(out->ve[i1+i*n0]),n0*sizeof(Real)); + + return out; +} + +/* vm_move -- copies selected piece of vector to a matrix + +-- moves the subvector with initial index i0 and length m1*n1 to + the m1 x n1 submatrix with top-left co-ordinate (i1,j1) + -- copying is done by rows + -- out is resized if necessary */ +#ifndef ANSI_C +MAT *vm_move(in,i0,out,i1,j1,m1,n1) +VEC *in; +MAT *out; +int i0, i1, j1, m1, n1; +#else +MAT *vm_move(const VEC *in, int i0, + MAT *out, int i1, int j1, int m1, int n1) +#endif +{ + int dim0, i; + + if ( ! in ) + error(E_NULL,"vm_move"); + if ( i0 < 0 || i1 < 0 || j1 < 0 || m1 < 0 || n1 < 0 || + i0+m1*n1 > in->dim ) + error(E_BOUNDS,"vm_move"); + + if ( ! out ) + out = m_resize(out,i1+m1,j1+n1); + else + out = m_resize(out,max(i1+m1,out->m),max(j1+n1,out->n)); + + dim0 = m1*n1; + for ( i = 0; i < m1; i++ ) + MEM_COPY(&(in->ve[i0+i*n1]),&(out->me[i1+i][j1]),n1*sizeof(Real)); + + return out; +} diff --git a/copyright b/copyright new file mode 100644 index 0000000..d2992bb --- /dev/null +++ b/copyright @@ -0,0 +1,25 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + diff --git a/dmacheps.c b/dmacheps.c new file mode 100644 index 0000000..e6300d5 --- /dev/null +++ b/dmacheps.c @@ -0,0 +1,46 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +#include + +double dclean(x) +double x; +{ + static double y; + y = x; + return y; /* prevents optimisation */ +} + +main() +{ + static double deps, deps1, dtmp; + + deps = 1.0; + while ( dclean(1.0+deps) > 1.0 ) + deps = 0.5*deps; + + printf("%g\n", 2.0*deps); +} diff --git a/err.c b/err.c new file mode 100644 index 0000000..d5f2584 --- /dev/null +++ b/err.c @@ -0,0 +1,366 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File with basic error-handling operations +*/ + +static char rcsid[] = "$Id: err.c,v 1.6 1995/01/30 14:49:14 des Exp $"; + +#include +#include +#include +#include "err.h" + + +#ifdef SYSV +/* AT&T System V */ +#include +#else +/* something else -- assume BSD or ANSI C */ +#include +#endif + + + +#define FALSE 0 +#define TRUE 1 + +#define EF_EXIT 0 +#define EF_ABORT 1 +#define EF_JUMP 2 +#define EF_SILENT 3 + +/* The only error caught in this file! */ +#define E_SIGNAL 16 + +static char *err_mesg[] = +{ "unknown error", /* 0 */ + "sizes of objects don't match", /* 1 */ + "index out of bounds", /* 2 */ + "can't allocate memory", /* 3 */ + "singular matrix", /* 4 */ + "matrix not positive definite", /* 5 */ + "incorrect format input", /* 6 */ + "bad input file/device", /* 7 */ + "NULL objects passed", /* 8 */ + "matrix not square", /* 9 */ + "object out of range", /* 10 */ + "can't do operation in situ for non-square matrix", /* 11 */ + "can't do operation in situ", /* 12 */ + "excessive number of iterations", /* 13 */ + "convergence criterion failed", /* 14 */ + "bad starting value", /* 15 */ + "floating exception", /* 16 */ + "internal inconsistency (data structure)",/* 17 */ + "unexpected end-of-file", /* 18 */ + "shared vectors (cannot release them)", /* 19 */ + "negative argument", /* 20 */ + "cannot overwrite object", /* 21 */ + "breakdown in iterative method" /* 22 */ + }; + +#define MAXERR (sizeof(err_mesg)/sizeof(char *)) + +static char *warn_mesg[] = { + "unknown warning", /* 0 */ + "wrong type number (use macro TYPE_*)", /* 1 */ + "no corresponding mem_stat_mark", /* 2 */ + "computed norm of a residual is less than 0", /* 3 */ + "resizing a shared vector" /* 4 */ +}; + +#define MAXWARN (sizeof(warn_mesg)/sizeof(char *)) + + + +#define MAX_ERRS 100 + +jmp_buf restart; + + +/* array of pointers to lists of errors */ + +typedef struct { + char **listp; /* pointer to a list of errors */ + unsigned len; /* length of the list */ + unsigned warn; /* =FALSE - errors, =TRUE - warnings */ +} Err_list; + +static Err_list err_list[ERR_LIST_MAX_LEN] = { + {err_mesg,MAXERR,FALSE}, /* basic errors list */ + {warn_mesg,MAXWARN,TRUE} /* basic warnings list */ +}; + + +static int err_list_end = 2; /* number of elements in err_list */ + +/* attach a new list of errors pointed by err_ptr + or change a previous one; + list_len is the number of elements in the list; + list_num is the list number; + warn == FALSE - errors (stop the program), + warn == TRUE - warnings (continue the program); + Note: lists numbered 0 and 1 are attached automatically, + you do not need to do it + */ +#ifndef ANSI_C +int err_list_attach(list_num, list_len,err_ptr,warn) +int list_num, list_len, warn; +char **err_ptr; +#else +int err_list_attach(int list_num, int list_len, char **err_ptr, int warn) +#endif +{ + if (list_num < 0 || list_len <= 0 || + err_ptr == (char **)NULL) + return -1; + + if (list_num >= ERR_LIST_MAX_LEN) { + fprintf(stderr,"\n file \"%s\": %s %s\n", + "err.c","increase the value of ERR_LIST_MAX_LEN", + "in matrix.h and zmatdef.h"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stderr,"\n file \"%s\": %s %s\n", + "err.c","increase the value of ERR_LIST_MAX_LEN", + "in matrix.h and zmatdef.h"); + printf("Exiting program\n"); + exit(0); + } + + if (err_list[list_num].listp != (char **)NULL && + err_list[list_num].listp != err_ptr) + free((char *)err_list[list_num].listp); + err_list[list_num].listp = err_ptr; + err_list[list_num].len = list_len; + err_list[list_num].warn = warn; + err_list_end = list_num+1; + + return list_num; +} + + +/* release the error list numbered list_num */ +#ifndef ANSI_C +int err_list_free(list_num) +int list_num; +#else +int err_list_free(int list_num) +#endif +{ + if (list_num < 0 || list_num >= err_list_end) return -1; + if (err_list[list_num].listp != (char **)NULL) { + err_list[list_num].listp = (char **)NULL; + err_list[list_num].len = 0; + err_list[list_num].warn = 0; + } + return 0; +} + + +/* check if list_num is attached; + return FALSE if not; + return TRUE if yes + */ +#ifndef ANSI_C +int err_is_list_attached(list_num) +int list_num; +#else +int err_is_list_attached(int list_num) +#endif +{ + if (list_num < 0 || list_num >= err_list_end) + return FALSE; + + if (err_list[list_num].listp != (char **)NULL) + return TRUE; + + return FALSE; +} + +/* other local variables */ + +static int err_flag = EF_EXIT, num_errs = 0, cnt_errs = 1; + +/* set_err_flag -- sets err_flag -- returns old err_flag */ +#ifndef ANSI_C +int set_err_flag(flag) +int flag; +#else +int set_err_flag(int flag) +#endif +{ + int tmp; + + tmp = err_flag; + err_flag = flag; + return tmp; +} + +/* count_errs -- sets cnt_errs (TRUE/FALSE) & returns old value */ +#ifndef ANSI_C +int count_errs(flag) +int flag; +#else +int count_errs(int flag) +#endif +{ + int tmp; + + tmp = cnt_errs; + cnt_errs = flag; + return tmp; +} + +/* ev_err -- reports error (err_num) in file "file" at line "line_num" and + returns to user error handler; + list_num is an error list number (0 is the basic list + pointed by err_mesg, 1 is the basic list of warnings) + */ +#ifndef ANSI_C +int ev_err(file,err_num,line_num,fn_name,list_num) +char *file, *fn_name; +int err_num, line_num,list_num; +#else +int ev_err(const char *file, int err_num, int line_num, + const char *fn_name, int list_num) +#endif +{ + int num; + + if ( err_num < 0 ) err_num = 0; + + if (list_num < 0 || list_num >= err_list_end || + err_list[list_num].listp == (char **)NULL) { + fprintf(stderr, + "\n Not (properly) attached list of errors: list_num = %d\n", + list_num); + fprintf(stderr," Call \"err_list_attach\" in your program\n"); + if ( ! isatty(fileno(stdout)) ) { + fprintf(stderr, + "\n Not (properly) attached list of errors: list_num = %d\n", + list_num); + fprintf(stderr," Call \"err_list_attach\" in your program\n"); + } + printf("\nExiting program\n"); + exit(0); + } + + num = err_num; + if ( num >= err_list[list_num].len ) num = 0; + + if ( cnt_errs && ++num_errs >= MAX_ERRS ) /* too many errors */ + { + fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + printf("Sorry, too many errors: %d\n",num_errs); + printf("Exiting program\n"); + exit(0); + } + if ( err_list[list_num].warn ) + switch ( err_flag ) + { + case EF_SILENT: break; + default: + fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + break; + } + else + switch ( err_flag ) + { + case EF_SILENT: + longjmp(restart,(err_num==0)? -1 : err_num); + break; + case EF_ABORT: + fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + abort(); + break; + case EF_JUMP: + fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + longjmp(restart,(err_num==0)? -1 : err_num); + break; + default: + fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + if ( ! isatty(fileno(stdout)) ) + fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n", + file,line_num,err_list[list_num].listp[num], + isascii(*fn_name) ? fn_name : "???"); + + break; + } + + /* ensure exit if fall through */ + if ( ! err_list[list_num].warn ) exit(0); + + return 0; +} + +/* float_error -- catches floating arithmetic signals */ +#ifndef ANSI_C +static void float_error(num) +int num; +#else +static void float_error(int num) +#endif +{ + signal(SIGFPE,float_error); + /* fprintf(stderr,"SIGFPE: signal #%d\n",num); */ + /* fprintf(stderr,"errno = %d\n",errno); */ + ev_err("???.c",E_SIGNAL,0,"???",0); +} + +/* catch_signal -- sets up float_error() to catch SIGFPE's */ +void catch_FPE() +{ + signal(SIGFPE,float_error); +} + + diff --git a/err.h b/err.h new file mode 100644 index 0000000..50f3482 --- /dev/null +++ b/err.h @@ -0,0 +1,183 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* err.h 28/09/1993 */ + +/* RCS id: $Id: err.h,v 1.2 1995/01/30 14:48:05 des Exp $ */ + + +#ifndef ERRHEADER +#define ERRHEADER + + +#include +#include "machine.h" + +/* Error recovery */ + +extern jmp_buf restart; + + +/* max. # of error lists */ +#define ERR_LIST_MAX_LEN 10 + +/* main error functions */ +#ifndef ANSI_C +extern int ev_err(); /* main error handler */ +extern int set_err_flag(); /* for different ways of handling + errors, returns old value */ +extern int count_errs(); /* to avoid "too many errors" */ +extern int err_list_attach(); /* for attaching a list of errors */ +extern int err_is_list_attached(); /* checking if a list is attached */ +extern int err_list_free(); /* freeing a list of errors */ + +#else /* ANSI_C */ + +extern int ev_err(const char *,int,int,const char *,int); /* main error handler */ +extern int set_err_flag(int flag); /* for different ways of handling + errors, returns old value */ +extern int count_errs(int true_false); /* to avoid "too many errors" */ +extern int err_list_attach(int list_num, int list_len, + char **err_ptr,int warn); /* for attaching a list of errors */ +extern int err_is_list_attached(int list_num); /* checking if a list + is attached */ +extern int err_list_free(int list_num); /* freeing a list of errors */ + +#endif + + +/* error(E_TYPE,"myfunc") raises error type E_TYPE for function my_func() */ +#define error(err_num,fn_name) ev_err(__FILE__,err_num,__LINE__,fn_name,0) + +/* warning(WARN_TYPE,"myfunc") raises warning type WARN_TYPE for + function my_func() */ +#define warning(err_num,fn_name) ev_err(__FILE__,err_num,__LINE__,fn_name,1) + + +/* error flags */ +#define EF_EXIT 0 /* exit on error */ +#define EF_ABORT 1 /* abort (dump core) on error */ +#define EF_JUMP 2 /* jump on error */ +#define EF_SILENT 3 /* jump, but don't print message */ +#define ERREXIT() set_err_flag(EF_EXIT) +#define ERRABORT() set_err_flag(EF_ABORT) +/* don't print message */ +#define SILENTERR() if ( ! setjmp(restart) ) set_err_flag(EF_SILENT) +/* return here on error */ +#define ON_ERROR() if ( ! setjmp(restart) ) set_err_flag(EF_JUMP) + + +/* error types */ +#define E_UNKNOWN 0 +#define E_SIZES 1 +#define E_BOUNDS 2 +#define E_MEM 3 +#define E_SING 4 +#define E_POSDEF 5 +#define E_FORMAT 6 +#define E_INPUT 7 +#define E_NULL 8 +#define E_SQUARE 9 +#define E_RANGE 10 +#define E_INSITU2 11 +#define E_INSITU 12 +#define E_ITER 13 +#define E_CONV 14 +#define E_START 15 +#define E_SIGNAL 16 +#define E_INTERN 17 +#define E_EOF 18 +#define E_SHARED_VECS 19 +#define E_NEG 20 +#define E_OVERWRITE 21 +#define E_BREAKDOWN 22 + +/* warning types */ +#define WARN_UNKNOWN 0 +#define WARN_WRONG_TYPE 1 +#define WARN_NO_MARK 2 +#define WARN_RES_LESS_0 3 +#define WARN_SHARED_VEC 4 + + +/* error catching macros */ + +/* execute err_part if error errnum is raised while executing ok_part */ +#define catch(errnum,ok_part,err_part) \ + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ + if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ + else if ( _err_num == errnum ) \ + { set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); \ + err_part; } \ + else { set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); \ + error(_err_num,"catch"); \ + } \ + } + + +/* execute err_part if any error raised while executing ok_part */ +#define catchall(ok_part,err_part) \ + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_SILENT); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ + if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ + else \ + { set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); \ + err_part; } \ + } + + +/* print message if error raised while executing ok_part, + then re-raise error to trace calls */ +#define tracecatch(ok_part,function) \ + { jmp_buf _save; int _err_num, _old_flag; \ + _old_flag = set_err_flag(EF_JUMP); \ + MEM_COPY(restart,_save,sizeof(jmp_buf)); \ + if ( (_err_num=setjmp(restart)) == 0 ) \ + { ok_part; \ + set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); } \ + else \ + { set_err_flag(_old_flag); \ + MEM_COPY(_save,restart,sizeof(jmp_buf)); \ + error(_err_num,function); } \ + } + + + +#endif /* ERRHEADER */ + diff --git a/extras.c b/extras.c new file mode 100644 index 0000000..dc6cb2b --- /dev/null +++ b/extras.c @@ -0,0 +1,500 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Memory port routines: MEM_COPY and MEM_ZERO +*/ + +/* For BSD 4.[23] environments: using bcopy() and bzero() */ + +#include "machine.h" + +#ifndef MEM_COPY +void MEM_COPY(from,to,len) +char *from, *to; +int len; +{ + int i; + + if ( from < to ) + { + for ( i = 0; i < len; i++ ) + *to++ = *from++; + } + else + { + from += len; to += len; + for ( i = 0; i < len; i++ ) + *(--to) = *(--from); + } +} +#endif + +#ifndef MEM_ZERO +void MEM_ZERO(ptr,len) +char *ptr; +int len; +{ + int i; + + for ( i = 0; i < len; i++ ) + *(ptr++) = '\0'; +} +#endif + +/* + This file contains versions of something approximating the well-known + BLAS routines in C, suitable for Meschach (hence the `m'). + These are "vanilla" implementations, at least with some consideration + of the effects of caching and paging, and maybe some loop unrolling + for register-rich machines +*/ + +/* + Organisation of matrices: it is assumed that matrices are represented + by Real **'s. To keep flexibility, there is also an "initial + column" parameter j0, so that the actual elements used are + A[0][j0], A[0][j0+1], ..., A[0][j0+n-1] + A[1][j0], A[1][j0+1], ..., A[1][j0+n-1] + .. .. ... .. + A[m-1][j0], A[m-1][j0+1], ..., A[m-1][j0+n-1] +*/ + +static char rcsid[] = "$Id: extras.c,v 1.4 1995/06/08 15:13:15 des Exp $"; + +#include + +#define REGISTER_RICH 1 + +/* mblar-1 routines */ + +/* Mscale -- sets x <- alpha.x */ +void Mscale(len,alpha,x) +int len; +double alpha; +Real *x; +{ + register int i; + + for ( i = 0; i < len; i++ ) + x[i] *= alpha; +} + +/* Mswap -- swaps x and y */ +void Mswap(len,x,y) +int len; +Real *x, *y; +{ + register int i; + register Real tmp; + + for ( i = 0; i < len; i++ ) + { + tmp = x[i]; + x[i] = y[i]; + y[i] = tmp; + } +} + +/* Mcopy -- copies x to y */ +void Mcopy(len,x,y) +int len; +Real *x, *y; +{ + register int i; + + for ( i = 0; i < len; i++ ) + y[i] = x[i]; +} + +/* Maxpy -- y <- y + alpha.x */ +void Maxpy(len,alpha,x,y) +int len; +double alpha; +Real *x, *y; +{ + register int i, len4; + + /**************************************** + for ( i = 0; i < len; i++ ) + y[i] += alpha*x[i]; + ****************************************/ + +#ifdef REGISTER_RICH + len4 = len / 4; + len = len % 4; + for ( i = 0; i < len4; i++ ) + { + y[4*i] += alpha*x[4*i]; + y[4*i+1] += alpha*x[4*i+1]; + y[4*i+2] += alpha*x[4*i+2]; + y[4*i+3] += alpha*x[4*i+3]; + } + x += 4*len4; y += 4*len4; +#endif + for ( i = 0; i < len; i++ ) + y[i] += alpha*x[i]; +} + +/* Mdot -- returns x'.y */ +double Mdot(len,x,y) +int len; +Real *x, *y; +{ + register int i, len4; + register Real sum; + +#ifndef REGISTER_RICH + sum = 0.0; +#endif + +#ifdef REGISTER_RICH + register Real sum0, sum1, sum2, sum3; + + sum0 = sum1 = sum2 = sum3 = 0.0; + + len4 = len / 4; + len = len % 4; + + for ( i = 0; i < len4; i++ ) + { + sum0 += x[4*i ]*y[4*i ]; + sum1 += x[4*i+1]*y[4*i+1]; + sum2 += x[4*i+2]*y[4*i+2]; + sum3 += x[4*i+3]*y[4*i+3]; + } + sum = sum0 + sum1 + sum2 + sum3; + x += 4*len4; y += 4*len4; +#endif + + for ( i = 0; i < len; i++ ) + sum += x[i]*y[i]; + + return sum; +} + +#ifndef ABS +#define ABS(x) ((x) >= 0 ? (x) : -(x)) +#endif + +/* Mnorminf -- returns ||x||_inf */ +double Mnorminf(len,x) +int len; +Real *x; +{ + register int i; + register Real tmp, max_val; + + max_val = 0.0; + for ( i = 0; i < len; i++ ) + { + tmp = ABS(x[i]); + if ( max_val < tmp ) + max_val = tmp; + } + + return max_val; +} + +/* Mnorm1 -- returns ||x||_1 */ +double Mnorm1(len,x) +int len; +Real *x; +{ + register int i; + register Real sum; + + sum = 0.0; + for ( i = 0; i < len; i++ ) + sum += ABS(x[i]); + + return sum; +} + +/* Mnorm2 -- returns ||x||_2 */ +double Mnorm2(len,x) +int len; +Real *x; +{ + register int i; + register Real norm, invnorm, sum, tmp; + + norm = Mnorminf(len,x); + if ( norm == 0.0 ) + return 0.0; + invnorm = 1.0/norm; + sum = 0.0; + for ( i = 0; i < len; i++ ) + { + tmp = x[i]*invnorm; + sum += tmp*tmp; + } + + return sum/invnorm; +} + +/* mblar-2 routines */ + +/* Mmv -- y <- alpha.A.x + beta.y */ +void Mmv(m,n,alpha,A,j0,x,beta,y) +int m, n, j0; +double alpha, beta; +Real **A, *x, *y; +{ + register int i, j, m4, n4; + register Real sum0, sum1, sum2, sum3, tmp0, tmp1, tmp2, tmp3; + register Real *dp0, *dp1, *dp2, *dp3; + + /**************************************** + for ( i = 0; i < m; i++ ) + y[i] += alpha*Mdot(n,&(A[i][j0]),x); + ****************************************/ + + m4 = n4 = 0; + +#ifdef REGISTER_RICH + m4 = m / 4; + m = m % 4; + n4 = n / 4; + n = n % 4; + + for ( i = 0; i < m4; i++ ) + { + sum0 = sum1 = sum2 = sum3 = 0.0; + dp0 = &(A[4*i ][j0]); + dp1 = &(A[4*i+1][j0]); + dp2 = &(A[4*i+2][j0]); + dp3 = &(A[4*i+3][j0]); + + for ( j = 0; j < n4; j++ ) + { + tmp0 = x[4*j ]; + tmp1 = x[4*j+1]; + tmp2 = x[4*j+2]; + tmp3 = x[4*j+3]; + sum0 = sum0 + dp0[j]*tmp0 + dp0[j+1]*tmp1 + + dp0[j+2]*tmp2 + dp0[j+3]*tmp3; + sum1 = sum1 + dp1[j]*tmp0 + dp1[j+1]*tmp1 + + dp1[j+2]*tmp2 + dp1[j+3]*tmp3; + sum2 = sum2 + dp2[j]*tmp0 + dp2[j+1]*tmp1 + + dp2[j+2]*tmp2 + dp2[j+3]*tmp3; + sum3 = sum3 + dp3[j]*tmp0 + dp3[j+1]*tmp2 + + dp3[j+2]*tmp2 + dp3[j+3]*tmp3; + } + for ( j = 0; j < n; j++ ) + { + sum0 += dp0[4*n4+j]*x[4*n4+j]; + sum1 += dp1[4*n4+j]*x[4*n4+j]; + sum2 += dp2[4*n4+j]*x[4*n4+j]; + sum3 += dp3[4*n4+j]*x[4*n4+j]; + } + y[4*i ] = beta*y[4*i ] + alpha*sum0; + y[4*i+1] = beta*y[4*i+1] + alpha*sum1; + y[4*i+2] = beta*y[4*i+2] + alpha*sum2; + y[4*i+3] = beta*y[4*i+3] + alpha*sum3; + } +#endif + + for ( i = 0; i < m; i++ ) + y[4*m4+i] = beta*y[i] + alpha*Mdot(4*n4+n,&(A[4*m4+i][j0]),x); +} + +/* Mvm -- y <- alpha.A^T.x + beta.y */ +void Mvm(m,n,alpha,A,j0,x,beta,y) +int m, n, j0; +double alpha, beta; +Real **A, *x, *y; +{ + register int i, j, m4, n2; + register Real *Aref; + register Real tmp; + +#ifdef REGISTER_RICH + register Real *Aref0, *Aref1; + register Real tmp0, tmp1; + register Real yval0, yval1, yval2, yval3; +#endif + + if ( beta != 1.0 ) + Mscale(m,beta,y); + /**************************************** + for ( j = 0; j < n; j++ ) + Maxpy(m,alpha*x[j],&(A[j][j0]),y); + ****************************************/ + m4 = n2 = 0; + + m4 = m / 4; + m = m % 4; +#ifdef REGISTER_RICH + n2 = n / 2; + n = n % 2; + + for ( j = 0; j < n2; j++ ) + { + tmp0 = alpha*x[2*j]; + tmp1 = alpha*x[2*j+1]; + Aref0 = &(A[2*j ][j0]); + Aref1 = &(A[2*j+1][j0]); + for ( i = 0; i < m4; i++ ) + { + yval0 = y[4*i ] + tmp0*Aref0[4*i ]; + yval1 = y[4*i+1] + tmp0*Aref0[4*i+1]; + yval2 = y[4*i+2] + tmp0*Aref0[4*i+2]; + yval3 = y[4*i+3] + tmp0*Aref0[4*i+3]; + y[4*i ] = yval0 + tmp1*Aref1[4*i ]; + y[4*i+1] = yval1 + tmp1*Aref1[4*i+1]; + y[4*i+2] = yval2 + tmp1*Aref1[4*i+2]; + y[4*i+3] = yval3 + tmp1*Aref1[4*i+3]; + } + y += 4*m4; Aref0 += 4*m4; Aref1 += 4*m4; + for ( i = 0; i < m; i++ ) + y[i] += tmp0*Aref0[i] + tmp1*Aref1[i]; + } +#endif + + for ( j = 0; j < n; j++ ) + { + tmp = alpha*x[2*n2+j]; + Aref = &(A[2*n2+j][j0]); + for ( i = 0; i < m4; i++ ) + { + y[4*i ] += tmp*Aref[4*i ]; + y[4*i+1] += tmp*Aref[4*i+1]; + y[4*i+2] += tmp*Aref[4*i+2]; + y[4*i+3] += tmp*Aref[4*i+3]; + } + y += 4*m4; Aref += 4*m4; + for ( i = 0; i < m; i++ ) + y[i] += tmp*Aref[i]; + } +} + +/* Mupdate -- A <- A + alpha.x.y^T */ +void Mupdate(m,n,alpha,x,y,A,j0) +int m, n, j0; +double alpha; +Real **A, *x, *y; +{ + register int i, j, n4; + register Real *Aref; + register Real tmp; + + /**************************************** + for ( i = 0; i < m; i++ ) + Maxpy(n,alpha*x[i],y,&(A[i][j0])); + ****************************************/ + + n4 = n / 4; + n = n % 4; + for ( i = 0; i < m; i++ ) + { + tmp = alpha*x[i]; + Aref = &(A[i][j0]); + for ( j = 0; j < n4; j++ ) + { + Aref[4*j ] += tmp*y[4*j ]; + Aref[4*j+1] += tmp*y[4*j+1]; + Aref[4*j+2] += tmp*y[4*j+2]; + Aref[4*j+3] += tmp*y[4*j+3]; + } + Aref += 4*n4; y += 4*n4; + for ( j = 0; j < n; j++ ) + Aref[j] += tmp*y[j]; + } +} + +/* mblar-3 routines */ + +/* Mmm -- C <- C + alpha.A.B */ +void Mmm(m,n,p,alpha,A,Aj0,B,Bj0,C,Cj0) +int m, n, p; /* C is m x n */ +double alpha; +Real **A, **B, **C; +int Aj0, Bj0, Cj0; +{ + register int i, j, k; + /* register Real tmp, sum; */ + + /**************************************** + for ( i = 0; i < m; i++ ) + for ( k = 0; k < p; k++ ) + Maxpy(n,alpha*A[i][Aj0+k],&(B[k][Bj0]),&(C[i][Cj0])); + ****************************************/ + for ( i = 0; i < m; i++ ) + Mvm(p,n,alpha,B,Bj0,&(A[i][Aj0]),1.0,&(C[i][Cj0])); +} + +/* Mmtrm -- C <- C + alpha.A^T.B */ +void Mmtrm(m,n,p,alpha,A,Aj0,B,Bj0,C,Cj0) +int m, n, p; /* C is m x n */ +double alpha; +Real **A, **B, **C; +int Aj0, Bj0, Cj0; +{ + register int i, j, k; + + /**************************************** + for ( i = 0; i < m; i++ ) + for ( k = 0; k < p; k++ ) + Maxpy(n,alpha*A[k][Aj0+i],&(B[k][Bj0]),&(C[i][Cj0])); + ****************************************/ + for ( k = 0; k < p; k++ ) + Mupdate(m,n,alpha,&(A[k][Aj0]),&(B[k][Bj0]),C,Cj0); +} + +/* Mmmtr -- C <- C + alpha.A.B^T */ +void Mmmtr(m,n,p,alpha,A,Aj0,B,Bj0,C,Cj0) +int m, n, p; /* C is m x n */ +double alpha; +Real **A, **B, **C; +int Aj0, Bj0, Cj0; +{ + register int i, j, k; + + /**************************************** + for ( i = 0; i < m; i++ ) + for ( j = 0; j < n; j++ ) + C[i][Cj0+j] += alpha*Mdot(p,&(A[i][Aj0]),&(B[j][Bj0])); + ****************************************/ + for ( i = 0; i < m; i++ ) + Mmv(n,p,alpha,B,Bj0,&(A[i][Aj0]),1.0,&(C[i][Cj0])); +} + +/* Mmtrmtr -- C <- C + alpha.A^T.B^T */ +void Mmtrmtr(m,n,p,alpha,A,Aj0,B,Bj0,C,Cj0) +int m, n, p; /* C is m x n */ +double alpha; +Real **A, **B, **C; +int Aj0, Bj0, Cj0; +{ + register int i, j, k; + + for ( i = 0; i < m; i++ ) + for ( j = 0; j < n; j++ ) + for ( k = 0; k < p; k++ ) + C[i][Cj0+j] += A[i][Aj0+k]*B[k][Bj0+j]; +} + diff --git a/fft.c b/fft.c new file mode 100644 index 0000000..d604a45 --- /dev/null +++ b/fft.c @@ -0,0 +1,153 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Fast Fourier Transform routine + Loosely based on the Fortran routine in Rabiner & Gold's + "Digital Signal Processing" +*/ + +static char rcsid[] = "$Id: fft.c,v 1.4 1996/08/20 14:21:05 stewart Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +/* fft -- d.i.t. fast Fourier transform + -- radix-2 FFT only + -- vector extended to a power of 2 */ +#ifndef ANSI_C +void fft(x_re,x_im) +VEC *x_re, *x_im; +#else +void fft(VEC *x_re, VEC *x_im) +#endif +{ + int i, ip, j, k, li, n, length; + Real *xr, *xi; + Real theta, pi = 3.1415926535897932384; + Real w_re, w_im, u_re, u_im, t_re, t_im; + Real tmp, tmpr, tmpi; + + if ( ! x_re || ! x_im ) + error(E_NULL,"fft"); + if ( x_re->dim != x_im->dim ) + error(E_SIZES,"fft"); + + n = 1; + while ( x_re->dim > n ) + n *= 2; + x_re = v_resize(x_re,n); + x_im = v_resize(x_im,n); + /* printf("# fft: x_re =\n"); v_output(x_re); */ + /* printf("# fft: x_im =\n"); v_output(x_im); */ + xr = x_re->ve; + xi = x_im->ve; + + /* Decimation in time (DIT) algorithm */ + j = 0; + for ( i = 0; i < n-1; i++ ) + { + if ( i < j ) + { + tmp = xr[i]; + xr[i] = xr[j]; + xr[j] = tmp; + tmp = xi[i]; + xi[i] = xi[j]; + xi[j] = tmp; + } + k = n / 2; + while ( k <= j ) + { + j -= k; + k /= 2; + } + j += k; + } + + /* Actual FFT */ + for ( li = 1; li < n; li *= 2 ) + { + length = 2*li; + theta = pi/li; + u_re = 1.0; + u_im = 0.0; + if ( li == 1 ) + { + w_re = -1.0; + w_im = 0.0; + } + else if ( li == 2 ) + { + w_re = 0.0; + w_im = 1.0; + } + else + { + w_re = cos(theta); + w_im = sin(theta); + } + for ( j = 0; j < li; j++ ) + { + for ( i = j; i < n; i += length ) + { + ip = i + li; + /* step 1 */ + t_re = xr[ip]*u_re - xi[ip]*u_im; + t_im = xr[ip]*u_im + xi[ip]*u_re; + /* step 2 */ + xr[ip] = xr[i] - t_re; + xi[ip] = xi[i] - t_im; + /* step 3 */ + xr[i] += t_re; + xi[i] += t_im; + } + tmpr = u_re*w_re - u_im*w_im; + tmpi = u_im*w_re + u_re*w_im; + u_re = tmpr; + u_im = tmpi; + } + } +} + +/* ifft -- inverse FFT using the same interface as fft() */ +#ifndef ANSI_C +void ifft(x_re,x_im) +VEC *x_re, *x_im; +#else +void ifft(VEC *x_re, VEC *x_im) +#endif +{ + /* we just use complex conjugates */ + + sv_mlt(-1.0,x_im,x_im); + fft(x_re,x_im); + sv_mlt(-1.0/((double)(x_re->dim)),x_im,x_im); + sv_mlt( 1.0/((double)(x_re->dim)),x_re,x_re); +} diff --git a/fmacheps.c b/fmacheps.c new file mode 100644 index 0000000..ca05ec5 --- /dev/null +++ b/fmacheps.c @@ -0,0 +1,46 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +#include + +double fclean(x) +double x; +{ + static float y; + y = x; + return y; /* prevents optimisation */ +} + +main() +{ + static float feps, feps1, ftmp; + + feps = 1.0; + while ( fclean(1.0+feps) > 1.0 ) + feps = 0.5*feps; + + printf("%g\n", 2.0*feps); +} diff --git a/givens.c b/givens.c new file mode 100644 index 0000000..30a20ab --- /dev/null +++ b/givens.c @@ -0,0 +1,159 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + + +/* + Files for matrix computations + + Givens operations file. Contains routines for calculating and + applying givens rotations for/to vectors and also to matrices by + row and by column. +*/ + +/* givens.c 1.2 11/25/87 */ +static char rcsid[] = "$Id: givens.c,v 1.3 1995/03/27 15:41:15 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + +/* givens -- returns c,s parameters for Givens rotation to + eliminate y in the vector [ x y ]' */ +#ifndef ANSI_C +void givens(x,y,c,s) +double x,y; +Real *c,*s; +#else +void givens(double x, double y, Real *c, Real *s) +#endif +{ + Real norm; + + norm = sqrt(x*x+y*y); + if ( norm == 0.0 ) + { *c = 1.0; *s = 0.0; } /* identity */ + else + { *c = x/norm; *s = y/norm; } +} + +/* rot_vec -- apply Givens rotation to x's i & k components */ +#ifndef ANSI_C +VEC *rot_vec(x,i,k,c,s,out) +VEC *x,*out; +unsigned int i,k; +double c,s; +#else +VEC *rot_vec(const VEC *x,unsigned int i,unsigned int k, double c,double s, + VEC *out) +#endif +{ + Real temp; + + if ( x==VNULL ) + error(E_NULL,"rot_vec"); + if ( i >= x->dim || k >= x->dim ) + error(E_RANGE,"rot_vec"); + out = v_copy(x,out); + + /* temp = c*out->ve[i] + s*out->ve[k]; */ + temp = c*v_entry(out,i) + s*v_entry(out,k); + /* out->ve[k] = -s*out->ve[i] + c*out->ve[k]; */ + v_set_val(out,k,-s*v_entry(out,i)+c*v_entry(out,k)); + /* out->ve[i] = temp; */ + v_set_val(out,i,temp); + + return (out); +} + +/* rot_rows -- premultiply mat by givens rotation described by c,s */ +#ifndef ANSI_C +MAT *rot_rows(mat,i,k,c,s,out) +MAT *mat,*out; +unsigned int i,k; +double c,s; +#else +MAT *rot_rows(const MAT *mat, unsigned int i, unsigned int k, + double c, double s, MAT *out) +#endif +{ + unsigned int j; + Real temp; + + if ( mat==(MAT *)NULL ) + error(E_NULL,"rot_rows"); + if ( i >= mat->m || k >= mat->m ) + error(E_RANGE,"rot_rows"); + if ( mat != out ) + out = m_copy(mat,m_resize(out,mat->m,mat->n)); + + for ( j=0; jn; j++ ) + { + /* temp = c*out->me[i][j] + s*out->me[k][j]; */ + temp = c*m_entry(out,i,j) + s*m_entry(out,k,j); + /* out->me[k][j] = -s*out->me[i][j] + c*out->me[k][j]; */ + m_set_val(out,k,j, -s*m_entry(out,i,j) + c*m_entry(out,k,j)); + /* out->me[i][j] = temp; */ + m_set_val(out,i,j, temp); + } + + return (out); +} + +/* rot_cols -- postmultiply mat by givens rotation described by c,s */ +#ifndef ANSI_C +MAT *rot_cols(mat,i,k,c,s,out) +MAT *mat,*out; +unsigned int i,k; +double c,s; +#else +MAT *rot_cols(const MAT *mat,unsigned int i,unsigned int k, + double c, double s, MAT *out) +#endif +{ + unsigned int j; + Real temp; + + if ( mat==(MAT *)NULL ) + error(E_NULL,"rot_cols"); + if ( i >= mat->n || k >= mat->n ) + error(E_RANGE,"rot_cols"); + if ( mat != out ) + out = m_copy(mat,m_resize(out,mat->m,mat->n)); + + for ( j=0; jm; j++ ) + { + /* temp = c*out->me[j][i] + s*out->me[j][k]; */ + temp = c*m_entry(out,j,i) + s*m_entry(out,j,k); + /* out->me[j][k] = -s*out->me[j][i] + c*out->me[j][k]; */ + m_set_val(out,j,k, -s*m_entry(out,j,i) + c*m_entry(out,j,k)); + /* out->me[j][i] = temp; */ + m_set_val(out,j,i,temp); + } + + return (out); +} + diff --git a/hessen.c b/hessen.c new file mode 100644 index 0000000..55de63c --- /dev/null +++ b/hessen.c @@ -0,0 +1,174 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + + +/* + File containing routines for determining Hessenberg + factorisations. +*/ + +static char rcsid[] = "$Id: hessen.c,v 1.2 1994/01/13 05:36:24 des Exp $"; + +#include +#include "matrix.h" +#include "matrix2.h" + + + +/* Hfactor -- compute Hessenberg factorisation in compact form. + -- factorisation performed in situ + -- for details of the compact form see QRfactor.c and matrix2.doc */ +#ifndef ANSI_C +MAT *Hfactor(A, diag, beta) +MAT *A; +VEC *diag, *beta; +#else +MAT *Hfactor(MAT *A, VEC *diag, VEC *beta) +#endif +{ + STATIC VEC *hh = VNULL, *w = VNULL; + int k, limit; + + if ( ! A || ! diag || ! beta ) + error(E_NULL,"Hfactor"); + if ( diag->dim < A->m - 1 || beta->dim < A->m - 1 ) + error(E_SIZES,"Hfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"Hfactor"); + limit = A->m - 1; + + hh = v_resize(hh,A->m); + w = v_resize(w,A->n); + MEM_STAT_REG(hh,TYPE_VEC); + MEM_STAT_REG(w, TYPE_VEC); + + for ( k = 0; k < limit; k++ ) + { + /* compute the Householder vector hh */ + get_col(A,(unsigned int)k,hh); + /* printf("the %d'th column = "); v_output(hh); */ + hhvec(hh,k+1,&beta->ve[k],hh,&A->me[k+1][k]); + /* diag->ve[k] = hh->ve[k+1]; */ + v_set_val(diag,k,v_entry(hh,k+1)); + /* printf("H/h vector = "); v_output(hh); */ + /* printf("from the %d'th entry\n",k+1); */ + /* printf("beta = %g\n",beta->ve[k]); */ + + /* apply Householder operation symmetrically to A */ + _hhtrcols(A,k+1,k+1,hh,v_entry(beta,k),w); + hhtrrows(A,0 ,k+1,hh,v_entry(beta,k)); + /* printf("A = "); m_output(A); */ + } + +#ifdef THREADSAFE + V_FREE(hh); V_FREE(w); +#endif + + return (A); +} + +/* makeHQ -- construct the Hessenberg orthogonalising matrix Q; + -- i.e. Hess M = Q.M.Q' */ +#ifndef ANSI_C +MAT *makeHQ(H, diag, beta, Qout) +MAT *H, *Qout; +VEC *diag, *beta; +#else +MAT *makeHQ(MAT *H, VEC *diag, VEC *beta, MAT *Qout) +#endif +{ + int i, j, limit; + STATIC VEC *tmp1 = VNULL, *tmp2 = VNULL; + + if ( H==(MAT *)NULL || diag==(VEC *)NULL || beta==(VEC *)NULL ) + error(E_NULL,"makeHQ"); + limit = H->m - 1; + if ( diag->dim < limit || beta->dim < limit ) + error(E_SIZES,"makeHQ"); + if ( H->m != H->n ) + error(E_SQUARE,"makeHQ"); + Qout = m_resize(Qout,H->m,H->m); + + tmp1 = v_resize(tmp1,H->m); + tmp2 = v_resize(tmp2,H->m); + MEM_STAT_REG(tmp1,TYPE_VEC); + MEM_STAT_REG(tmp2,TYPE_VEC); + + for ( i = 0; i < H->m; i++ ) + { + /* tmp1 = i'th basis vector */ + for ( j = 0; j < H->m; j++ ) + /* tmp1->ve[j] = 0.0; */ + v_set_val(tmp1,j,0.0); + /* tmp1->ve[i] = 1.0; */ + v_set_val(tmp1,i,1.0); + + /* apply H/h transforms in reverse order */ + for ( j = limit-1; j >= 0; j-- ) + { + get_col(H,(unsigned int)j,tmp2); + /* tmp2->ve[j+1] = diag->ve[j]; */ + v_set_val(tmp2,j+1,v_entry(diag,j)); + hhtrvec(tmp2,beta->ve[j],j+1,tmp1,tmp1); + } + + /* insert into Qout */ + set_col(Qout,(unsigned int)i,tmp1); + } + +#ifdef THREADSAFE + V_FREE(tmp1); V_FREE(tmp2); +#endif + + return (Qout); +} + +/* makeH -- construct actual Hessenberg matrix */ +#ifndef ANSI_C +MAT *makeH(H,Hout) +MAT *H, *Hout; +#else +MAT *makeH(const MAT *H, MAT *Hout) +#endif +{ + int i, j, limit; + + if ( H==(MAT *)NULL ) + error(E_NULL,"makeH"); + if ( H->m != H->n ) + error(E_SQUARE,"makeH"); + Hout = m_resize(Hout,H->m,H->m); + Hout = m_copy(H,Hout); + + limit = H->m; + for ( i = 1; i < limit; i++ ) + for ( j = 0; j < i-1; j++ ) + /* Hout->me[i][j] = 0.0;*/ + m_set_val(Hout,i,j,0.0); + + return (Hout); +} + diff --git a/hsehldr.c b/hsehldr.c new file mode 100644 index 0000000..b0770b8 --- /dev/null +++ b/hsehldr.c @@ -0,0 +1,248 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Files for matrix computations + + Householder transformation file. Contains routines for calculating + householder transformations, applying them to vectors and matrices + by both row & column. +*/ + +/* hsehldr.c 1.3 10/8/87 */ +static char rcsid[] = "$Id: hsehldr.c,v 1.2 1994/01/13 05:36:29 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +/* hhvec -- calulates Householder vector to eliminate all entries after the + i0 entry of the vector vec. It is returned as out. May be in-situ */ +#ifndef ANSI_C +VEC *hhvec(vec,i0,beta,out,newval) +VEC *vec,*out; +unsigned int i0; +Real *beta,*newval; +#else +VEC *hhvec(const VEC *vec, unsigned int i0, Real *beta, + VEC *out, Real *newval) +#endif +{ + Real norm; + + out = _v_copy(vec,out,i0); + norm = sqrt(_in_prod(out,out,i0)); + if ( norm <= 0.0 ) + { + *beta = 0.0; + return (out); + } + *beta = 1.0/(norm * (norm+fabs(out->ve[i0]))); + if ( out->ve[i0] > 0.0 ) + *newval = -norm; + else + *newval = norm; + out->ve[i0] -= *newval; + + return (out); +} + +/* hhtrvec -- apply Householder transformation to vector + -- that is, out <- (I-beta.hh(i0:n).hh(i0:n)^T).in + -- may be in-situ */ +#ifndef ANSI_C +VEC *hhtrvec(hh,beta,i0,in,out) +VEC *hh,*in,*out; /* hh = Householder vector */ +unsigned int i0; +double beta; +#else +VEC *hhtrvec(const VEC *hh, double beta, unsigned int i0, + const VEC *in, VEC *out) +#endif +{ + Real scale; + /* unsigned int i; */ + + if ( hh==VNULL || in==VNULL ) + error(E_NULL,"hhtrvec"); + if ( in->dim != hh->dim ) + error(E_SIZES,"hhtrvec"); + if ( i0 > in->dim ) + error(E_BOUNDS,"hhtrvec"); + + scale = beta*_in_prod(hh,in,i0); + out = v_copy(in,out); + __mltadd__(&(out->ve[i0]),&(hh->ve[i0]),-scale,(int)(in->dim-i0)); + /************************************************************ + for ( i=i0; idim; i++ ) + out->ve[i] = in->ve[i] - scale*hh->ve[i]; + ************************************************************/ + + return (out); +} + +/* hhtrrows -- transform a matrix by a Householder vector by rows + starting at row i0 from column j0 -- in-situ + -- that is, M(i0:m,j0:n) <- M(i0:m,j0:n)(I-beta.hh(j0:n).hh(j0:n)^T) */ +#ifndef ANSI_C +MAT *hhtrrows(M,i0,j0,hh,beta) +MAT *M; +unsigned int i0, j0; +VEC *hh; +double beta; +#else +MAT *hhtrrows(MAT *M, unsigned int i0, unsigned int j0, + const VEC *hh, double beta) +#endif +{ + Real ip, scale; + int i /*, j */; + + if ( M==MNULL || hh==VNULL ) + error(E_NULL,"hhtrrows"); + if ( M->n != hh->dim ) + error(E_RANGE,"hhtrrows"); + if ( i0 > M->m || j0 > M->n ) + error(E_BOUNDS,"hhtrrows"); + + if ( beta == 0.0 ) return (M); + + /* for each row ... */ + for ( i = i0; i < M->m; i++ ) + { /* compute inner product */ + ip = __ip__(&(M->me[i][j0]),&(hh->ve[j0]),(int)(M->n-j0)); + /************************************************** + ip = 0.0; + for ( j = j0; j < M->n; j++ ) + ip += M->me[i][j]*hh->ve[j]; + **************************************************/ + scale = beta*ip; + if ( scale == 0.0 ) + continue; + + /* do operation */ + __mltadd__(&(M->me[i][j0]),&(hh->ve[j0]),-scale, + (int)(M->n-j0)); + /************************************************** + for ( j = j0; j < M->n; j++ ) + M->me[i][j] -= scale*hh->ve[j]; + **************************************************/ + } + + return (M); +} + +/* hhtrcols -- transform a matrix by a Householder vector by columns + starting at row i0 from column j0 + -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n) + -- in-situ + -- calls _hhtrcols() with the scratch vector w + -- Meschach internal routines should call _hhtrcols() to + avoid excessive memory allocation/de-allocation +*/ +#ifndef ANSI_C +MAT *hhtrcols(M,i0,j0,hh,beta) +MAT *M; +unsigned int i0, j0; +VEC *hh; +double beta; +#else +MAT *hhtrcols(MAT *M, unsigned int i0, unsigned int j0, + const VEC *hh, double beta) +#endif +{ + STATIC VEC *w = VNULL; + + if ( M == MNULL || hh == VNULL || w == VNULL ) + error(E_NULL,"hhtrcols"); + if ( M->m != hh->dim ) + error(E_SIZES,"hhtrcols"); + if ( i0 > M->m || j0 > M->n ) + error(E_BOUNDS,"hhtrcols"); + + if ( ! w || w->dim < M->n ) + w = v_resize(w,M->n); + MEM_STAT_REG(w,TYPE_VEC); + + M = _hhtrcols(M,i0,j0,hh,beta,w); + +#ifdef THREADSAFE + V_FREE(w); +#endif + + return M; +} + +/* _hhtrcols -- transform a matrix by a Householder vector by columns + starting at row i0 from column j0 + -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n) + -- in-situ + -- scratch vector w passed as argument + -- raises error if w == NULL +*/ +#ifndef ANSI_C +MAT *_hhtrcols(M,i0,j0,hh,beta,w) +MAT *M; +unsigned int i0, j0; +VEC *hh; +double beta; +VEC *w; +#else +MAT *_hhtrcols(MAT *M, unsigned int i0, unsigned int j0, + const VEC *hh, double beta, VEC *w) +#endif +{ + /* Real ip, scale; */ + int i /*, k */; + /* STATIC VEC *w = VNULL; */ + + if ( M == MNULL || hh == VNULL || w == VNULL ) + error(E_NULL,"_hhtrcols"); + if ( M->m != hh->dim ) + error(E_SIZES,"_hhtrcols"); + if ( i0 > M->m || j0 > M->n ) + error(E_BOUNDS,"_hhtrcols"); + + if ( beta == 0.0 ) return (M); + + if ( w->dim < M->n ) + w = v_resize(w,M->n); + /* MEM_STAT_REG(w,TYPE_VEC); */ + v_zero(w); + + for ( i = i0; i < M->m; i++ ) + if ( hh->ve[i] != 0.0 ) + __mltadd__(&(w->ve[j0]),&(M->me[i][j0]),hh->ve[i], + (int)(M->n-j0)); + for ( i = i0; i < M->m; i++ ) + if ( hh->ve[i] != 0.0 ) + __mltadd__(&(M->me[i][j0]),&(w->ve[j0]),-beta*hh->ve[i], + (int)(M->n-j0)); + return (M); +} + diff --git a/init.c b/init.c new file mode 100644 index 0000000..d9657c8 --- /dev/null +++ b/init.c @@ -0,0 +1,346 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This is a file of routines for zero-ing, and initialising + vectors, matrices and permutations. + This is to be included in the matrix.a library +*/ + +static char rcsid[] = "$Id: init.c,v 1.6 1994/01/13 05:36:58 des Exp $"; + +#include +#include "matrix.h" + +/* v_zero -- zero the vector x */ +#ifndef ANSI_C +VEC *v_zero(x) +VEC *x; +#else +VEC *v_zero(VEC *x) +#endif +{ + if ( x == VNULL ) + error(E_NULL,"v_zero"); + + __zero__(x->ve,x->dim); + /* for ( i = 0; i < x->dim; i++ ) + x->ve[i] = 0.0; */ + + return x; +} + + +/* iv_zero -- zero the vector ix */ +#ifndef ANSI_C +IVEC *iv_zero(ix) +IVEC *ix; +#else +IVEC *iv_zero(IVEC *ix) +#endif +{ + int i; + + if ( ix == IVNULL ) + error(E_NULL,"iv_zero"); + + for ( i = 0; i < ix->dim; i++ ) + ix->ive[i] = 0; + + return ix; +} + + +/* m_zero -- zero the matrix A */ +#ifndef ANSI_C +MAT *m_zero(A) +MAT *A; +#else +MAT *m_zero(MAT *A) +#endif +{ + int i, A_m, A_n; + Real **A_me; + + if ( A == MNULL ) + error(E_NULL,"m_zero"); + + A_m = A->m; A_n = A->n; A_me = A->me; + for ( i = 0; i < A_m; i++ ) + __zero__(A_me[i],A_n); + /* for ( j = 0; j < A_n; j++ ) + A_me[i][j] = 0.0; */ + + return A; +} + +/* mat_id -- set A to being closest to identity matrix as possible + -- i.e. A[i][j] == 1 if i == j and 0 otherwise */ +#ifndef ANSI_C +MAT *m_ident(A) +MAT *A; +#else +MAT *m_ident(MAT *A) +#endif +{ + int i, size; + + if ( A == MNULL ) + error(E_NULL,"m_ident"); + + m_zero(A); + size = min(A->m,A->n); + for ( i = 0; i < size; i++ ) + A->me[i][i] = 1.0; + + return A; +} + +/* px_ident -- set px to identity permutation */ +#ifndef ANSI_C +PERM *px_ident(px) +PERM *px; +#else +PERM *px_ident(PERM *px) +#endif +{ + int i, px_size; + unsigned int *px_pe; + + if ( px == PNULL ) + error(E_NULL,"px_ident"); + + px_size = px->size; px_pe = px->pe; + for ( i = 0; i < px_size; i++ ) + px_pe[i] = i; + + return px; +} + +/* Pseudo random number generator data structures */ +/* Knuth's lagged Fibonacci-based generator: See "Seminumerical Algorithms: + The Art of Computer Programming" sections 3.2-3.3 */ + +#ifdef ANSI_C +#ifndef LONG_MAX +#include +#endif +#endif + +#ifdef LONG_MAX +#define MODULUS LONG_MAX +#else +#define MODULUS 1000000000L /* assuming long's at least 32 bits long */ +#endif +#define MZ 0L + +static long mrand_list[56]; +static int started = FALSE; +static int inext = 0, inextp = 31; + + +/* mrand -- pseudo-random number generator */ +#ifdef ANSI_C +double mrand(void) +#else +double mrand() +#endif +{ + long lval; + static Real factor = 1.0/((Real)MODULUS); + + if ( ! started ) + smrand(3127); + + inext = (inext >= 54) ? 0 : inext+1; + inextp = (inextp >= 54) ? 0 : inextp+1; + + lval = mrand_list[inext]-mrand_list[inextp]; + if ( lval < 0L ) + lval += MODULUS; + mrand_list[inext] = lval; + + return (double)lval*factor; +} + +/* mrandlist -- fills the array a[] with len random numbers */ +#ifndef ANSI_C +void mrandlist(a, len) +Real a[]; +int len; +#else +void mrandlist(Real a[], int len) +#endif +{ + int i; + long lval; + static Real factor = 1.0/((Real)MODULUS); + + if ( ! started ) + smrand(3127); + + for ( i = 0; i < len; i++ ) + { + inext = (inext >= 54) ? 0 : inext+1; + inextp = (inextp >= 54) ? 0 : inextp+1; + + lval = mrand_list[inext]-mrand_list[inextp]; + if ( lval < 0L ) + lval += MODULUS; + mrand_list[inext] = lval; + + a[i] = (Real)lval*factor; + } +} + + +/* smrand -- set seed for mrand() */ +#ifndef ANSI_C +void smrand(seed) +int seed; +#else +void smrand(int seed) +#endif +{ + int i; + + mrand_list[0] = (123413*seed) % MODULUS; + for ( i = 1; i < 55; i++ ) + mrand_list[i] = (123413*mrand_list[i-1]) % MODULUS; + + started = TRUE; + + /* run mrand() through the list sufficient times to + thoroughly randomise the array */ + for ( i = 0; i < 55*55; i++ ) + mrand(); +} +#undef MODULUS +#undef MZ +#undef FAC + +/* v_rand -- initialises x to be a random vector, components + independently & uniformly ditributed between 0 and 1 */ +#ifndef ANSI_C +VEC *v_rand(x) +VEC *x; +#else +VEC *v_rand(VEC *x) +#endif +{ + /* int i; */ + + if ( ! x ) + error(E_NULL,"v_rand"); + + /* for ( i = 0; i < x->dim; i++ ) */ + /* x->ve[i] = rand()/((Real)MAX_RAND); */ + /* x->ve[i] = mrand(); */ + mrandlist(x->ve,x->dim); + + return x; +} + +/* m_rand -- initialises A to be a random vector, components + independently & uniformly distributed between 0 and 1 */ +#ifndef ANSI_C +MAT *m_rand(A) +MAT *A; +#else +MAT *m_rand(MAT *A) +#endif +{ + int i /* , j */; + + if ( ! A ) + error(E_NULL,"m_rand"); + + for ( i = 0; i < A->m; i++ ) + /* for ( j = 0; j < A->n; j++ ) */ + /* A->me[i][j] = rand()/((Real)MAX_RAND); */ + /* A->me[i][j] = mrand(); */ + mrandlist(A->me[i],A->n); + + return A; +} + +/* v_ones -- fills x with one's */ +#ifndef ANSI_C +VEC *v_ones(x) +VEC *x; +#else +VEC *v_ones(VEC *x) +#endif +{ + int i; + + if ( ! x ) + error(E_NULL,"v_ones"); + + for ( i = 0; i < x->dim; i++ ) + x->ve[i] = 1.0; + + return x; +} + +/* m_ones -- fills matrix with one's */ +#ifndef ANSI_C +MAT *m_ones(A) +MAT *A; +#else +MAT *m_ones(MAT *A) +#endif +{ + int i, j; + + if ( ! A ) + error(E_NULL,"m_ones"); + + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < A->n; j++ ) + A->me[i][j] = 1.0; + + return A; +} + +/* v_count -- initialises x so that x->ve[i] == i */ +#ifndef ANSI_C +VEC *v_count(x) +VEC *x; +#else +VEC *v_count(VEC *x) +#endif +{ + int i; + + if ( ! x ) + error(E_NULL,"v_count"); + + for ( i = 0; i < x->dim; i++ ) + x->ve[i] = (Real)i; + + return x; +} diff --git a/iotort.c b/iotort.c new file mode 100644 index 0000000..b2252b5 --- /dev/null +++ b/iotort.c @@ -0,0 +1,141 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* iotort.c 10/11/93 */ +/* test of I/O functions */ + + +static char rcsid[] = "$Id: $"; + +#include "sparse.h" +#include "zmatrix.h" + + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + + +void main() +{ + VEC *x; + MAT *A; + PERM *pivot; + IVEC *ix; + SPMAT *spA; + ZVEC *zx; + ZMAT *ZA; + char yes; + int i; + FILE *fp; + + mem_info_on(TRUE); + + if ((fp = fopen("iotort.dat","w")) == NULL) { + printf(" !!! Cannot open file %s for writing\n\n","iotort.dat"); + exit(1); + } + + x = v_get(10); + A = m_get(3,3); + zx = zv_get(10); + ZA = zm_get(3,3); + pivot = px_get(10); + ix = iv_get(10); + spA = sp_get(3,3,2); + + v_rand(x); + m_rand(A); + zv_rand(zx); + zm_rand(ZA); + px_ident(pivot); + for (i=0; i < 10; i++) + ix->ive[i] = i+1; + for (i=0; i < spA->m; i++) { + sp_set_val(spA,i,i,1.0); + if (i > 0) sp_set_val(spA,i-1,i,-1.0); + } + + notice(" VEC output"); + v_foutput(fp,x); + notice(" MAT output"); + m_foutput(fp,A); + notice(" ZVEC output"); + zv_foutput(fp,zx); + notice(" ZMAT output"); + zm_foutput(fp,ZA); + notice(" PERM output"); + px_foutput(fp,pivot); + notice(" IVEC output"); + iv_foutput(fp,ix); + notice(" SPMAT output"); + sp_foutput(fp,spA); + fprintf(fp,"Y"); + fclose(fp); + + printf("\nENTER SOME VALUES:\n\n"); + + if ((fp = fopen("iotort.dat","r")) == NULL) { + printf(" !!! Cannot open file %s for reading\n\n","iotort.dat"); + exit(1); + } + + notice(" VEC input/output"); + x = v_finput(fp,x); + v_output(x); + + notice(" MAT input/output"); + A = m_finput(fp,A); + m_output(A); + + notice(" ZVEC input/output"); + zx = zv_finput(fp,zx); + zv_output(zx); + + notice(" ZMAT input/output"); + ZA = zm_finput(fp,ZA); + zm_output(ZA); + + notice(" PERM input/output"); + pivot = px_finput(fp,pivot); + px_output(pivot); + + notice(" IVEC input/output"); + ix = iv_finput(fp,ix); + iv_output(ix); + + notice(" SPMAT input/output"); + SP_FREE(spA); + spA = sp_finput(fp); + sp_output(spA); + + notice(" general input"); + finput(fp," finish the test? ","%c",&yes); + if (yes == 'y' || yes == 'Y' ) + printf(" YES\n"); + else printf(" NO\n"); + fclose(fp); + + mem_info(); +} diff --git a/iter.h b/iter.h new file mode 100644 index 0000000..4084033 --- /dev/null +++ b/iter.h @@ -0,0 +1,253 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* iter.h 14/09/93 */ + +/* + + Structures for iterative methods + +*/ + +#ifndef ITERHH + +#define ITERHH + +/* RCS id: $Id: iter.h,v 1.2 1994/03/08 05:48:27 des Exp $ */ + + +#include "sparse.h" + + +/* basic structure for iterative methods */ + +/* type Fun_Ax for functions to get y = A*x */ +#ifdef ANSI_C +typedef VEC *(*Fun_Ax)(void *,VEC *,VEC *); +#else +typedef VEC *(*Fun_Ax)(); +#endif + + +/* type ITER */ +typedef struct Iter_data { + int shared_x; /* if TRUE then x is shared and it will not be free'd */ + int shared_b; /* if TRUE then b is shared and it will not be free'd */ + unsigned k; /* no. of direction (search) vectors; =0 - none */ + int limit; /* upper bound on the no. of iter. steps */ + int steps; /* no. of iter. steps done */ + Real eps; /* accuracy required */ + + VEC *x; /* input: initial guess; + output: approximate solution */ + VEC *b; /* right hand side of the equation A*x = b */ + + Fun_Ax Ax; /* function computing y = A*x */ + void *A_par; /* parameters for Ax */ + + Fun_Ax ATx; /* function computing y = A^T*x; + T = transpose */ + void *AT_par; /* parameters for ATx */ + + Fun_Ax Bx; /* function computing y = B*x; B - preconditioner */ + void *B_par; /* parameters for Bx */ + + Fun_Ax BTx; /* function computing y = B^T*x; B - preconditioner */ + void *BT_par; /* parameters for BTx */ + +#ifdef ANSI_C + +#ifdef PROTOTYPES_IN_STRUCT + void (*info)(struct Iter_data *, double, VEC *,VEC *); + /* function giving some information for a user; + nres - a norm of a residual res */ + + int (*stop_crit)(struct Iter_data *, double, VEC *,VEC *); + /* stopping criterion: + nres - a norm of res; + res - residual; + if returned value == TRUE then stop; + if returned value == FALSE then continue; */ +#else + void (*info)(); + int (*stop_crit)(); +#endif /* PROTOTYPES_IN_STRUCT */ + +#else + + void (*info)(); + /* function giving some information for a user */ + + int (*stop_crit)(); + /* stopping criterion: + if returned value == TRUE then stop; + if returned value == FALSE then continue; */ + +#endif /* ANSI_C */ + + Real init_res; /* the norm of the initial residual */ + +} ITER; + + +#define INULL (ITER *)NULL + +/* type Fun_info */ +#ifdef ANSI_C +typedef void (*Fun_info)(ITER *, double, VEC *,VEC *); +#else +typedef void (*Fun_info)(); +#endif + +/* type Fun_stp_crt */ +#ifdef ANSI_C +typedef int (*Fun_stp_crt)(ITER *, double, VEC *,VEC *); +#else +typedef int (*Fun_stp_crt)(); +#endif + + + +/* macros */ +/* default values */ + +#define ITER_LIMIT_DEF 1000 +#define ITER_EPS_DEF 1e-6 + +/* other macros */ + +/* set ip->Ax=fun and ip->A_par=fun_par */ +#define iter_Ax(ip,fun,fun_par) \ + (ip->Ax=(Fun_Ax)(fun),ip->A_par=(void *)(fun_par),0) +#define iter_ATx(ip,fun,fun_par) \ + (ip->ATx=(Fun_Ax)(fun),ip->AT_par=(void *)(fun_par),0) +#define iter_Bx(ip,fun,fun_par) \ + (ip->Bx=(Fun_Ax)(fun),ip->B_par=(void *)(fun_par),0) +#define iter_BTx(ip,fun,fun_par) \ + (ip->BTx=(Fun_Ax)(fun),ip->BT_par=(void *)(fun_par),0) + +/* save free macro */ +#define ITER_FREE(ip) (iter_free(ip), (ip)=(ITER *)NULL) + + +/* prototypes from iter0.c */ + +#ifdef ANSI_C +/* standard information */ +void iter_std_info(const ITER *ip,double nres,VEC *res,VEC *Bres); +/* standard stopping criterion */ +int iter_std_stop_crit(const ITER *ip, double nres, VEC *res,VEC *Bres); + +/* get, resize and free ITER variable */ +ITER *iter_get(int lenb, int lenx); +ITER *iter_resize(ITER *ip,int lenb,int lenx); +int iter_free(ITER *ip); + +void iter_dump(FILE *fp,ITER *ip); + +/* copy ip1 to ip2 copying also elements of x and b */ +ITER *iter_copy(const ITER *ip1, ITER *ip2); +/* copy ip1 to ip2 without copying elements of x and b */ +ITER *iter_copy2(ITER *ip1,ITER *ip2); + +/* functions for generating sparse matrices with random elements */ +SPMAT *iter_gen_sym(int n, int nrow); +SPMAT *iter_gen_nonsym(int m,int n,int nrow,double diag); +SPMAT *iter_gen_nonsym_posdef(int n,int nrow); + +#else + +void iter_std_info(); +int iter_std_stop_crit(); +ITER *iter_get(); +int iter_free(); +ITER *iter_resize(); +void iter_dump(); +ITER *iter_copy(); +ITER *iter_copy2(); +SPMAT *iter_gen_sym(); +SPMAT *iter_gen_nonsym(); +SPMAT *iter_gen_nonsym_posdef(); + +#endif + +/* prototypes from iter.c */ + +/* different iterative procedures */ +#ifdef ANSI_C +VEC *iter_cg(ITER *ip); +VEC *iter_cg1(ITER *ip); +VEC *iter_spcg(SPMAT *A,SPMAT *LLT,VEC *b,double eps,VEC *x,int limit, + int *steps); +VEC *iter_cgs(ITER *ip,VEC *r0); +VEC *iter_spcgs(SPMAT *A,SPMAT *B,VEC *b,VEC *r0,double eps,VEC *x, + int limit, int *steps); +VEC *iter_lsqr(ITER *ip); +VEC *iter_splsqr(SPMAT *A,VEC *b,double tol,VEC *x, + int limit,int *steps); +VEC *iter_gmres(ITER *ip); +VEC *iter_spgmres(SPMAT *A,SPMAT *B,VEC *b,double tol,VEC *x,int k, + int limit, int *steps); +MAT *iter_arnoldi_iref(ITER *ip,Real *h,MAT *Q,MAT *H); +MAT *iter_arnoldi(ITER *ip,Real *h,MAT *Q,MAT *H); +MAT *iter_sparnoldi(SPMAT *A,VEC *x0,int k,Real *h,MAT *Q,MAT *H); +VEC *iter_mgcr(ITER *ip); +VEC *iter_spmgcr(SPMAT *A,SPMAT *B,VEC *b,double tol,VEC *x,int k, + int limit, int *steps); +void iter_lanczos(ITER *ip,VEC *a,VEC *b,Real *beta2,MAT *Q); +void iter_splanczos(SPMAT *A,int m,VEC *x0,VEC *a,VEC *b,Real *beta2, + MAT *Q); +VEC *iter_lanczos2(ITER *ip,VEC *evals,VEC *err_est); +VEC *iter_splanczos2(SPMAT *A,int m,VEC *x0,VEC *evals,VEC *err_est); +VEC *iter_cgne(ITER *ip); +VEC *iter_spcgne(SPMAT *A,SPMAT *B,VEC *b,double eps,VEC *x, + int limit,int *steps); +#else +VEC *iter_cg(); +VEC *iter_cg1(); +VEC *iter_spcg(); +VEC *iter_cgs(); +VEC *iter_spcgs(); +VEC *iter_lsqr(); +VEC *iter_splsqr(); +VEC *iter_gmres(); +VEC *iter_spgmres(); +MAT *iter_arnoldi_iref(); +MAT *iter_arnoldi(); +MAT *iter_sparnoldi(); +VEC *iter_mgcr(); +VEC *iter_spmgcr(); +void iter_lanczos(); +void iter_splanczos(); +VEC *iter_lanczos2(); +VEC *iter_splanczos2(); +VEC *iter_cgne(); +VEC *iter_spcgne(); + +#endif + + +#endif /* ITERHH */ diff --git a/iter0.c b/iter0.c new file mode 100644 index 0000000..4444153 --- /dev/null +++ b/iter0.c @@ -0,0 +1,435 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* iter0.c 14/09/93 */ + +/* ITERATIVE METHODS - service functions */ + +/* functions for creating and releasing ITER structures; + for memory information; + for getting some values from an ITER variable; + for changing values in an ITER variable; + see also iter.c +*/ + +#include +#include +#include "iter.h" + + +static char rcsid[] = "$Id: iter0.c,v 1.3 1995/01/30 14:50:56 des Exp $"; + + +/* standard functions */ + +/* standard information */ +#ifndef ANSI_C +void iter_std_info(ip,nres,res,Bres) +ITER *ip; +double nres; +VEC *res, *Bres; +#else +void iter_std_info(const ITER *ip, double nres, VEC *res, VEC *Bres) +#endif +{ + if (nres >= 0.0) +#ifndef MEX + printf(" %d. residual = %g\n",ip->steps,nres); +#else + mexPrintf(" %d. residual = %g\n",ip->steps,nres); +#endif + else +#ifndef MEX + printf(" %d. residual = %g (WARNING !!! should be >= 0) \n", + ip->steps,nres); +#else + mexPrintf(" %d. residual = %g (WARNING !!! should be >= 0) \n", + ip->steps,nres); +#endif +} + +/* standard stopping criterion */ +#ifndef ANSI_C +int iter_std_stop_crit(ip, nres, res, Bres) +ITER *ip; +double nres; +VEC *res, *Bres; +#else +int iter_std_stop_crit(const ITER *ip, double nres, VEC *res, VEC *Bres) +#endif +{ + /* standard stopping criterium */ + if (nres <= ip->init_res*ip->eps) return TRUE; + return FALSE; +} + + +/* iter_get - create a new structure pointing to ITER */ +#ifndef ANSI_C +ITER *iter_get(lenb, lenx) +int lenb, lenx; +#else +ITER *iter_get(int lenb, int lenx) +#endif +{ + ITER *ip; + + if ((ip = NEW(ITER)) == (ITER *) NULL) + error(E_MEM,"iter_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ITER,0,sizeof(ITER)); + mem_numvar(TYPE_ITER,1); + } + + /* default values */ + + ip->shared_x = FALSE; + ip->shared_b = FALSE; + ip->k = 0; + ip->limit = ITER_LIMIT_DEF; + ip->eps = ITER_EPS_DEF; + ip->steps = 0; + + if (lenb > 0) ip->b = v_get(lenb); + else ip->b = (VEC *)NULL; + + if (lenx > 0) ip->x = v_get(lenx); + else ip->x = (VEC *)NULL; + + ip->Ax = (Fun_Ax) NULL; + ip->A_par = NULL; + ip->ATx = (Fun_Ax) NULL; + ip->AT_par = NULL; + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + ip->info = iter_std_info; + ip->stop_crit = iter_std_stop_crit; + ip->init_res = 0.0; + + return ip; +} + + +/* iter_free - release memory */ +#ifndef ANSI_C +int iter_free(ip) +ITER *ip; +#else +int iter_free(ITER *ip) +#endif +{ + if (ip == (ITER *)NULL) return -1; + + if (mem_info_is_on()) { + mem_bytes(TYPE_ITER,sizeof(ITER),0); + mem_numvar(TYPE_ITER,-1); + } + + if ( !ip->shared_x && ip->x != NULL ) v_free(ip->x); + if ( !ip->shared_b && ip->b != NULL ) v_free(ip->b); + + free((char *)ip); + + return 0; +} + +#ifndef ANSI_C +ITER *iter_resize(ip,new_lenb,new_lenx) +ITER *ip; +int new_lenb, new_lenx; +#else +ITER *iter_resize(ITER *ip, int new_lenb, int new_lenx) +#endif +{ + VEC *old; + + if ( ip == (ITER *) NULL) + error(E_NULL,"iter_resize"); + + old = ip->x; + ip->x = v_resize(ip->x,new_lenx); + if ( ip->shared_x && old != ip->x ) + warning(WARN_SHARED_VEC,"iter_resize"); + old = ip->b; + ip->b = v_resize(ip->b,new_lenb); + if ( ip->shared_b && old != ip->b ) + warning(WARN_SHARED_VEC,"iter_resize"); + + return ip; +} + +#ifndef MEX +/* print out ip structure - for diagnostic purposes mainly */ +#ifndef ANSI_C +void iter_dump(fp,ip) +ITER *ip; +FILE *fp; +#else +void iter_dump(FILE *fp, ITER *ip) +#endif +{ + if (ip == NULL) { + fprintf(fp," ITER structure: NULL\n"); + return; + } + + fprintf(fp,"\n ITER structure:\n"); + fprintf(fp," ip->shared_x = %s, ip->shared_b = %s\n", + (ip->shared_x ? "TRUE" : "FALSE"), + (ip->shared_b ? "TRUE" : "FALSE") ); + fprintf(fp," ip->k = %d, ip->limit = %d, ip->steps = %d, ip->eps = %g\n", + ip->k,ip->limit,ip->steps,ip->eps); + fprintf(fp," ip->x = 0x%p, ip->b = 0x%p\n",ip->x,ip->b); + fprintf(fp," ip->Ax = 0x%p, ip->A_par = 0x%p\n",ip->Ax,ip->A_par); + fprintf(fp," ip->ATx = 0x%p, ip->AT_par = 0x%p\n",ip->ATx,ip->AT_par); + fprintf(fp," ip->Bx = 0x%p, ip->B_par = 0x%p\n",ip->Bx,ip->B_par); + fprintf(fp," ip->info = 0x%p, ip->stop_crit = 0x%p, ip->init_res = %g\n", + ip->info,ip->stop_crit,ip->init_res); + fprintf(fp,"\n"); + +} +#endif + +/* copy the structure ip1 to ip2 preserving vectors x and b of ip2 + (vectors x and b in ip2 are the same before and after iter_copy2) + if ip2 == NULL then a new structure is created with x and b being NULL + and other members are taken from ip1 +*/ +#ifndef ANSI_C +ITER *iter_copy2(ip1,ip2) +ITER *ip1, *ip2; +#else +ITER *iter_copy2(ITER *ip1, ITER *ip2) +#endif +{ + VEC *x, *b; + int shx, shb; + + if (ip1 == (ITER *)NULL) + error(E_NULL,"iter_copy2"); + + if (ip2 == (ITER *)NULL) { + if ((ip2 = NEW(ITER)) == (ITER *) NULL) + error(E_MEM,"iter_copy2"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ITER,0,sizeof(ITER)); + mem_numvar(TYPE_ITER,1); + } + ip2->x = ip2->b = NULL; + ip2->shared_x = ip2->shared_x = FALSE; + } + + x = ip2->x; + b = ip2->b; + shb = ip2->shared_b; + shx = ip2->shared_x; + MEM_COPY(ip1,ip2,sizeof(ITER)); + ip2->x = x; + ip2->b = b; + ip2->shared_x = shx; + ip2->shared_b = shb; + + return ip2; +} + + +/* copy the structure ip1 to ip2 copying also the vectors x and b */ +#ifndef ANSI_C +ITER *iter_copy(ip1,ip2) +ITER *ip1, *ip2; +#else +ITER *iter_copy(const ITER *ip1, ITER *ip2) +#endif +{ + VEC *x, *b; + + if (ip1 == (ITER *)NULL) + error(E_NULL,"iter_copy"); + + if (ip2 == (ITER *)NULL) { + if ((ip2 = NEW(ITER)) == (ITER *) NULL) + error(E_MEM,"iter_copy2"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ITER,0,sizeof(ITER)); + mem_numvar(TYPE_ITER,1); + } + } + + x = ip2->x; + b = ip2->b; + + MEM_COPY(ip1,ip2,sizeof(ITER)); + if (ip1->x) + ip2->x = v_copy(ip1->x,x); + if (ip1->b) + ip2->b = v_copy(ip1->b,b); + + ip2->shared_x = ip2->shared_b = FALSE; + + return ip2; +} + + +/*** functions to generate sparse matrices with random entries ***/ + + +/* iter_gen_sym -- generate symmetric positive definite + n x n matrix, + nrow - number of nonzero entries in a row + */ +#ifndef ANSI_C +SPMAT *iter_gen_sym(n,nrow) +int n, nrow; +#else +SPMAT *iter_gen_sym(int n, int nrow) +#endif +{ + SPMAT *A; + VEC *u; + Real s1; + int i, j, k, k_max; + + if (nrow <= 1) nrow = 2; + /* nrow should be even */ + if ((nrow & 1)) nrow -= 1; + A = sp_get(n,n,nrow); + u = v_get(A->m); + v_zero(u); + for ( i = 0; i < A->m; i++ ) + { + k_max = ((rand() >> 8) % (nrow/2)); + for ( k = 0; k <= k_max; k++ ) + { + j = (rand() >> 8) % A->n; + s1 = mrand(); + sp_set_val(A,i,j,s1); + sp_set_val(A,j,i,s1); + u->ve[i] += fabs(s1); + u->ve[j] += fabs(s1); + } + } + /* ensure that A is positive definite */ + for ( i = 0; i < A->m; i++ ) + sp_set_val(A,i,i,u->ve[i] + 1.0); + + V_FREE(u); + return A; +} + + +/* iter_gen_nonsym -- generate non-symmetric m x n sparse matrix, m >= n + nrow - number of entries in a row; + diag - number which is put in diagonal entries and then permuted + (if diag is zero then 1.0 is there) +*/ +#ifndef ANSI_C +SPMAT *iter_gen_nonsym(m,n,nrow,diag) +int m, n, nrow; +double diag; +#else +SPMAT *iter_gen_nonsym(int m, int n, int nrow, double diag) +#endif +{ + SPMAT *A; + PERM *px; + int i, j, k, k_max; + Real s1; + + if (nrow <= 1) nrow = 2; + if (diag == 0.0) diag = 1.0; + A = sp_get(m,n,nrow); + px = px_get(n); + for ( i = 0; i < A->m; i++ ) + { + k_max = (rand() >> 8) % (nrow-1); + for ( k = 0; k <= k_max; k++ ) + { + j = (rand() >> 8) % A->n; + s1 = mrand(); + sp_set_val(A,i,j,-s1); + } + } + /* to make it likely that A is nonsingular, use pivot... */ + for ( i = 0; i < 2*A->n; i++ ) + { + j = (rand() >> 8) % A->n; + k = (rand() >> 8) % A->n; + px_transp(px,j,k); + } + for ( i = 0; i < A->n; i++ ) + sp_set_val(A,i,px->pe[i],diag); + + PX_FREE(px); + return A; +} + +#if ( 0 ) +/* iter_gen_nonsym -- generate non-symmetric positive definite + n x n sparse matrix; + nrow - number of entries in a row +*/ +#ifndef ANSI_C +SPMAT *iter_gen_nonsym_posdef(n,nrow) +int n, nrow; +#else +SPMAT *iter_gen_nonsym(int m, int n, int nrow, double diag) +#endif +{ + SPMAT *A; + PERM *px; + VEC *u; + int i, j, k, k_max; + Real s1; + + if (nrow <= 1) nrow = 2; + A = sp_get(n,n,nrow); + px = px_get(n); + u = v_get(A->m); + v_zero(u); + for ( i = 0; i < A->m; i++ ) + { + k_max = (rand() >> 8) % (nrow-1); + for ( k = 0; k <= k_max; k++ ) + { + j = (rand() >> 8) % A->n; + s1 = mrand(); + sp_set_val(A,i,j,-s1); + u->ve[i] += fabs(s1); + } + } + /* ensure that A is positive definite */ + for ( i = 0; i < A->m; i++ ) + sp_set_val(A,i,i,u->ve[i] + 1.0); + + PX_FREE(px); + V_FREE(u); + return A; +} +#endif + + + + diff --git a/iternsym.c b/iternsym.c new file mode 100644 index 0000000..573569a --- /dev/null +++ b/iternsym.c @@ -0,0 +1,1395 @@ + + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* iter.c 17/09/93 */ + +/* + ITERATIVE METHODS - implementation of several iterative methods; + see also iter0.c +*/ + +#include +#include +#include "matrix.h" +#include "matrix2.h" +#include "sparse.h" +#include "iter.h" + +static char rcsid[] = "$Header: iternsym.c,v 1.6 1995/01/30 14:53:01 des Exp $"; + + +#ifdef ANSI_C +VEC *spCHsolve(SPMAT *,VEC *,VEC *); +#else +VEC *spCHsolve(); +#endif + + +/* + iter_cgs -- uses CGS to compute a solution x to A.x=b +*/ +#ifndef ANSI_C +VEC *iter_cgs(ip,r0) +ITER *ip; +VEC *r0; +#else +VEC *iter_cgs(ITER *ip, VEC *r0) +#endif +{ + STATIC VEC *p = VNULL, *q = VNULL, *r = VNULL, *u = VNULL; + STATIC VEC *v = VNULL, *z = VNULL; + VEC *tmp; + Real alpha, beta, nres, rho, old_rho, sigma, inner; + + if (ip == INULL) + error(E_NULL,"iter_cgs"); + if (!ip->Ax || !ip->b || !r0) + error(E_NULL,"iter_cgs"); + if ( ip->x == ip->b ) + error(E_INSITU,"iter_cgs"); + if (!ip->stop_crit) + error(E_NULL,"iter_cgs"); + if ( r0->dim != ip->b->dim ) + error(E_SIZES,"iter_cgs"); + + if ( ip->eps <= 0.0 ) ip->eps = MACHEPS; + + p = v_resize(p,ip->b->dim); + q = v_resize(q,ip->b->dim); + r = v_resize(r,ip->b->dim); + u = v_resize(u,ip->b->dim); + v = v_resize(v,ip->b->dim); + + MEM_STAT_REG(p,TYPE_VEC); + MEM_STAT_REG(q,TYPE_VEC); + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(v,TYPE_VEC); + + if (ip->Bx) { + z = v_resize(z,ip->b->dim); + MEM_STAT_REG(z,TYPE_VEC); + } + + if (ip->x != VNULL) { + if (ip->x->dim != ip->b->dim) + error(E_SIZES,"iter_cgs"); + ip->Ax(ip->A_par,ip->x,v); /* v = A*x */ + if (ip->Bx) { + v_sub(ip->b,v,v); /* v = b - A*x */ + (ip->Bx)(ip->B_par,v,r); /* r = B*(b-A*x) */ + } + else v_sub(ip->b,v,r); /* r = b-A*x */ + } + else { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); /* x == 0 */ + ip->shared_x = FALSE; + if (ip->Bx) (ip->Bx)(ip->B_par,ip->b,r); /* r = B*b */ + else v_copy(ip->b,r); /* r = b */ + } + + v_zero(p); + v_zero(q); + old_rho = 1.0; + + for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) { + + inner = in_prod(r,r); + nres = sqrt(fabs(inner)); + if (ip->steps == 0) ip->init_res = nres; + + if (ip->info) ip->info(ip,nres,r,VNULL); + if ( ip->stop_crit(ip,nres,r,VNULL) ) break; + + rho = in_prod(r0,r); + if ( old_rho == 0.0 ) + error(E_BREAKDOWN,"iter_cgs"); + beta = rho/old_rho; + v_mltadd(r,q,beta,u); + v_mltadd(q,p,beta,v); + v_mltadd(u,v,beta,p); + + (ip->Ax)(ip->A_par,p,q); + if (ip->Bx) { + (ip->Bx)(ip->B_par,q,z); + tmp = z; + } + else tmp = q; + + sigma = in_prod(r0,tmp); + if ( sigma == 0.0 ) + error(E_BREAKDOWN,"iter_cgs"); + alpha = rho/sigma; + v_mltadd(u,tmp,-alpha,q); + v_add(u,q,v); + + (ip->Ax)(ip->A_par,v,u); + if (ip->Bx) { + (ip->Bx)(ip->B_par,u,z); + tmp = z; + } + else tmp = u; + + v_mltadd(r,tmp,-alpha,r); + v_mltadd(ip->x,v,alpha,ip->x); + + old_rho = rho; + } + +#ifdef THREADSAFE + V_FREE(p); V_FREE(q); V_FREE(r); V_FREE(u); + V_FREE(v); V_FREE(z); +#endif + + return ip->x; +} + + + +/* iter_spcgs -- simple interface for SPMAT data structures + use always as follows: + x = iter_spcgs(A,B,b,r0,tol,x,limit,steps); + or + x = iter_spcgs(A,B,b,r0,tol,VNULL,limit,steps); + In the second case the solution vector is created. + If B is not NULL then it is a preconditioner. +*/ +#ifndef ANSI_C +VEC *iter_spcgs(A,B,b,r0,tol,x,limit,steps) +SPMAT *A, *B; +VEC *b, *r0, *x; +double tol; +int *steps,limit; +#else +VEC *iter_spcgs(SPMAT *A, SPMAT *B, VEC *b, VEC *r0, double tol, + VEC *x, int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + if (B) { + ip->Bx = (Fun_Ax) sp_mv_mlt; + ip->B_par = (void *) B; + } + else { + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + } + ip->info = (Fun_info) NULL; + ip->limit = limit; + ip->b = b; + ip->eps = tol; + ip->x = x; + iter_cgs(ip,r0); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; + +} + +/* + Routine for performing LSQR -- the least squares QR algorithm + of Paige and Saunders: + "LSQR: an algorithm for sparse linear equations and + sparse least squares", ACM Trans. Math. Soft., v. 8 + pp. 43--71 (1982) + */ +/* iter_lsqr -- sparse CG-like least squares routine: + -- finds min_x ||A.x-b||_2 using A defined through A & AT + -- returns x (if x != NULL) */ +#ifndef ANSI_C +VEC *iter_lsqr(ip) +ITER *ip; +#else +VEC *iter_lsqr(ITER *ip) +#endif +{ + STATIC VEC *u = VNULL, *v = VNULL, *w = VNULL, *tmp = VNULL; + Real alpha, beta, phi, phi_bar; + Real rho, rho_bar, rho_max, theta, nres; + Real s, c; /* for Givens' rotations */ + int m, n; + + if ( ! ip || ! ip->b || !ip->Ax || !ip->ATx ) + error(E_NULL,"iter_lsqr"); + if ( ip->x == ip->b ) + error(E_INSITU,"iter_lsqr"); + if (!ip->stop_crit || !ip->x) + error(E_NULL,"iter_lsqr"); + + if ( ip->eps <= 0.0 ) ip->eps = MACHEPS; + + m = ip->b->dim; + n = ip->x->dim; + + u = v_resize(u,(unsigned int)m); + v = v_resize(v,(unsigned int)n); + w = v_resize(w,(unsigned int)n); + tmp = v_resize(tmp,(unsigned int)n); + + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(v,TYPE_VEC); + MEM_STAT_REG(w,TYPE_VEC); + MEM_STAT_REG(tmp,TYPE_VEC); + + if (ip->x != VNULL) { + ip->Ax(ip->A_par,ip->x,u); /* u = A*x */ + v_sub(ip->b,u,u); /* u = b-A*x */ + } + else { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + v_copy(ip->b,u); /* u = b */ + } + + beta = v_norm2(u); + if ( beta == 0.0 ) return ip->x; + + sv_mlt(1.0/beta,u,u); + (ip->ATx)(ip->AT_par,u,v); + alpha = v_norm2(v); + if ( alpha == 0.0 ) return ip->x; + + sv_mlt(1.0/alpha,v,v); + v_copy(v,w); + phi_bar = beta; + rho_bar = alpha; + + rho_max = 1.0; + for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) { + + tmp = v_resize(tmp,m); + (ip->Ax)(ip->A_par,v,tmp); + + v_mltadd(tmp,u,-alpha,u); + beta = v_norm2(u); + sv_mlt(1.0/beta,u,u); + + tmp = v_resize(tmp,n); + (ip->ATx)(ip->AT_par,u,tmp); + v_mltadd(tmp,v,-beta,v); + alpha = v_norm2(v); + sv_mlt(1.0/alpha,v,v); + + rho = sqrt(rho_bar*rho_bar+beta*beta); + if ( rho > rho_max ) + rho_max = rho; + c = rho_bar/rho; + s = beta/rho; + theta = s*alpha; + rho_bar = -c*alpha; + phi = c*phi_bar; + phi_bar = s*phi_bar; + + /* update ip->x & w */ + if ( rho == 0.0 ) + error(E_BREAKDOWN,"iter_lsqr"); + v_mltadd(ip->x,w,phi/rho,ip->x); + v_mltadd(v,w,-theta/rho,w); + + nres = fabs(phi_bar*alpha*c)*rho_max; + + if (ip->info) ip->info(ip,nres,w,VNULL); + if (ip->steps == 0) ip->init_res = nres; + if ( ip->stop_crit(ip,nres,w,VNULL) ) break; + } + +#ifdef THREADSAFE + V_FREE(u); V_FREE(v); V_FREE(w); V_FREE(tmp); +#endif + + return ip->x; +} + +/* iter_splsqr -- simple interface for SPMAT data structures */ +#ifndef ANSI_C +VEC *iter_splsqr(A,b,tol,x,limit,steps) +SPMAT *A; +VEC *b, *x; +double tol; +int *steps,limit; +#else +VEC *iter_splsqr(SPMAT *A, VEC *b, double tol, + VEC *x, int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + ip->ATx = (Fun_Ax) sp_vm_mlt; + ip->AT_par = (void *) A; + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + + ip->info = (Fun_info) NULL; + ip->limit = limit; + ip->b = b; + ip->eps = tol; + ip->x = x; + iter_lsqr(ip); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; +} + + + +/* iter_arnoldi -- an implementation of the Arnoldi method; + iterative refinement is applied. +*/ +#ifndef ANSI_C +MAT *iter_arnoldi_iref(ip,h_rem,Q,H) +ITER *ip; +Real *h_rem; +MAT *Q, *H; +#else +MAT *iter_arnoldi_iref(ITER *ip, Real *h_rem, MAT *Q, MAT *H) +#endif +{ + STATIC VEC *u=VNULL, *r=VNULL, *s=VNULL, *tmp=VNULL; + VEC v; /* auxiliary vector */ + int i,j; + Real h_val, c; + + if (ip == INULL) + error(E_NULL,"iter_arnoldi_iref"); + if ( ! ip->Ax || ! Q || ! ip->x ) + error(E_NULL,"iter_arnoldi_iref"); + if ( ip->k <= 0 ) + error(E_BOUNDS,"iter_arnoldi_iref"); + if ( Q->n != ip->x->dim || Q->m != ip->k ) + error(E_SIZES,"iter_arnoldi_iref"); + + m_zero(Q); + H = m_resize(H,ip->k,ip->k); + m_zero(H); + + u = v_resize(u,ip->x->dim); + r = v_resize(r,ip->k); + s = v_resize(s,ip->k); + tmp = v_resize(tmp,ip->x->dim); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(s,TYPE_VEC); + MEM_STAT_REG(tmp,TYPE_VEC); + + v.dim = v.max_dim = ip->x->dim; + + c = v_norm2(ip->x); + if ( c <= 0.0) + return H; + else { + v.ve = Q->me[0]; + sv_mlt(1.0/c,ip->x,&v); + } + + v_zero(r); + v_zero(s); + for ( i = 0; i < ip->k; i++ ) + { + v.ve = Q->me[i]; + u = (ip->Ax)(ip->A_par,&v,u); + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + /* modified Gram-Schmidt */ + r->ve[j] = in_prod(&v,u); + v_mltadd(u,&v,-r->ve[j],u); + } + h_val = v_norm2(u); + /* if u == 0 then we have an exact subspace */ + if ( h_val <= 0.0 ) + { + *h_rem = h_val; + return H; + } + /* iterative refinement -- ensures near orthogonality */ + do { + v_zero(tmp); + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + s->ve[j] = in_prod(&v,u); + v_mltadd(tmp,&v,s->ve[j],tmp); + } + v_sub(u,tmp,u); + v_add(r,s,r); + } while ( v_norm2(s) > 0.1*(h_val = v_norm2(u)) ); + /* now that u is nearly orthogonal to Q, update H */ + set_col(H,i,r); + /* check once again if h_val is zero */ + if ( h_val <= 0.0 ) + { + *h_rem = h_val; + return H; + } + if ( i == ip->k-1 ) + { + *h_rem = h_val; + continue; + } + /* H->me[i+1][i] = h_val; */ + m_set_val(H,i+1,i,h_val); + v.ve = Q->me[i+1]; + sv_mlt(1.0/h_val,u,&v); + } + +#ifdef THREADSAFE + V_FREE(u); V_FREE(r); V_FREE(s); V_FREE(tmp); +#endif + + return H; +} + +/* iter_arnoldi -- an implementation of the Arnoldi method; + modified Gram-Schmidt algorithm +*/ +#ifndef ANSI_C +MAT *iter_arnoldi(ip,h_rem,Q,H) +ITER *ip; +Real *h_rem; +MAT *Q, *H; +#else +MAT *iter_arnoldi(ITER *ip, Real *h_rem, MAT *Q, MAT *H) +#endif +{ + STATIC VEC *u=VNULL, *r=VNULL; + VEC v; /* auxiliary vector */ + int i,j; + Real h_val, c; + + if (ip == INULL) + error(E_NULL,"iter_arnoldi"); + if ( ! ip->Ax || ! Q || ! ip->x ) + error(E_NULL,"iter_arnoldi"); + if ( ip->k <= 0 ) + error(E_BOUNDS,"iter_arnoldi"); + if ( Q->n != ip->x->dim || Q->m != ip->k ) + error(E_SIZES,"iter_arnoldi"); + + m_zero(Q); + H = m_resize(H,ip->k,ip->k); + m_zero(H); + + u = v_resize(u,ip->x->dim); + r = v_resize(r,ip->k); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(r,TYPE_VEC); + + v.dim = v.max_dim = ip->x->dim; + + c = v_norm2(ip->x); + if ( c <= 0.0) + return H; + else { + v.ve = Q->me[0]; + sv_mlt(1.0/c,ip->x,&v); + } + + v_zero(r); + for ( i = 0; i < ip->k; i++ ) + { + v.ve = Q->me[i]; + u = (ip->Ax)(ip->A_par,&v,u); + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + /* modified Gram-Schmidt */ + r->ve[j] = in_prod(&v,u); + v_mltadd(u,&v,-r->ve[j],u); + } + h_val = v_norm2(u); + /* if u == 0 then we have an exact subspace */ + if ( h_val <= 0.0 ) + { + *h_rem = h_val; + return H; + } + set_col(H,i,r); + if ( i == ip->k-1 ) + { + *h_rem = h_val; + continue; + } + /* H->me[i+1][i] = h_val; */ + m_set_val(H,i+1,i,h_val); + v.ve = Q->me[i+1]; + sv_mlt(1.0/h_val,u,&v); + } + +#ifdef THREADSAFE + V_FREE(u); V_FREE(r); +#endif + + return H; +} + + + +/* iter_sparnoldi -- uses arnoldi() with an explicit representation of A */ +#ifndef ANSI_C +MAT *iter_sparnoldi(A,x0,m,h_rem,Q,H) +SPMAT *A; +VEC *x0; +int m; +Real *h_rem; +MAT *Q, *H; +#else +MAT *iter_sparnoldi(SPMAT *A, VEC *x0, int m, Real *h_rem, MAT *Q, MAT *H) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + ip->x = x0; + ip->k = m; + iter_arnoldi_iref(ip,h_rem,Q,H); + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return H; +} + + +/* for testing gmres */ +#ifndef ANSI_C +static void test_gmres(ip,i,Q,R,givc,givs,h_val) +ITER *ip; +int i; +MAT *Q, *R; +VEC *givc, *givs; +double h_val; +#else +static void test_gmres(ITER *ip, int i, MAT *Q, MAT *R, + VEC *givc, VEC *givs, double h_val) +#endif +{ + VEC vt, vt1; + STATIC MAT *Q1=MNULL, *R1=MNULL; + int j; + + /* test Q*A*Q^T = R */ + + Q = m_resize(Q,i+1,ip->b->dim); + Q1 = m_resize(Q1,i+1,ip->b->dim); + R1 = m_resize(R1,i+1,i+1); + MEM_STAT_REG(Q1,TYPE_MAT); + MEM_STAT_REG(R1,TYPE_MAT); + + vt.dim = vt.max_dim = ip->b->dim; + vt1.dim = vt1.max_dim = ip->b->dim; + for (j=0; j <= i; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + ip->Ax(ip->A_par,&vt,&vt1); + } + + mmtr_mlt(Q,Q1,R1); + R1 = m_resize(R1,i+2,i+1); + for (j=0; j < i; j++) + R1->me[i+1][j] = 0.0; + R1->me[i+1][i] = h_val; + + for (j = 0; j <= i; j++) { + rot_rows(R1,j,j+1,givc->ve[j],givs->ve[j],R1); + } + + R1 = m_resize(R1,i+1,i+1); + m_sub(R,R1,R1); + /* if (m_norm_inf(R1) > MACHEPS*ip->b->dim) */ +#ifndef MEX + printf(" %d. ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + ip->steps,m_norm_inf(R1),MACHEPS); +#endif + + /* check Q*Q^T = I */ + + Q = m_resize(Q,i+1,ip->b->dim); + mmtr_mlt(Q,Q,R1); + for (j=0; j <= i; j++) + R1->me[j][j] -= 1.0; +#ifndef MEX + if (m_norm_inf(R1) > MACHEPS*ip->b->dim) + printf(" ! m_norm_inf(Q*Q^T) = %g\n",m_norm_inf(R1)); +#endif +#ifdef THREADSAFE + M_FREE(Q1); M_FREE(R1); +#endif +} + + +/* gmres -- generalised minimum residual algorithm of Saad & Schultz + SIAM J. Sci. Stat. Comp. v.7, pp.856--869 (1986) +*/ +#ifndef ANSI_C +VEC *iter_gmres(ip) +ITER *ip; +#else +VEC *iter_gmres(ITER *ip) +#endif +{ + STATIC VEC *u=VNULL, *r=VNULL, *rhs = VNULL; + STATIC VEC *givs=VNULL, *givc=VNULL, *z = VNULL; + STATIC MAT *Q = MNULL, *R = MNULL; + VEC *rr, v, v1; /* additional pointers (not real vectors) */ + int i,j, done; + Real nres; +/* Real last_h; */ + + if (ip == INULL) + error(E_NULL,"iter_gmres"); + if ( ! ip->Ax || ! ip->b ) + error(E_NULL,"iter_gmres"); + if ( ! ip->stop_crit ) + error(E_NULL,"iter_gmres"); + if ( ip->k <= 0 ) + error(E_BOUNDS,"iter_gmres"); + if (ip->x != VNULL && ip->x->dim != ip->b->dim) + error(E_SIZES,"iter_gmres"); + if (ip->eps <= 0.0) ip->eps = MACHEPS; + + r = v_resize(r,ip->k+1); + u = v_resize(u,ip->b->dim); + rhs = v_resize(rhs,ip->k+1); + givs = v_resize(givs,ip->k); /* Givens rotations */ + givc = v_resize(givc,ip->k); + + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(u,TYPE_VEC); + MEM_STAT_REG(rhs,TYPE_VEC); + MEM_STAT_REG(givs,TYPE_VEC); + MEM_STAT_REG(givc,TYPE_VEC); + + R = m_resize(R,ip->k+1,ip->k); + Q = m_resize(Q,ip->k,ip->b->dim); + MEM_STAT_REG(R,TYPE_MAT); + MEM_STAT_REG(Q,TYPE_MAT); + + if (ip->x == VNULL) { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + } + + v.dim = v.max_dim = ip->b->dim; /* v and v1 are pointers to rows */ + v1.dim = v1.max_dim = ip->b->dim; /* of matrix Q */ + + if (ip->Bx != (Fun_Ax)NULL) { /* if precondition is defined */ + z = v_resize(z,ip->b->dim); + MEM_STAT_REG(z,TYPE_VEC); + } + + done = FALSE; + for (ip->steps = 0; ip->steps < ip->limit; ) { + + /* restart */ + + ip->Ax(ip->A_par,ip->x,u); /* u = A*x */ + v_sub(ip->b,u,u); /* u = b - A*x */ + rr = u; /* rr is a pointer only */ + + if (ip->Bx) { + (ip->Bx)(ip->B_par,u,z); /* tmp = B*(b-A*x) */ + rr = z; + } + + nres = v_norm2(rr); + if (ip->steps == 0) { + if (ip->info) ip->info(ip,nres,VNULL,VNULL); + ip->init_res = nres; + } + + if ( nres == 0.0 ) { + done = TRUE; + break; + } + + v.ve = Q->me[0]; + sv_mlt(1.0/nres,rr,&v); + + v_zero(r); + v_zero(rhs); + rhs->ve[0] = nres; + + for ( i = 0; i < ip->k && ip->steps < ip->limit; i++ ) { + ip->steps++; + v.ve = Q->me[i]; + (ip->Ax)(ip->A_par,&v,u); + rr = u; + if (ip->Bx) { + (ip->Bx)(ip->B_par,u,z); + rr = z; + } + + if (i < ip->k - 1) { + v1.ve = Q->me[i+1]; + v_copy(rr,&v1); + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + /* r->ve[j] = in_prod(&v,rr); */ + /* modified Gram-Schmidt algorithm */ + r->ve[j] = in_prod(&v,&v1); + v_mltadd(&v1,&v,-r->ve[j],&v1); + } + + r->ve[i+1] = nres = v_norm2(&v1); + if (nres <= MACHEPS*ip->init_res) { + for (j = 0; j < i; j++) + rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r); + set_col(R,i,r); + done = TRUE; + break; + } + sv_mlt(1.0/nres,&v1,&v1); + } + else { /* i == ip->k - 1 */ + /* Q->me[ip->k] need not be computed */ + + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + r->ve[j] = in_prod(&v,rr); + } + + nres = in_prod(rr,rr) - in_prod(r,r); + if (sqrt(fabs(nres)) <= MACHEPS*ip->init_res) { + for (j = 0; j < i; j++) + rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r); + set_col(R,i,r); + done = TRUE; + break; + } + if (nres < 0.0) { /* do restart */ + i--; + ip->steps--; + break; + } + r->ve[i+1] = sqrt(nres); + } + + /* QR update */ + + /* last_h = r->ve[i+1]; */ /* for test only */ + for (j = 0; j < i; j++) + rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r); + givens(r->ve[i],r->ve[i+1],&givc->ve[i],&givs->ve[i]); + rot_vec(r,i,i+1,givc->ve[i],givs->ve[i],r); + rot_vec(rhs,i,i+1,givc->ve[i],givs->ve[i],rhs); + + set_col(R,i,r); + + nres = fabs((double) rhs->ve[i+1]); + if (ip->info) ip->info(ip,nres,VNULL,VNULL); + if ( ip->stop_crit(ip,nres,VNULL,VNULL) ) { + done = TRUE; + break; + } + } + + /* use ixi submatrix of R */ + + if (i >= ip->k) i = ip->k - 1; + + R = m_resize(R,i+1,i+1); + rhs = v_resize(rhs,i+1); + + /* test only */ + /* test_gmres(ip,i,Q,R,givc,givs,last_h); */ + + Usolve(R,rhs,rhs,0.0); /* solve a system: R*x = rhs */ + + /* new approximation */ + + for (j = 0; j <= i; j++) { + v.ve = Q->me[j]; + v_mltadd(ip->x,&v,rhs->ve[j],ip->x); + } + + if (done) break; + + /* back to old dimensions */ + + rhs = v_resize(rhs,ip->k+1); + R = m_resize(R,ip->k+1,ip->k); + + } + +#ifdef THREADSAFE + V_FREE(u); V_FREE(r); V_FREE(rhs); + V_FREE(givs); V_FREE(givc); V_FREE(z); + M_FREE(Q); M_FREE(R); +#endif + + return ip->x; +} + +/* iter_spgmres - a simple interface to iter_gmres */ +#ifndef ANSI_C +VEC *iter_spgmres(A,B,b,tol,x,k,limit,steps) +SPMAT *A, *B; +VEC *b, *x; +double tol; +int *steps,k,limit; +#else +VEC *iter_spgmres(SPMAT *A, SPMAT *B, VEC *b, double tol, + VEC *x, int k, int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + if (B) { + ip->Bx = (Fun_Ax) sp_mv_mlt; + ip->B_par = (void *) B; + } + else { + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + } + ip->k = k; + ip->limit = limit; + ip->info = (Fun_info) NULL; + ip->b = b; + ip->eps = tol; + ip->x = x; + iter_gmres(ip); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; +} + + +/* for testing mgcr */ +#ifndef ANSI_C +static void test_mgcr(ip,i,Q,R) +ITER *ip; +int i; +MAT *Q, *R; +#else +static void test_mgcr(ITER *ip, int i, MAT *Q, MAT *R) +#endif +{ + VEC vt, vt1; + static MAT *R1=MNULL; + static VEC *r=VNULL, *r1=VNULL; + VEC *rr; + int k,j; + Real sm; + + + /* check Q*Q^T = I */ + vt.dim = vt.max_dim = ip->b->dim; + vt1.dim = vt1.max_dim = ip->b->dim; + + Q = m_resize(Q,i+1,ip->b->dim); + R1 = m_resize(R1,i+1,i+1); + r = v_resize(r,ip->b->dim); + r1 = v_resize(r1,ip->b->dim); + MEM_STAT_REG(R1,TYPE_MAT); + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(r1,TYPE_VEC); + + m_zero(R1); + for (k=1; k <= i; k++) + for (j=1; j <= i; j++) { + vt.ve = Q->me[k]; + vt1.ve = Q->me[j]; + R1->me[k][j] = in_prod(&vt,&vt1); + } + for (j=1; j <= i; j++) + R1->me[j][j] -= 1.0; +#ifndef MEX + if (m_norm_inf(R1) > MACHEPS*ip->b->dim) + printf(" ! (mgcr:) m_norm_inf(Q*Q^T) = %g\n",m_norm_inf(R1)); +#endif + + /* check (r_i,Ap_j) = 0 for j <= i */ + + ip->Ax(ip->A_par,ip->x,r); + v_sub(ip->b,r,r); + rr = r; + if (ip->Bx) { + ip->Bx(ip->B_par,r,r1); + rr = r1; + } + +#ifndef MEX + printf(" ||r|| = %g\n",v_norm2(rr)); +#endif + sm = 0.0; + for (j = 1; j <= i; j++) { + vt.ve = Q->me[j]; + sm = max(sm,in_prod(&vt,rr)); + } +#ifndef MEX + if (sm >= MACHEPS*ip->b->dim) + printf(" ! (mgcr:) max_j (r,Ap_j) = %g\n",sm); +#endif + +} + + + + +/* + iter_mgcr -- modified generalized conjugate residual algorithm; + fast version of GCR; +*/ +#ifndef ANSI_C +VEC *iter_mgcr(ip) +ITER *ip; +#else +VEC *iter_mgcr(ITER *ip) +#endif +{ + STATIC VEC *As=VNULL, *beta=VNULL, *alpha=VNULL, *z=VNULL; + STATIC MAT *N=MNULL, *H=MNULL; + + VEC *rr, v, s; /* additional pointer and structures */ + Real nres; /* norm of a residual */ + Real dd; /* coefficient d_i */ + int i,j; + int done; /* if TRUE then stop the iterative process */ + int dim; /* dimension of the problem */ + + /* ip cannot be NULL */ + if (ip == INULL) error(E_NULL,"mgcr"); + /* Ax, b and stopping criterion must be given */ + if (! ip->Ax || ! ip->b || ! ip->stop_crit) + error(E_NULL,"mgcr"); + /* at least one direction vector must exist */ + if ( ip->k <= 0) error(E_BOUNDS,"mgcr"); + /* if the vector x is given then b and x must have the same dimension */ + if ( ip->x && ip->x->dim != ip->b->dim) + error(E_SIZES,"mgcr"); + if (ip->eps <= 0.0) ip->eps = MACHEPS; + + dim = ip->b->dim; + As = v_resize(As,dim); + alpha = v_resize(alpha,ip->k); + beta = v_resize(beta,ip->k); + + MEM_STAT_REG(As,TYPE_VEC); + MEM_STAT_REG(alpha,TYPE_VEC); + MEM_STAT_REG(beta,TYPE_VEC); + + H = m_resize(H,ip->k,ip->k); + N = m_resize(N,ip->k,dim); + + MEM_STAT_REG(H,TYPE_MAT); + MEM_STAT_REG(N,TYPE_MAT); + + /* if a preconditioner is defined */ + if (ip->Bx) { + z = v_resize(z,dim); + MEM_STAT_REG(z,TYPE_VEC); + } + + /* if x is NULL then it is assumed that x has + entries with value zero */ + if ( ! ip->x ) { + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + } + + /* v and s are additional pointers to rows of N */ + /* they must have the same dimension as rows of N */ + v.dim = v.max_dim = s.dim = s.max_dim = dim; + + + done = FALSE; + for (ip->steps = 0; ip->steps < ip->limit; ) { + (*ip->Ax)(ip->A_par,ip->x,As); /* As = A*x */ + v_sub(ip->b,As,As); /* As = b - A*x */ + rr = As; /* rr is an additional pointer */ + + /* if a preconditioner is defined */ + if (ip->Bx) { + (*ip->Bx)(ip->B_par,As,z); /* z = B*(b-A*x) */ + rr = z; + } + + /* norm of the residual */ + nres = v_norm2(rr); + dd = nres; /* dd = ||r_i|| */ + + /* check if the norm of the residual is zero */ + if (ip->steps == 0) { + /* information for a user */ + if (ip->info) (*ip->info)(ip,nres,As,rr); + ip->init_res = fabs(nres); + } + + if (nres == 0.0) { + /* iterative process is finished */ + done = TRUE; + break; + } + + /* save this residual in the first row of N */ + v.ve = N->me[0]; + v_copy(rr,&v); + + for (i = 0; i < ip->k && ip->steps < ip->limit; i++) { + ip->steps++; + v.ve = N->me[i]; /* pointer to a row of N (=s_i) */ + /* note that we must use here &v, not v */ + (*ip->Ax)(ip->A_par,&v,As); + rr = As; /* As = A*s_i */ + if (ip->Bx) { + (*ip->Bx)(ip->B_par,As,z); /* z = B*A*s_i */ + rr = z; + } + + if (i < ip->k - 1) { + s.ve = N->me[i+1]; /* pointer to a row of N (=s_{i+1}) */ + v_copy(rr,&s); /* s_{i+1} = B*A*s_i */ + for (j = 0; j <= i-1; j++) { + v.ve = N->me[j+1]; /* pointer to a row of N (=s_{j+1}) */ + /* beta->ve[j] = in_prod(&v,rr); */ /* beta_{j,i} */ + /* modified Gram-Schmidt algorithm */ + beta->ve[j] = in_prod(&v,&s); /* beta_{j,i} */ + /* s_{i+1} -= beta_{j,i}*s_{j+1} */ + v_mltadd(&s,&v,- beta->ve[j],&s); + } + + /* beta_{i,i} = ||s_{i+1}||_2 */ + beta->ve[i] = nres = v_norm2(&s); + if ( nres <= MACHEPS*ip->init_res) { + /* s_{i+1} == 0 */ + i--; + done = TRUE; + break; + } + sv_mlt(1.0/nres,&s,&s); /* normalize s_{i+1} */ + + v.ve = N->me[0]; + alpha->ve[i] = in_prod(&v,&s); /* alpha_i = (s_0 , s_{i+1}) */ + + } + else { + for (j = 0; j <= i-1; j++) { + v.ve = N->me[j+1]; /* pointer to a row of N (=s_{j+1}) */ + beta->ve[j] = in_prod(&v,rr); /* beta_{j,i} */ + } + + nres = in_prod(rr,rr); /* rr = B*A*s_{k-1} */ + for (j = 0; j <= i-1; j++) + nres -= beta->ve[j]*beta->ve[j]; + + if (sqrt(fabs(nres)) <= MACHEPS*ip->init_res) { + /* s_k is zero */ + i--; + done = TRUE; + break; + } + if (nres < 0.0) { /* do restart */ + i--; + ip->steps--; + break; + } + beta->ve[i] = sqrt(nres); /* beta_{k-1,k-1} */ + + v.ve = N->me[0]; + alpha->ve[i] = in_prod(&v,rr); + for (j = 0; j <= i-1; j++) + alpha->ve[i] -= beta->ve[j]*alpha->ve[j]; + alpha->ve[i] /= beta->ve[i]; /* alpha_{k-1} */ + + } + + set_col(H,i,beta); + + /* other method of computing dd */ + /* if (fabs((double)alpha->ve[i]) > dd) { + nres = - dd*dd + alpha->ve[i]*alpha->ve[i]; + nres = sqrt((double) nres); + if (ip->info) (*ip->info)(ip,-nres,VNULL,VNULL); + break; + } */ + /* to avoid overflow/underflow in computing dd */ + /* dd *= cos(asin((double)(alpha->ve[i]/dd))); */ + + nres = alpha->ve[i]/dd; + if (fabs(nres-1.0) <= MACHEPS*ip->init_res) + dd = 0.0; + else { + nres = 1.0 - nres*nres; + if (nres < 0.0) { + nres = sqrt((double) -nres); + if (ip->info) (*ip->info)(ip,-dd*nres,VNULL,VNULL); + break; + } + dd *= sqrt((double) nres); + } + + if (ip->info) (*ip->info)(ip,dd,VNULL,VNULL); + if ( ip->stop_crit(ip,dd,VNULL,VNULL) ) { + /* stopping criterion is satisfied */ + done = TRUE; + break; + } + + } /* end of for */ + + if (i >= ip->k) i = ip->k - 1; + + /* use (i+1) by (i+1) submatrix of H */ + H = m_resize(H,i+1,i+1); + alpha = v_resize(alpha,i+1); + Usolve(H,alpha,alpha,0.0); /* c_i is saved in alpha */ + + for (j = 0; j <= i; j++) { + v.ve = N->me[j]; + v_mltadd(ip->x,&v,alpha->ve[j],ip->x); + } + + + if (done) break; /* stop the iterative process */ + alpha = v_resize(alpha,ip->k); + H = m_resize(H,ip->k,ip->k); + + } /* end of while */ + +#ifdef THREADSAFE + V_FREE(As); V_FREE(beta); V_FREE(alpha); V_FREE(z); + M_FREE(N); M_FREE(H); +#endif + + return ip->x; /* return the solution */ +} + + + +/* iter_spmgcr - a simple interface to iter_mgcr */ +/* no preconditioner */ +#ifndef ANSI_C +VEC *iter_spmgcr(A,B,b,tol,x,k,limit,steps) +SPMAT *A, *B; +VEC *b, *x; +double tol; +int *steps,k,limit; +#else +VEC *iter_spmgcr(SPMAT *A, SPMAT *B, VEC *b, double tol, + VEC *x, int k, int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + if (B) { + ip->Bx = (Fun_Ax) sp_mv_mlt; + ip->B_par = (void *) B; + } + else { + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + } + + ip->k = k; + ip->limit = limit; + ip->info = (Fun_info) NULL; + ip->b = b; + ip->eps = tol; + ip->x = x; + iter_mgcr(ip); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; +} + + + +/* + Conjugate gradients method for a normal equation + a preconditioner B must be symmetric !! +*/ +#ifndef ANSI_C +VEC *iter_cgne(ip) +ITER *ip; +#else +VEC *iter_cgne(ITER *ip) +#endif +{ + STATIC VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL; + Real alpha, beta, inner, old_inner, nres; + VEC *rr1; /* pointer only */ + + if (ip == INULL) + error(E_NULL,"iter_cgne"); + if (!ip->Ax || ! ip->ATx || !ip->b) + error(E_NULL,"iter_cgne"); + if ( ip->x == ip->b ) + error(E_INSITU,"iter_cgne"); + if (!ip->stop_crit) + error(E_NULL,"iter_cgne"); + + if ( ip->eps <= 0.0 ) ip->eps = MACHEPS; + + r = v_resize(r,ip->b->dim); + p = v_resize(p,ip->b->dim); + q = v_resize(q,ip->b->dim); + + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(p,TYPE_VEC); + MEM_STAT_REG(q,TYPE_VEC); + + z = v_resize(z,ip->b->dim); + MEM_STAT_REG(z,TYPE_VEC); + + if (ip->x) { + if (ip->x->dim != ip->b->dim) + error(E_SIZES,"iter_cgne"); + ip->Ax(ip->A_par,ip->x,p); /* p = A*x */ + v_sub(ip->b,p,z); /* z = b - A*x */ + } + else { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + v_copy(ip->b,z); + } + rr1 = z; + if (ip->Bx) { + (ip->Bx)(ip->B_par,rr1,p); + rr1 = p; + } + (ip->ATx)(ip->AT_par,rr1,r); /* r = A^T*B*(b-A*x) */ + + + old_inner = 0.0; + for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ ) + { + rr1 = r; + if ( ip->Bx ) { + (ip->Bx)(ip->B_par,r,z); /* rr = B*r */ + rr1 = z; + } + + inner = in_prod(r,rr1); + nres = sqrt(fabs(inner)); + if (ip->info) ip->info(ip,nres,r,rr1); + if (ip->steps == 0) ip->init_res = nres; + if ( ip->stop_crit(ip,nres,r,rr1) ) break; + + if ( ip->steps ) /* if ( ip->steps > 0 ) ... */ + { + beta = inner/old_inner; + p = v_mltadd(rr1,p,beta,p); + } + else /* if ( ip->steps == 0 ) ... */ + { + beta = 0.0; + p = v_copy(rr1,p); + old_inner = 0.0; + } + (ip->Ax)(ip->A_par,p,q); /* q = A*p */ + if (ip->Bx) { + (ip->Bx)(ip->B_par,q,z); + (ip->ATx)(ip->AT_par,z,q); + rr1 = q; /* q = A^T*B*A*p */ + } + else { + (ip->ATx)(ip->AT_par,q,z); /* z = A^T*A*p */ + rr1 = z; + } + + alpha = inner/in_prod(rr1,p); + v_mltadd(ip->x,p,alpha,ip->x); + v_mltadd(r,rr1,-alpha,r); + old_inner = inner; + } + +#ifdef THREADSAFE + V_FREE(r); V_FREE(p); V_FREE(q); V_FREE(z); +#endif + + return ip->x; +} + +/* iter_spcgne -- a simple interface to iter_cgne() which + uses sparse matrix data structures + -- assumes that B contains an actual preconditioner (or NULL) + use always as follows: + x = iter_spcgne(A,B,b,eps,x,limit,steps); + or + x = iter_spcgne(A,B,b,eps,VNULL,limit,steps); + In the second case the solution vector is created. +*/ +#ifndef ANSI_C +VEC *iter_spcgne(A,B,b,eps,x,limit,steps) +SPMAT *A, *B; +VEC *b, *x; +double eps; +int *steps, limit; +#else +VEC *iter_spcgne(SPMAT *A,SPMAT *B, VEC *b, double eps, + VEC *x, int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *)A; + ip->ATx = (Fun_Ax) sp_vm_mlt; + ip->AT_par = (void *)A; + if (B) { + ip->Bx = (Fun_Ax) sp_mv_mlt; + ip->B_par = (void *)B; + } + else { + ip->Bx = (Fun_Ax) NULL; + ip->B_par = NULL; + } + ip->info = (Fun_info) NULL; + ip->b = b; + ip->eps = eps; + ip->limit = limit; + ip->x = x; + iter_cgne(ip); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; +} + + + diff --git a/itersym.c b/itersym.c new file mode 100644 index 0000000..0cfcb65 --- /dev/null +++ b/itersym.c @@ -0,0 +1,648 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* itersym.c 17/09/93 */ + + +/* + ITERATIVE METHODS - implementation of several iterative methods; + see also iter0.c + */ + +#include +#include +#include "matrix.h" +#include "matrix2.h" +#include "sparse.h" +#include "iter.h" + +static char rcsid[] = "$Id: itersym.c,v 1.2 1995/01/30 14:55:54 des Exp $"; + + +#ifdef ANSI_C +VEC *spCHsolve(const SPMAT *,VEC *,VEC *); +VEC *trieig(VEC *,VEC *,MAT *); +#else +VEC *spCHsolve(); +VEC *trieig(); +#endif + + + +/* iter_spcg -- a simple interface to iter_cg() which uses sparse matrix + data structures + -- assumes that LLT contains the Cholesky factorisation of the + actual preconditioner; + use always as follows: + x = iter_spcg(A,LLT,b,eps,x,limit,steps); + or + x = iter_spcg(A,LLT,b,eps,VNULL,limit,steps); + In the second case the solution vector is created. + */ +#ifndef ANSI_C +VEC *iter_spcg(A,LLT,b,eps,x,limit,steps) +SPMAT *A, *LLT; +VEC *b, *x; +double eps; +int *steps, limit; +#else +VEC *iter_spcg(SPMAT *A, SPMAT *LLT, VEC *b, double eps, VEC *x, + int limit, int *steps) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *)A; + ip->Bx = (Fun_Ax) spCHsolve; + ip->B_par = (void *)LLT; + ip->info = (Fun_info) NULL; + ip->b = b; + ip->eps = eps; + ip->limit = limit; + ip->x = x; + iter_cg(ip); + x = ip->x; + if (steps) *steps = ip->steps; + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return x; +} + +/* + Conjugate gradients method; + */ +#ifndef ANSI_C +VEC *iter_cg(ip) +ITER *ip; +#else +VEC *iter_cg(ITER *ip) +#endif +{ + STATIC VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL; + Real alpha, beta, inner, old_inner, nres; + VEC *rr; /* rr == r or rr == z */ + + if (ip == INULL) + error(E_NULL,"iter_cg"); + if (!ip->Ax || !ip->b) + error(E_NULL,"iter_cg"); + if ( ip->x == ip->b ) + error(E_INSITU,"iter_cg"); + if (!ip->stop_crit) + error(E_NULL,"iter_cg"); + + if ( ip->eps <= 0.0 ) + ip->eps = MACHEPS; + + r = v_resize(r,ip->b->dim); + p = v_resize(p,ip->b->dim); + q = v_resize(q,ip->b->dim); + + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(p,TYPE_VEC); + MEM_STAT_REG(q,TYPE_VEC); + + if (ip->Bx != (Fun_Ax)NULL) { + z = v_resize(z,ip->b->dim); + MEM_STAT_REG(z,TYPE_VEC); + rr = z; + } + else rr = r; + + if (ip->x != VNULL) { + if (ip->x->dim != ip->b->dim) + error(E_SIZES,"iter_cg"); + ip->Ax(ip->A_par,ip->x,p); /* p = A*x */ + v_sub(ip->b,p,r); /* r = b - A*x */ + } + else { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + v_copy(ip->b,r); + } + + old_inner = 0.0; + for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ ) + { + if ( ip->Bx ) + (ip->Bx)(ip->B_par,r,rr); /* rr = B*r */ + + inner = in_prod(rr,r); + nres = sqrt(fabs(inner)); + if (ip->info) ip->info(ip,nres,r,rr); + if (ip->steps == 0) ip->init_res = nres; + if ( ip->stop_crit(ip,nres,r,rr) ) break; + + if ( ip->steps ) /* if ( ip->steps > 0 ) ... */ + { + beta = inner/old_inner; + p = v_mltadd(rr,p,beta,p); + } + else /* if ( ip->steps == 0 ) ... */ + { + beta = 0.0; + p = v_copy(rr,p); + old_inner = 0.0; + } + (ip->Ax)(ip->A_par,p,q); /* q = A*p */ + alpha = in_prod(p,q); + if (sqrt(fabs(alpha)) <= MACHEPS*ip->init_res) + error(E_BREAKDOWN,"iter_cg"); + alpha = inner/alpha; + v_mltadd(ip->x,p,alpha,ip->x); + v_mltadd(r,q,-alpha,r); + old_inner = inner; + } + +#ifdef THREADSAFE + V_FREE(r); V_FREE(p); V_FREE(q); V_FREE(z); +#endif + + return ip->x; +} + + + +/* iter_lanczos -- raw lanczos algorithm -- no re-orthogonalisation + -- creates T matrix of size == m, + but no larger than before beta_k == 0 + -- uses passed routine to do matrix-vector multiplies */ +#ifndef ANSI_C +void iter_lanczos(ip,a,b,beta2,Q) +ITER *ip; +VEC *a, *b; +Real *beta2; +MAT *Q; +#else +void iter_lanczos(ITER *ip, VEC *a, VEC *b, Real *beta2, MAT *Q) +#endif +{ + int j; + STATIC VEC *v = VNULL, *w = VNULL, *tmp = VNULL; + Real alpha, beta, c; + + if ( ! ip ) + error(E_NULL,"iter_lanczos"); + if ( ! ip->Ax || ! ip->x || ! a || ! b ) + error(E_NULL,"iter_lanczos"); + if ( ip->k <= 0 ) + error(E_BOUNDS,"iter_lanczos"); + if ( Q && ( Q->n < ip->x->dim || Q->m < ip->k ) ) + error(E_SIZES,"iter_lanczos"); + + a = v_resize(a,(unsigned int)ip->k); + b = v_resize(b,(unsigned int)(ip->k-1)); + v = v_resize(v,ip->x->dim); + w = v_resize(w,ip->x->dim); + tmp = v_resize(tmp,ip->x->dim); + MEM_STAT_REG(v,TYPE_VEC); + MEM_STAT_REG(w,TYPE_VEC); + MEM_STAT_REG(tmp,TYPE_VEC); + + beta = 1.0; + v_zero(a); + v_zero(b); + if (Q) m_zero(Q); + + /* normalise x as w */ + c = v_norm2(ip->x); + if (c <= MACHEPS) { /* ip->x == 0 */ + *beta2 = 0.0; + return; + } + else + sv_mlt(1.0/c,ip->x,w); + + (ip->Ax)(ip->A_par,w,v); + + for ( j = 0; j < ip->k; j++ ) + { + /* store w in Q if Q not NULL */ + if ( Q ) set_row(Q,j,w); + + alpha = in_prod(w,v); + a->ve[j] = alpha; + v_mltadd(v,w,-alpha,v); + beta = v_norm2(v); + if ( beta == 0.0 ) + { + *beta2 = 0.0; + return; + } + + if ( j < ip->k-1 ) + b->ve[j] = beta; + v_copy(w,tmp); + sv_mlt(1/beta,v,w); + sv_mlt(-beta,tmp,v); + (ip->Ax)(ip->A_par,w,tmp); + v_add(v,tmp,v); + } + *beta2 = beta; + +#ifdef THREADSAFE + V_FREE(v); V_FREE(w); V_FREE(tmp); +#endif +} + +/* iter_splanczos -- version that uses sparse matrix data structure */ +#ifndef ANSI_C +void iter_splanczos(A,m,x0,a,b,beta2,Q) +SPMAT *A; +int m; +VEC *x0, *a, *b; +Real *beta2; +MAT *Q; +#else +void iter_splanczos(SPMAT *A, int m, VEC *x0, + VEC *a, VEC *b, Real *beta2, MAT *Q) +#endif +{ + ITER *ip; + + ip = iter_get(0,0); + ip->shared_x = ip->shared_b = TRUE; + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + ip->x = x0; + ip->k = m; + iter_lanczos(ip,a,b,beta2,Q); + iter_free(ip); /* release only ITER structure */ +} + + +#ifndef ANSI_C +extern double frexp(), ldexp(); +#else +extern double frexp(double num, int *exponent), + ldexp(double num, int exponent); +#endif + +/* product -- returns the product of a long list of numbers + -- answer stored in mant (mantissa) and expt (exponent) */ +#ifndef ANSI_C +static double product(a,offset,expt) +VEC *a; +double offset; +int *expt; +#else +static double product(VEC *a, double offset, int *expt) +#endif +{ + Real mant, tmp_fctr; + int i, tmp_expt; + + if ( ! a ) + error(E_NULL,"product"); + + mant = 1.0; + *expt = 0; + if ( offset == 0.0 ) + for ( i = 0; i < a->dim; i++ ) + { + mant *= frexp(a->ve[i],&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + else + for ( i = 0; i < a->dim; i++ ) + { + tmp_fctr = a->ve[i] - offset; + tmp_fctr += (tmp_fctr > 0.0 ) ? -MACHEPS*offset : + MACHEPS*offset; + mant *= frexp(tmp_fctr,&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + + return mant; +} + +/* product2 -- returns the product of a long list of numbers (except the k'th) + -- answer stored in mant (mantissa) and expt (exponent) */ +#ifndef ANSI_C +static double product2(a,k,expt) +VEC *a; +int k; /* entry of a to leave out */ +int *expt; +#else +static double product2(VEC *a, int k, int *expt) +#endif +{ + Real mant, mu, tmp_fctr; + int i, tmp_expt; + + if ( ! a ) + error(E_NULL,"product2"); + if ( k < 0 || k >= a->dim ) + error(E_BOUNDS,"product2"); + + mant = 1.0; + *expt = 0; + mu = a->ve[k]; + for ( i = 0; i < a->dim; i++ ) + { + if ( i == k ) + continue; + tmp_fctr = a->ve[i] - mu; + tmp_fctr += ( tmp_fctr > 0.0 ) ? -MACHEPS*mu : MACHEPS*mu; + mant *= frexp(tmp_fctr,&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + + return mant; +} + +/* dbl_cmp -- comparison function to pass to qsort() */ +#ifndef ANSI_C +static int dbl_cmp(x,y) +Real *x, *y; +#else +static int dbl_cmp(Real *x, Real *y) +#endif +{ + Real tmp; + + tmp = *x - *y; + return (tmp > 0 ? 1 : tmp < 0 ? -1: 0); +} + +/* iter_lanczos2 -- lanczos + error estimate for every e-val + -- uses Cullum & Willoughby approach, Sparse Matrix Proc. 1978 + -- returns multiple e-vals where multiple e-vals may not exist + -- returns evals vector */ +#ifndef ANSI_C +VEC *iter_lanczos2(ip,evals,err_est) +ITER *ip; /* ITER structure */ +VEC *evals; /* eigenvalue vector */ +VEC *err_est; /* error estimates of eigenvalues */ +#else +VEC *iter_lanczos2(ITER *ip, VEC *evals, VEC *err_est) +#endif +{ + VEC *a; + STATIC VEC *b=VNULL, *a2=VNULL, *b2=VNULL; + Real beta, pb_mant, det_mant, det_mant1, det_mant2; + int i, pb_expt, det_expt, det_expt1, det_expt2; + + if ( ! ip ) + error(E_NULL,"iter_lanczos2"); + if ( ! ip->Ax || ! ip->x ) + error(E_NULL,"iter_lanczos2"); + if ( ip->k <= 0 ) + error(E_RANGE,"iter_lanczos2"); + + a = evals; + a = v_resize(a,(unsigned int)ip->k); + b = v_resize(b,(unsigned int)(ip->k-1)); + MEM_STAT_REG(b,TYPE_VEC); + + iter_lanczos(ip,a,b,&beta,MNULL); + + /* printf("# beta =%g\n",beta); */ + pb_mant = 0.0; + if ( err_est ) + { + pb_mant = product(b,(double)0.0,&pb_expt); + /* printf("# pb_mant = %g, pb_expt = %d\n",pb_mant, pb_expt); */ + } + + /* printf("# diags =\n"); v_output(a); */ + /* printf("# off diags =\n"); v_output(b); */ + a2 = v_resize(a2,a->dim - 1); + b2 = v_resize(b2,b->dim - 1); + MEM_STAT_REG(a2,TYPE_VEC); + MEM_STAT_REG(b2,TYPE_VEC); + for ( i = 0; i < a2->dim - 1; i++ ) + { + a2->ve[i] = a->ve[i+1]; + b2->ve[i] = b->ve[i+1]; + } + a2->ve[a2->dim-1] = a->ve[a2->dim]; + + trieig(a,b,MNULL); + + /* sort evals as a courtesy */ + qsort((void *)(a->ve),(int)(a->dim),sizeof(Real),(int (*)())dbl_cmp); + + /* error estimates */ + if ( err_est ) + { + err_est = v_resize(err_est,(unsigned int)ip->k); + + trieig(a2,b2,MNULL); + /* printf("# a =\n"); v_output(a); */ + /* printf("# a2 =\n"); v_output(a2); */ + + for ( i = 0; i < a->dim; i++ ) + { + det_mant1 = product2(a,i,&det_expt1); + det_mant2 = product(a2,(double)a->ve[i],&det_expt2); + /* printf("# det_mant1=%g, det_expt1=%d\n", + det_mant1,det_expt1); */ + /* printf("# det_mant2=%g, det_expt2=%d\n", + det_mant2,det_expt2); */ + if ( det_mant1 == 0.0 ) + { /* multiple e-val of T */ + err_est->ve[i] = 0.0; + continue; + } + else if ( det_mant2 == 0.0 ) + { + err_est->ve[i] = HUGE_VAL; + continue; + } + if ( (det_expt1 + det_expt2) % 2 ) + /* if odd... */ + det_mant = sqrt(2.0*fabs(det_mant1*det_mant2)); + else /* if even... */ + det_mant = sqrt(fabs(det_mant1*det_mant2)); + det_expt = (det_expt1+det_expt2)/2; + err_est->ve[i] = fabs(beta* + ldexp(pb_mant/det_mant,pb_expt-det_expt)); + } + } + +#ifdef THREADSAFE + V_FREE(b); V_FREE(a2); V_FREE(b2); +#endif + + return a; +} + +/* iter_splanczos2 -- version of iter_lanczos2() that uses sparse matrix data + structure */ +#ifndef ANSI_C +VEC *iter_splanczos2(A,m,x0,evals,err_est) +SPMAT *A; +int m; +VEC *x0; /* initial vector */ +VEC *evals; /* eigenvalue vector */ +VEC *err_est; /* error estimates of eigenvalues */ +#else +VEC *iter_splanczos2(SPMAT *A, int m, VEC *x0, VEC *evals, VEC *err_est) +#endif +{ + ITER *ip; + VEC *a; + + ip = iter_get(0,0); + ip->Ax = (Fun_Ax) sp_mv_mlt; + ip->A_par = (void *) A; + ip->x = x0; + ip->k = m; + a = iter_lanczos2(ip,evals,err_est); + ip->shared_x = ip->shared_b = TRUE; + iter_free(ip); /* release only ITER structure */ + return a; +} + + + + +/* + Conjugate gradient method + Another variant - mainly for testing + */ +#ifndef ANSI_C +VEC *iter_cg1(ip) +ITER *ip; +#else +VEC *iter_cg1(ITER *ip) +#endif +{ + STATIC VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL; + Real alpha; + double inner,nres; + VEC *rr; /* rr == r or rr == z */ + + if (ip == INULL) + error(E_NULL,"iter_cg"); + if (!ip->Ax || !ip->b) + error(E_NULL,"iter_cg"); + if ( ip->x == ip->b ) + error(E_INSITU,"iter_cg"); + if (!ip->stop_crit) + error(E_NULL,"iter_cg"); + + if ( ip->eps <= 0.0 ) + ip->eps = MACHEPS; + + r = v_resize(r,ip->b->dim); + p = v_resize(p,ip->b->dim); + q = v_resize(q,ip->b->dim); + + MEM_STAT_REG(r,TYPE_VEC); + MEM_STAT_REG(p,TYPE_VEC); + MEM_STAT_REG(q,TYPE_VEC); + + if (ip->Bx != (Fun_Ax)NULL) { + z = v_resize(z,ip->b->dim); + MEM_STAT_REG(z,TYPE_VEC); + rr = z; + } + else rr = r; + + if (ip->x != VNULL) { + if (ip->x->dim != ip->b->dim) + error(E_SIZES,"iter_cg"); + ip->Ax(ip->A_par,ip->x,p); /* p = A*x */ + v_sub(ip->b,p,r); /* r = b - A*x */ + } + else { /* ip->x == 0 */ + ip->x = v_get(ip->b->dim); + ip->shared_x = FALSE; + v_copy(ip->b,r); + } + + if (ip->Bx) (ip->Bx)(ip->B_par,r,p); + else v_copy(r,p); + + inner = in_prod(p,r); + nres = sqrt(fabs(inner)); + if (ip->info) ip->info(ip,nres,r,p); + if ( nres == 0.0) return ip->x; + + for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ ) + { + ip->Ax(ip->A_par,p,q); + inner = in_prod(q,p); + if (sqrt(fabs(inner)) <= MACHEPS*ip->init_res) + error(E_BREAKDOWN,"iter_cg1"); + + alpha = in_prod(p,r)/inner; + v_mltadd(ip->x,p,alpha,ip->x); + v_mltadd(r,q,-alpha,r); + + rr = r; + if (ip->Bx) { + ip->Bx(ip->B_par,r,z); + rr = z; + } + + nres = in_prod(r,rr); + if (nres < 0.0) { + warning(WARN_RES_LESS_0,"iter_cg"); + break; + } + nres = sqrt(fabs(nres)); + if (ip->info) ip->info(ip,nres,r,z); + if (ip->steps == 0) ip->init_res = nres; + if ( ip->stop_crit(ip,nres,r,z) ) break; + + alpha = -in_prod(rr,q)/inner; + v_mltadd(rr,p,alpha,p); + + } + +#ifdef THREADSAFE + V_FREE(r); V_FREE(p); V_FREE(q); V_FREE(z); +#endif + + return ip->x; +} + + diff --git a/itertort.c b/itertort.c new file mode 100644 index 0000000..72a35ac --- /dev/null +++ b/itertort.c @@ -0,0 +1,691 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* iter_tort.c 16/09/93 */ + +/* + This file contains tests for the iterative part of Meschach +*/ + +#include +#include "matrix2.h" +#include "sparse2.h" +#include "iter.h" +#include + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + + /* for iterative methods */ + +#if REAL == DOUBLE +#define EPS 1e-7 +#define KK 20 +#elif REAL == FLOAT +#define EPS 1e-5 +#define KK 8 +#endif + +#define ANON 513 +#define ASYM ANON + + +static VEC *ex_sol = VNULL; + +/* new iter information */ +void iter_mod_info(ip,nres,res,Bres) +ITER *ip; +double nres; +VEC *res, *Bres; +{ + static VEC *tmp; + + if (ip->b == VNULL) return; + tmp = v_resize(tmp,ip->b->dim); + MEM_STAT_REG(tmp,TYPE_VEC); + + if (nres >= 0.0) { + printf(" %d. residual = %g\n",ip->steps,nres); + } + else + printf(" %d. residual = %g (WARNING !!! should be >= 0) \n", + ip->steps,nres); + if (ex_sol != VNULL) + printf(" ||u_ex - u_approx||_2 = %g\n", + v_norm2(v_sub(ip->x,ex_sol,tmp))); +} + + +/* out = A^T*A*x */ +VEC *norm_equ(A,x,out) +SPMAT *A; +VEC *x, *out; +{ + static VEC * tmp; + + tmp = v_resize(tmp,x->dim); + MEM_STAT_REG(tmp,TYPE_VEC); + sp_mv_mlt(A,x,tmp); + sp_vm_mlt(A,tmp,out); + return out; + +} + + +/* + make symmetric preconditioner for nonsymmetric matrix A; + B = 0.5*(A+A^T) and then B is factorized using + incomplete Choleski factorization +*/ + +SPMAT *gen_sym_precond(A) +SPMAT *A; +{ + SPMAT *B; + SPROW *row; + int i,j,k; + Real val; + + B = sp_get(A->m,A->n,A->row[0].maxlen); + for (i=0; i < A->m; i++) { + row = &(A->row[i]); + for (j = 0; j < row->len; j++) { + k = row->elt[j].col; + if (i != k) { + val = 0.5*(sp_get_val(A,i,k) + sp_get_val(A,k,i)); + sp_set_val(B,i,k,val); + sp_set_val(B,k,i,val); + } + else { /* i == k */ + val = sp_get_val(A,i,i); + sp_set_val(B,i,i,val); + } + } + } + + spICHfactor(B); + return B; +} + +/* Dv_mlt -- diagonal by vector multiply; the diagonal matrix is represented + by a vector d */ +VEC *Dv_mlt(d, x, out) +VEC *d, *x, *out; +{ + int i; + + if ( ! d || ! x ) + error(E_NULL,"Dv_mlt"); + if ( d->dim != x->dim ) + error(E_SIZES,"Dv_mlt"); + out = v_resize(out,x->dim); + + for ( i = 0; i < x->dim; i++ ) + out->ve[i] = d->ve[i]*x->ve[i]; + + return out; +} + + + +/************************************************/ +void main(argc, argv) +int argc; +char *argv[]; +{ + VEC *x, *y, *z, *u, *v, *xn, *yn; + SPMAT *A = NULL, *B = NULL; + SPMAT *An = NULL, *Bn = NULL; + int i, k, kk, j; + ITER *ips, *ips1, *ipns, *ipns1; + MAT *Q, *H, *Q1, *H1; + VEC vt, vt1; + Real hh; + + + mem_info_on(TRUE); + notice("allocating sparse matrices"); + + printf(" dim of A = %dx%d\n",ASYM,ASYM); + + A = iter_gen_sym(ASYM,8); + B = sp_copy(A); + spICHfactor(B); + + u = v_get(A->n); + x = v_get(A->n); + y = v_get(A->n); + v = v_get(A->n); + + v_rand(x); + sp_mv_mlt(A,x,y); + ex_sol = x; + + notice(" initialize ITER variables"); + /* ips for symmetric matrices with precondition */ + ips = iter_get(A->m,A->n); + + /* printf(" ips:\n"); + iter_dump(stdout,ips); */ + + ips->limit = 500; + ips->eps = EPS; + + iter_Ax(ips,sp_mv_mlt,A); + iter_Bx(ips,spCHsolve,B); + + ips->b = v_copy(y,ips->b); + v_rand(ips->x); + /* test of iter_resize */ + ips = iter_resize(ips,2*A->m,2*A->n); + ips = iter_resize(ips,A->m,A->n); + + /* printf(" ips:\n"); + iter_dump(stdout,ips); */ + + /* ips1 for symmetric matrices without precondition */ + ips1 = iter_get(0,0); + /* printf(" ips1:\n"); + iter_dump(stdout,ips1); */ + ITER_FREE(ips1); + + ips1 = iter_copy2(ips,ips1); + iter_Bx(ips1,NULL,NULL); + ips1->b = ips->b; + ips1->shared_b = TRUE; + /* printf(" ips1:\n"); + iter_dump(stdout,ips1); */ + + /* ipns for nonsymetric matrices with precondition */ + ipns = iter_copy(ips,INULL); + ipns->k = KK; + ipns->limit = 500; + ipns->info = NULL; + + An = iter_gen_nonsym_posdef(ANON,8); + Bn = gen_sym_precond(An); + xn = v_get(An->n); + yn = v_get(An->n); + v_rand(xn); + sp_mv_mlt(An,xn,yn); + ipns->b = v_copy(yn,ipns->b); + + iter_Ax(ipns, sp_mv_mlt,An); + iter_ATx(ipns, sp_vm_mlt,An); + iter_Bx(ipns, spCHsolve,Bn); + + /* printf(" ipns:\n"); + iter_dump(stdout,ipns); */ + + /* ipns1 for nonsymmetric matrices without precondition */ + ipns1 = iter_copy2(ipns,INULL); + ipns1->b = ipns->b; + ipns1->shared_b = TRUE; + iter_Bx(ipns1,NULL,NULL); + + /* printf(" ipns1:\n"); + iter_dump(stdout,ipns1); */ + + + /******* CG ********/ + + notice(" CG method without preconditioning"); + ips1->info = NULL; + mem_stat_mark(1); + iter_cg(ips1); + + k = ips1->steps; + z = ips1->x; + printf(" cg: no. of iter.steps = %d\n",k); + v_sub(z,x,u); + printf(" (cg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + notice(" CG method with ICH preconditioning"); + + ips->info = NULL; + v_zero(ips->x); + iter_cg(ips); + + k = ips->steps; + printf(" cg: no. of iter.steps = %d\n",k); + v_sub(ips->x,x,u); + printf(" (cg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + V_FREE(v); + if ((v = iter_spcg(A,B,y,EPS,VNULL,1000,&k)) == VNULL) + errmesg("CG method with precond.: NULL solution"); + + v_sub(ips->x,v,u); + if (v_norm2(u) >= EPS) { + errmesg("CG method with precond.: different solutions"); + printf(" diff. = %g\n",v_norm2(u)); + } + + + mem_stat_free(1); + printf(" spcg: # of iter. steps = %d\n",k); + v_sub(v,x,u); + printf(" (spcg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + + /*** CG FOR NORMAL EQUATION *****/ + + notice("CGNE method with ICH preconditioning (nonsymmetric case)"); + + /* ipns->info = iter_std_info; */ + ipns->info = NULL; + v_zero(ipns->x); + + mem_stat_mark(1); + iter_cgne(ipns); + + k = ipns->steps; + z = ipns->x; + printf(" cgne: no. of iter.steps = %d\n",k); + v_sub(z,xn,u); + printf(" (cgne:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + notice("CGNE method without preconditioning (nonsymmetric case)"); + + v_rand(u); + u = iter_spcgne(An,NULL,yn,EPS,u,1000,&k); + + mem_stat_free(1); + printf(" spcgne: no. of iter.steps = %d\n",k); + v_sub(u,xn,u); + printf(" (spcgne:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + /*** CGS *****/ + + notice("CGS method with ICH preconditioning (nonsymmetric case)"); + + v_zero(ipns->x); /* new init guess == 0 */ + + mem_stat_mark(1); + ipns->info = NULL; + v_rand(u); + iter_cgs(ipns,u); + + k = ipns->steps; + z = ipns->x; + printf(" cgs: no. of iter.steps = %d\n",k); + v_sub(z,xn,u); + printf(" (cgs:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + notice("CGS method without preconditioning (nonsymmetric case)"); + + v_rand(u); + v_rand(v); + v = iter_spcgs(An,NULL,yn,u,EPS,v,1000,&k); + + mem_stat_free(1); + printf(" cgs: no. of iter.steps = %d\n",k); + v_sub(v,xn,u); + printf(" (cgs:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(u),EPS); + + + + /*** LSQR ***/ + + notice("LSQR method (without preconditioning)"); + + v_rand(u); + v_free(ipns1->x); + ipns1->x = u; + ipns1->shared_x = TRUE; + ipns1->info = NULL; + mem_stat_mark(2); + z = iter_lsqr(ipns1); + + v_sub(xn,z,v); + k = ipns1->steps; + printf(" lsqr: # of iter. steps = %d\n",k); + printf(" (lsqr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + v_rand(u); + u = iter_splsqr(An,yn,EPS,u,1000,&k); + mem_stat_free(2); + + v_sub(xn,u,v); + printf(" splsqr: # of iter. steps = %d\n",k); + printf(" (splsqr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + + + /***** GMRES ********/ + + notice("GMRES method with ICH preconditioning (nonsymmetric case)"); + + v_zero(ipns->x); +/* ipns->info = iter_std_info; */ + ipns->info = NULL; + + mem_stat_mark(2); + z = iter_gmres(ipns); + v_sub(xn,z,v); + k = ipns->steps; + printf(" gmres: # of iter. steps = %d\n",k); + printf(" (gmres:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + notice("GMRES method without preconditioning (nonsymmetric case)"); + V_FREE(v); + v = iter_spgmres(An,NULL,yn,EPS,VNULL,10,1004,&k); + mem_stat_free(2); + + v_sub(xn,v,v); + printf(" spgmres: # of iter. steps = %d\n",k); + printf(" (spgmres:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + + + /**** MGCR *****/ + + notice("MGCR method with ICH preconditioning (nonsymmetric case)"); + + v_zero(ipns->x); + mem_stat_mark(2); + z = iter_mgcr(ipns); + v_sub(xn,z,v); + k = ipns->steps; + printf(" mgcr: # of iter. steps = %d\n",k); + printf(" (mgcr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + notice("MGCR method without preconditioning (nonsymmetric case)"); + V_FREE(v); + v = iter_spmgcr(An,NULL,yn,EPS,VNULL,10,1004,&k); + mem_stat_free(2); + + v_sub(xn,v,v); + printf(" spmgcr: # of iter. steps = %d\n",k); + printf(" (spmgcr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n", + v_norm2(v),EPS); + + + /***** ARNOLDI METHOD ********/ + + + notice("arnoldi method"); + + kk = ipns1->k = KK; + Q = m_get(kk,x->dim); + Q1 = m_get(kk,x->dim); + H = m_get(kk,kk); + v_rand(u); + ipns1->x = u; + ipns1->shared_x = TRUE; + mem_stat_mark(3); + iter_arnoldi_iref(ipns1,&hh,Q,H); + mem_stat_free(3); + + /* check the equality: + Q*A*Q^T = H; */ + + vt.dim = vt.max_dim = x->dim; + vt1.dim = vt1.max_dim = x->dim; + for (j=0; j < kk; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + sp_mv_mlt(An,&vt,&vt1); + } + H1 = m_get(kk,kk); + mmtr_mlt(Q,Q1,H1); + m_sub(H,H1,H1); + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (arnoldi_iref) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + /* check Q*Q^T = I */ + + mmtr_mlt(Q,Q,H1); + for (j=0; j < kk; j++) + H1->me[j][j] -= 1.0; + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (arnoldi_iref) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + ipns1->x = u; + ipns1->shared_x = TRUE; + mem_stat_mark(3); + iter_arnoldi(ipns1,&hh,Q,H); + mem_stat_free(3); + + /* check the equality: + Q*A*Q^T = H; */ + + vt.dim = vt.max_dim = x->dim; + vt1.dim = vt1.max_dim = x->dim; + for (j=0; j < kk; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + sp_mv_mlt(An,&vt,&vt1); + } + + mmtr_mlt(Q,Q1,H1); + m_sub(H,H1,H1); + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (arnoldi) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + /* check Q*Q^T = I */ + mmtr_mlt(Q,Q,H1); + for (j=0; j < kk; j++) + H1->me[j][j] -= 1.0; + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (arnoldi) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + v_rand(u); + mem_stat_mark(3); + iter_sparnoldi(An,u,kk,&hh,Q,H); + mem_stat_free(3); + + /* check the equality: + Q*A*Q^T = H; */ + + vt.dim = vt.max_dim = x->dim; + vt1.dim = vt1.max_dim = x->dim; + for (j=0; j < kk; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + sp_mv_mlt(An,&vt,&vt1); + } + + mmtr_mlt(Q,Q1,H1); + m_sub(H,H1,H1); + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (sparnoldi) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + /* check Q*Q^T = I */ + mmtr_mlt(Q,Q,H1); + for (j=0; j < kk; j++) + H1->me[j][j] -= 1.0; + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (sparnoldi) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + + + /****** LANCZOS METHOD ******/ + + notice("lanczos method"); + kk = ipns1->k; + Q = m_resize(Q,kk,x->dim); + Q1 = m_resize(Q1,kk,x->dim); + H = m_resize(H,kk,kk); + ips1->k = kk; + v_rand(u); + v_free(ips1->x); + ips1->x = u; + ips1->shared_x = TRUE; + + mem_stat_mark(3); + iter_lanczos(ips1,x,y,&hh,Q); + mem_stat_free(3); + + /* check the equality: + Q*A*Q^T = H; */ + + vt.dim = vt1.dim = Q->n; + vt.max_dim = vt1.max_dim = Q->max_n; + Q1 = m_resize(Q1,Q->m,Q->n); + for (j=0; j < Q->m; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + sp_mv_mlt(A,&vt,&vt1); + } + H1 = m_resize(H1,Q->m,Q->m); + H = m_resize(H,Q->m,Q->m); + mmtr_mlt(Q,Q1,H1); + + m_zero(H); + for (j=0; j < Q->m-1; j++) { + H->me[j][j] = x->ve[j]; + H->me[j][j+1] = H->me[j+1][j] = y->ve[j]; + } + H->me[Q->m-1][Q->m-1] = x->ve[Q->m-1]; + + m_sub(H,H1,H1); + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (lanczos) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + /* check Q*Q^T = I */ + + mmtr_mlt(Q,Q,H1); + for (j=0; j < Q->m; j++) + H1->me[j][j] -= 1.0; + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (lanczos) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + mem_stat_mark(3); + v_rand(u); + iter_splanczos(A,kk,u,x,y,&hh,Q); + mem_stat_free(3); + + /* check the equality: + Q*A*Q^T = H; */ + + vt.dim = vt1.dim = Q->n; + vt.max_dim = vt1.max_dim = Q->max_n; + Q1 = m_resize(Q1,Q->m,Q->n); + for (j=0; j < Q->m; j++) { + vt.ve = Q->me[j]; + vt1.ve = Q1->me[j]; + sp_mv_mlt(A,&vt,&vt1); + } + H1 = m_resize(H1,Q->m,Q->m); + H = m_resize(H,Q->m,Q->m); + mmtr_mlt(Q,Q1,H1); + for (j=0; j < Q->m-1; j++) { + H->me[j][j] = x->ve[j]; + H->me[j][j+1] = H->me[j+1][j] = y->ve[j]; + } + H->me[Q->m-1][Q->m-1] = x->ve[Q->m-1]; + + m_sub(H,H1,H1); + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (splanczos) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + /* check Q*Q^T = I */ + mmtr_mlt(Q,Q,H1); + for (j=0; j < Q->m; j++) + H1->me[j][j] -= 1.0; + if (m_norm_inf(H1) > MACHEPS*x->dim) + printf(" (splanczos) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n", + m_norm_inf(H1),MACHEPS); + + + + /***** LANCZOS2 ****/ + + notice("lanczos2 method"); + kk = 50; /* # of dir. vectors */ + ips1->k = kk; + v_rand(u); + ips1->x = u; + ips1->shared_x = TRUE; + + for ( i = 0; i < xn->dim; i++ ) + xn->ve[i] = i; + iter_Ax(ips1,Dv_mlt,xn); + mem_stat_mark(3); + iter_lanczos2(ips1,y,v); + mem_stat_free(3); + + printf("# Number of steps of Lanczos algorithm = %d\n", kk); + printf("# Exact eigenvalues are 0, 1, 2, ..., %d\n",ANON-1); + printf("# Extreme eigenvalues should be accurate; \n"); + printf("# interior values usually are not.\n"); + printf("# approx e-vals =\n"); v_output(y); + printf("# Error in estimate of bottom e-vec (Lanczos) = %g\n", + fabs(v->ve[0])); + + mem_stat_mark(3); + v_rand(u); + iter_splanczos2(A,kk,u,y,v); + mem_stat_free(3); + + + /***** FINISHING *******/ + + notice("release ITER variables"); + + M_FREE(Q); + M_FREE(Q1); + M_FREE(H); + M_FREE(H1); + + ITER_FREE(ipns); + ITER_FREE(ips); + ITER_FREE(ipns1); + ITER_FREE(ips1); + SP_FREE(A); + SP_FREE(B); + SP_FREE(An); + SP_FREE(Bn); + + V_FREE(x); + V_FREE(y); + V_FREE(u); + V_FREE(v); + V_FREE(xn); + V_FREE(yn); + + printf("# Done testing (%s)\n",argv[0]); + mem_info(); +} diff --git a/ivecop.c b/ivecop.c new file mode 100644 index 0000000..944a054 --- /dev/null +++ b/ivecop.c @@ -0,0 +1,334 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* ivecop.c */ + +#include +#include "matrix.h" + +static char rcsid[] = "$Id: ivecop.c,v 1.6 1996/08/20 18:19:21 stewart Exp $"; + +static char line[MAXLINE]; + + + +/* iv_get -- get integer vector -- see also memory.c */ +#ifndef ANSI_C +IVEC *iv_get(dim) +int dim; +#else +IVEC *iv_get(int dim) +#endif +{ + IVEC *iv; + /* unsigned int i; */ + + if (dim < 0) + error(E_NEG,"iv_get"); + + if ((iv=NEW(IVEC)) == IVNULL ) + error(E_MEM,"iv_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_IVEC,0,sizeof(IVEC)); + mem_numvar(TYPE_IVEC,1); + } + + iv->dim = iv->max_dim = dim; + if ((iv->ive = NEW_A(dim,int)) == (int *)NULL ) + error(E_MEM,"iv_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_IVEC,0,dim*sizeof(int)); + } + + return (iv); +} + +/* iv_free -- returns iv & asoociated memory back to memory heap */ +#ifndef ANSI_C +int iv_free(iv) +IVEC *iv; +#else +int iv_free(IVEC *iv) +#endif +{ + if ( iv==IVNULL || iv->dim > MAXDIM ) + /* don't trust it */ + return (-1); + + if ( iv->ive == (int *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_IVEC,sizeof(IVEC),0); + mem_numvar(TYPE_IVEC,-1); + } + free((char *)iv); + } + else + { + if (mem_info_is_on()) { + mem_bytes(TYPE_IVEC,sizeof(IVEC)+iv->max_dim*sizeof(int),0); + mem_numvar(TYPE_IVEC,-1); + } + free((char *)iv->ive); + free((char *)iv); + } + + return (0); +} + +/* iv_resize -- returns the IVEC with dimension new_dim + -- iv is set to the zero vector */ +#ifndef ANSI_C +IVEC *iv_resize(iv,new_dim) +IVEC *iv; +int new_dim; +#else +IVEC *iv_resize(IVEC *iv, int new_dim) +#endif +{ + int i; + + if (new_dim < 0) + error(E_NEG,"iv_resize"); + + if ( ! iv ) + return iv_get(new_dim); + + if (new_dim == iv->dim) + return iv; + + if ( new_dim > iv->max_dim ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_IVEC,iv->max_dim*sizeof(int), + new_dim*sizeof(int)); + } + iv->ive = RENEW(iv->ive,new_dim,int); + if ( ! iv->ive ) + error(E_MEM,"iv_resize"); + iv->max_dim = new_dim; + } + if ( iv->dim <= new_dim ) + for ( i = iv->dim; i < new_dim; i++ ) + iv->ive[i] = 0; + iv->dim = new_dim; + + return iv; +} + +/* iv_copy -- copy integer vector in to out + -- out created/resized if necessary */ +#ifndef ANSI_C +IVEC *iv_copy(in,out) +IVEC *in, *out; +#else +IVEC *iv_copy(const IVEC *in, IVEC *out) +#endif +{ + int i; + + if ( ! in ) + error(E_NULL,"iv_copy"); + out = iv_resize(out,in->dim); + for ( i = 0; i < in->dim; i++ ) + out->ive[i] = in->ive[i]; + + return out; +} + +/* iv_move -- move selected pieces of an IVEC + -- moves the length dim0 subvector with initial index i0 + to the corresponding subvector of out with initial index i1 + -- out is resized if necessary */ +#ifndef ANSI_C +IVEC *iv_move(in,i0,dim0,out,i1) +IVEC *in, *out; +int i0, dim0, i1; +#else +IVEC *iv_move(const IVEC *in, int i0, int dim0, IVEC *out, int i1) +#endif +{ + if ( ! in ) + error(E_NULL,"iv_move"); + if ( i0 < 0 || dim0 < 0 || i1 < 0 || + i0+dim0 > in->dim ) + error(E_BOUNDS,"iv_move"); + + if ( (! out) || i1+dim0 > out->dim ) + out = iv_resize(out,i1+dim0); + + MEM_COPY(&(in->ive[i0]),&(out->ive[i1]),dim0*sizeof(int)); + + return out; +} + +/* iv_add -- integer vector addition -- may be in-situ */ +#ifndef ANSI_C +IVEC *iv_add(iv1,iv2,out) +IVEC *iv1,*iv2,*out; +#else +IVEC *iv_add(const IVEC *iv1, const IVEC *iv2, IVEC *out) +#endif +{ + unsigned int i; + int *out_ive, *iv1_ive, *iv2_ive; + + if ( iv1==IVNULL || iv2==IVNULL ) + error(E_NULL,"iv_add"); + if ( iv1->dim != iv2->dim ) + error(E_SIZES,"iv_add"); + if ( out==IVNULL || out->dim != iv1->dim ) + out = iv_resize(out,iv1->dim); + + out_ive = out->ive; + iv1_ive = iv1->ive; + iv2_ive = iv2->ive; + + for ( i = 0; i < iv1->dim; i++ ) + out_ive[i] = iv1_ive[i] + iv2_ive[i]; + + return (out); +} + + + +/* iv_sub -- integer vector addition -- may be in-situ */ +#ifndef ANSI_C +IVEC *iv_sub(iv1,iv2,out) +IVEC *iv1,*iv2,*out; +#else +IVEC *iv_sub(const IVEC *iv1, const IVEC *iv2, IVEC *out) +#endif +{ + unsigned int i; + int *out_ive, *iv1_ive, *iv2_ive; + + if ( iv1==IVNULL || iv2==IVNULL ) + error(E_NULL,"iv_sub"); + if ( iv1->dim != iv2->dim ) + error(E_SIZES,"iv_sub"); + if ( out==IVNULL || out->dim != iv1->dim ) + out = iv_resize(out,iv1->dim); + + out_ive = out->ive; + iv1_ive = iv1->ive; + iv2_ive = iv2->ive; + + for ( i = 0; i < iv1->dim; i++ ) + out_ive[i] = iv1_ive[i] - iv2_ive[i]; + + return (out); +} + +#define MAX_STACK 60 + + +/* iv_sort -- sorts vector x, and generates permutation that gives the order + of the components; x = [1.3, 3.7, 0.5] -> [0.5, 1.3, 3.7] and + the permutation is order = [2, 0, 1]. + -- if order is NULL on entry then it is ignored + -- the sorted vector x is returned */ +#ifndef ANSI_C +IVEC *iv_sort(x, order) +IVEC *x; +PERM *order; +#else +IVEC *iv_sort(IVEC *x, PERM *order) +#endif +{ + int *x_ive, tmp, v; + /* int *order_pe; */ + int dim, i, j, l, r, tmp_i; + int stack[MAX_STACK], sp; + + if ( ! x ) + error(E_NULL,"iv_sort"); + if ( order != PNULL && order->size != x->dim ) + order = px_resize(order, x->dim); + + x_ive = x->ive; + dim = x->dim; + if ( order != PNULL ) + px_ident(order); + + if ( dim <= 1 ) + return x; + + /* using quicksort algorithm in Sedgewick, + "Algorithms in C", Ch. 9, pp. 118--122 (1990) */ + sp = 0; + l = 0; r = dim-1; v = x_ive[0]; + for ( ; ; ) + { + while ( r > l ) + { + /* "i = partition(x_ive,l,r);" */ + v = x_ive[r]; + i = l-1; + j = r; + for ( ; ; ) + { + while ( x_ive[++i] < v ) + ; + --j; + while ( x_ive[j] > v && j != 0 ) + --j; + if ( i >= j ) break; + + tmp = x_ive[i]; + x_ive[i] = x_ive[j]; + x_ive[j] = tmp; + if ( order != PNULL ) + { + tmp_i = order->pe[i]; + order->pe[i] = order->pe[j]; + order->pe[j] = tmp_i; + } + } + tmp = x_ive[i]; + x_ive[i] = x_ive[r]; + x_ive[r] = tmp; + if ( order != PNULL ) + { + tmp_i = order->pe[i]; + order->pe[i] = order->pe[r]; + order->pe[r] = tmp_i; + } + + if ( i-l > r-i ) + { stack[sp++] = l; stack[sp++] = i-1; l = i+1; } + else + { stack[sp++] = i+1; stack[sp++] = r; r = i-1; } + } + + /* recursion elimination */ + if ( sp == 0 ) + break; + r = stack[--sp]; + l = stack[--sp]; + } + + return x; +} diff --git a/lanczos.c b/lanczos.c new file mode 100644 index 0000000..f09b76c --- /dev/null +++ b/lanczos.c @@ -0,0 +1,328 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File containing Lanczos type routines for finding eigenvalues + of large, sparse, symmetic matrices +*/ + +#include +#include +#include "matrix.h" +#include "sparse.h" + +static char rcsid[] = "$Id: lanczos.c,v 1.4 1994/01/13 05:28:24 des Exp $"; + +#ifdef ANSI_C +extern VEC *trieig(VEC *,VEC *,MAT *); +#else +extern VEC *trieig(); +#endif + +/* lanczos -- raw lanczos algorithm -- no re-orthogonalisation + -- creates T matrix of size == m, + but no larger than before beta_k == 0 + -- uses passed routine to do matrix-vector multiplies */ +void lanczos(A_fn,A_params,m,x0,a,b,beta2,Q) +VEC *(*A_fn)(); /* VEC *(*A_fn)(void *A_params,VEC *in, VEC *out) */ +void *A_params; +int m; +VEC *x0, *a, *b; +Real *beta2; +MAT *Q; +{ + int j; + VEC *v, *w, *tmp; + Real alpha, beta; + + if ( ! A_fn || ! x0 || ! a || ! b ) + error(E_NULL,"lanczos"); + if ( m <= 0 ) + error(E_BOUNDS,"lanczos"); + if ( Q && ( Q->m < x0->dim || Q->n < m ) ) + error(E_SIZES,"lanczos"); + + a = v_resize(a,(unsigned int)m); + b = v_resize(b,(unsigned int)(m-1)); + v = v_get(x0->dim); + w = v_get(x0->dim); + tmp = v_get(x0->dim); + + beta = 1.0; + /* normalise x0 as w */ + sv_mlt(1.0/v_norm2(x0),x0,w); + + (*A_fn)(A_params,w,v); + + for ( j = 0; j < m; j++ ) + { + /* store w in Q if Q not NULL */ + if ( Q ) + set_col(Q,j,w); + + alpha = in_prod(w,v); + a->ve[j] = alpha; + v_mltadd(v,w,-alpha,v); + beta = v_norm2(v); + if ( beta == 0.0 ) + { + v_resize(a,(unsigned int)j+1); + v_resize(b,(unsigned int)j); + *beta2 = 0.0; + if ( Q ) + Q = m_resize(Q,Q->m,j+1); + return; + } + if ( j < m-1 ) + b->ve[j] = beta; + v_copy(w,tmp); + sv_mlt(1/beta,v,w); + sv_mlt(-beta,tmp,v); + (*A_fn)(A_params,w,tmp); + v_add(v,tmp,v); + } + *beta2 = beta; + + + V_FREE(v); V_FREE(w); V_FREE(tmp); +} + +extern double frexp(), ldexp(); + +/* product -- returns the product of a long list of numbers + -- answer stored in mant (mantissa) and expt (exponent) */ +static double product(a,offset,expt) +VEC *a; +double offset; +int *expt; +{ + Real mant, tmp_fctr; + int i, tmp_expt; + + if ( ! a ) + error(E_NULL,"product"); + + mant = 1.0; + *expt = 0; + if ( offset == 0.0 ) + for ( i = 0; i < a->dim; i++ ) + { + mant *= frexp(a->ve[i],&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + else + for ( i = 0; i < a->dim; i++ ) + { + tmp_fctr = a->ve[i] - offset; + tmp_fctr += (tmp_fctr > 0.0 ) ? -MACHEPS*offset : + MACHEPS*offset; + mant *= frexp(tmp_fctr,&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + + return mant; +} + +/* product2 -- returns the product of a long list of numbers + -- answer stored in mant (mantissa) and expt (exponent) */ +static double product2(a,k,expt) +VEC *a; +int k; /* entry of a to leave out */ +int *expt; +{ + Real mant, mu, tmp_fctr; + int i, tmp_expt; + + if ( ! a ) + error(E_NULL,"product2"); + if ( k < 0 || k >= a->dim ) + error(E_BOUNDS,"product2"); + + mant = 1.0; + *expt = 0; + mu = a->ve[k]; + for ( i = 0; i < a->dim; i++ ) + { + if ( i == k ) + continue; + tmp_fctr = a->ve[i] - mu; + tmp_fctr += ( tmp_fctr > 0.0 ) ? -MACHEPS*mu : MACHEPS*mu; + mant *= frexp(tmp_fctr,&tmp_expt); + *expt += tmp_expt; + if ( ! (i % 10) ) + { + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + } + } + mant = frexp(mant,&tmp_expt); + *expt += tmp_expt; + + return mant; +} + +/* dbl_cmp -- comparison function to pass to qsort() */ +static int dbl_cmp(x,y) +Real *x, *y; +{ + Real tmp; + + tmp = *x - *y; + return (tmp > 0 ? 1 : tmp < 0 ? -1: 0); +} + +/* lanczos2 -- lanczos + error estimate for every e-val + -- uses Cullum & Willoughby approach, Sparse Matrix Proc. 1978 + -- returns multiple e-vals where multiple e-vals may not exist + -- returns evals vector */ +VEC *lanczos2(A_fn,A_params,m,x0,evals,err_est) +VEC *(*A_fn)(); +void *A_params; +int m; +VEC *x0; /* initial vector */ +VEC *evals; /* eigenvalue vector */ +VEC *err_est; /* error estimates of eigenvalues */ +{ + VEC *a; + STATIC VEC *b=VNULL, *a2=VNULL, *b2=VNULL; + Real beta, pb_mant, det_mant, det_mant1, det_mant2; + int i, pb_expt, det_expt, det_expt1, det_expt2; + + if ( ! A_fn || ! x0 ) + error(E_NULL,"lanczos2"); + if ( m <= 0 ) + error(E_RANGE,"lanczos2"); + + a = evals; + a = v_resize(a,(unsigned int)m); + b = v_resize(b,(unsigned int)(m-1)); + MEM_STAT_REG(b,TYPE_VEC); + + lanczos(A_fn,A_params,m,x0,a,b,&beta,MNULL); + + /* printf("# beta =%g\n",beta); */ + pb_mant = 0.0; + if ( err_est ) + { + pb_mant = product(b,(double)0.0,&pb_expt); + /* printf("# pb_mant = %g, pb_expt = %d\n",pb_mant, pb_expt); */ + } + + /* printf("# diags =\n"); out_vec(a); */ + /* printf("# off diags =\n"); out_vec(b); */ + a2 = v_resize(a2,a->dim - 1); + b2 = v_resize(b2,b->dim - 1); + MEM_STAT_REG(a2,TYPE_VEC); + MEM_STAT_REG(b2,TYPE_VEC); + for ( i = 0; i < a2->dim - 1; i++ ) + { + a2->ve[i] = a->ve[i+1]; + b2->ve[i] = b->ve[i+1]; + } + a2->ve[a2->dim-1] = a->ve[a2->dim]; + + trieig(a,b,MNULL); + + /* sort evals as a courtesy */ + qsort((void *)(a->ve),(int)(a->dim),sizeof(Real),(int (*)())dbl_cmp); + + /* error estimates */ + if ( err_est ) + { + err_est = v_resize(err_est,(unsigned int)m); + + trieig(a2,b2,MNULL); + /* printf("# a =\n"); out_vec(a); */ + /* printf("# a2 =\n"); out_vec(a2); */ + + for ( i = 0; i < a->dim; i++ ) + { + det_mant1 = product2(a,i,&det_expt1); + det_mant2 = product(a2,(double)a->ve[i],&det_expt2); + /* printf("# det_mant1=%g, det_expt1=%d\n", + det_mant1,det_expt1); */ + /* printf("# det_mant2=%g, det_expt2=%d\n", + det_mant2,det_expt2); */ + if ( det_mant1 == 0.0 ) + { /* multiple e-val of T */ + err_est->ve[i] = 0.0; + continue; + } + else if ( det_mant2 == 0.0 ) + { + err_est->ve[i] = HUGE_VAL; + continue; + } + if ( (det_expt1 + det_expt2) % 2 ) + /* if odd... */ + det_mant = sqrt(2.0*fabs(det_mant1*det_mant2)); + else /* if even... */ + det_mant = sqrt(fabs(det_mant1*det_mant2)); + det_expt = (det_expt1+det_expt2)/2; + err_est->ve[i] = fabs(beta* + ldexp(pb_mant/det_mant,pb_expt-det_expt)); + } + } + +#ifdef THREADSAFE + V_FREE(b); V_FREE(a2); V_FREE(b2); +#endif + + return a; +} + +/* sp_lanczos -- version that uses sparse matrix data structure */ +void sp_lanczos(A,m,x0,a,b,beta2,Q) +SPMAT *A; +int m; +VEC *x0, *a, *b; +Real *beta2; +MAT *Q; +{ lanczos(sp_mv_mlt,A,m,x0,a,b,beta2,Q); } + +/* sp_lanczos2 -- version of lanczos2() that uses sparse matrix data + structure */ +VEC *sp_lanczos2(A,m,x0,evals,err_est) +SPMAT *A; +int m; +VEC *x0; /* initial vector */ +VEC *evals; /* eigenvalue vector */ +VEC *err_est; /* error estimates of eigenvalues */ +{ return lanczos2(sp_mv_mlt,A,m,x0,evals,err_est); } + diff --git a/ls.dat b/ls.dat new file mode 100644 index 0000000..8b1c28b --- /dev/null +++ b/ls.dat @@ -0,0 +1,14 @@ +# No. of a problem +2 +# A = +Matrix: 5 by 3 +row 0: 3 -1 2 +row 1: 2 -1 1.2 +row 2: 2.5 1 -1.5 +row 3: 3 1 1 +row 4: -1 1 -2.2 + +# b = +Vector: dim: 5 + 5 3 2 4 6 + diff --git a/lufactor.c b/lufactor.c new file mode 100644 index 0000000..acbbde4 --- /dev/null +++ b/lufactor.c @@ -0,0 +1,314 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. +*/ + +/* LUfactor.c 1.5 11/25/87 */ +static char rcsid[] = "$Id: lufactor.c,v 1.10 1995/05/16 17:26:44 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* LUfactor -- gaussian elimination with scaled partial pivoting + -- Note: returns LU matrix which is A */ +#ifndef ANSI_C +MAT *LUfactor(A,pivot) +MAT *A; +PERM *pivot; +#else +MAT *LUfactor(MAT *A, PERM *pivot) +#endif +{ + unsigned int i, j, m, n; + int i_max, k, k_max; + Real **A_v, *A_piv, *A_row; + Real max1, temp, tiny; + STATIC VEC *scale = VNULL; + + if ( A==(MAT *)NULL || pivot==(PERM *)NULL ) + error(E_NULL,"LUfactor"); + if ( pivot->size != A->m ) + error(E_SIZES,"LUfactor"); + m = A->m; n = A->n; + scale = v_resize(scale,A->m); + MEM_STAT_REG(scale,TYPE_VEC); + A_v = A->me; + + tiny = 10.0/HUGE_VAL; + + /* initialise pivot with identity permutation */ + for ( i=0; ipe[i] = i; + + /* set scale parameters */ + for ( i=0; ive[i] = max1; + } + + /* main loop */ + k_max = min(m,n)-1; + for ( k=0; kve[i]) >= tiny*fabs(A_v[i][k]) ) + { + temp = fabs(A_v[i][k])/scale->ve[i]; + if ( temp > max1 ) + { max1 = temp; i_max = i; } + } + + /* if no pivot then ignore column k... */ + if ( i_max == -1 ) + { + /* set pivot entry A[k][k] exactly to zero, + rather than just "small" */ + A_v[k][k] = 0.0; + continue; + } + + /* do we pivot ? */ + if ( i_max != k ) /* yes we do... */ + { + px_transp(pivot,i_max,k); + for ( j=0; jm != LU->n || LU->n != b->dim ) + error(E_SIZES,"LUsolve"); + + x = v_resize(x,b->dim); + px_vec(pivot,b,x); /* x := P.b */ + Lsolve(LU,x,x,1.0); /* implicit diagonal = 1 */ + Usolve(LU,x,x,0.0); /* explicit diagonal */ + + return (x); +} + +/* LUTsolve -- given an LU factorisation in A, solve A^T.x=b */ +#ifndef ANSI_C +VEC *LUTsolve(LU,pivot,b,x) +MAT *LU; +PERM *pivot; +VEC *b,*x; +#else +VEC *LUTsolve(const MAT *LU, PERM *pivot, const VEC *b, VEC *x) +#endif +{ + if ( ! LU || ! b || ! pivot ) + error(E_NULL,"LUTsolve"); + if ( LU->m != LU->n || LU->n != b->dim ) + error(E_SIZES,"LUTsolve"); + + x = v_copy(b,x); + UTsolve(LU,x,x,0.0); /* explicit diagonal */ + LTsolve(LU,x,x,1.0); /* implicit diagonal = 1 */ + pxinv_vec(pivot,x,x); /* x := P^T.tmp */ + + return (x); +} + +/* m_inverse -- returns inverse of A, provided A is not too rank deficient + -- uses LU factorisation */ +#ifndef ANSI_C +MAT *m_inverse(A,out) +MAT *A, *out; +#else +MAT *m_inverse(const MAT *A, MAT *out) +#endif +{ + int i; + STATIC VEC *tmp = VNULL, *tmp2 = VNULL; + STATIC MAT *A_cp = MNULL; + STATIC PERM *pivot = PNULL; + + if ( ! A ) + error(E_NULL,"m_inverse"); + if ( A->m != A->n ) + error(E_SQUARE,"m_inverse"); + if ( ! out || out->m < A->m || out->n < A->n ) + out = m_resize(out,A->m,A->n); + + A_cp = m_resize(A_cp,A->m,A->n); + A_cp = m_copy(A,A_cp); + tmp = v_resize(tmp,A->m); + tmp2 = v_resize(tmp2,A->m); + pivot = px_resize(pivot,A->m); + MEM_STAT_REG(A_cp,TYPE_MAT); + MEM_STAT_REG(tmp, TYPE_VEC); + MEM_STAT_REG(tmp2,TYPE_VEC); + MEM_STAT_REG(pivot,TYPE_PERM); + tracecatch(LUfactor(A_cp,pivot),"m_inverse"); + for ( i = 0; i < A->n; i++ ) + { + v_zero(tmp); + tmp->ve[i] = 1.0; + tracecatch(LUsolve(A_cp,pivot,tmp,tmp2),"m_inverse"); + set_col(out,i,tmp2); + } + +#ifdef THREADSAFE + V_FREE(tmp); V_FREE(tmp2); + M_FREE(A_cp); PX_FREE(pivot); +#endif + + return out; +} + +/* LUcondest -- returns an estimate of the condition number of LU given the + LU factorisation in compact form */ +#ifndef ANSI_C +double LUcondest(LU,pivot) +MAT *LU; +PERM *pivot; +#else +double LUcondest(const MAT *LU, PERM *pivot) +#endif +{ + STATIC VEC *y = VNULL, *z = VNULL; + Real cond_est, L_norm, U_norm, sum, tiny; + int i, j, n; + + if ( ! LU || ! pivot ) + error(E_NULL,"LUcondest"); + if ( LU->m != LU->n ) + error(E_SQUARE,"LUcondest"); + if ( LU->n != pivot->size ) + error(E_SIZES,"LUcondest"); + + tiny = 10.0/HUGE_VAL; + + n = LU->n; + y = v_resize(y,n); + z = v_resize(z,n); + MEM_STAT_REG(y,TYPE_VEC); + MEM_STAT_REG(z,TYPE_VEC); + + for ( i = 0; i < n; i++ ) + { + sum = 0.0; + for ( j = 0; j < i; j++ ) + sum -= LU->me[j][i]*y->ve[j]; + sum -= (sum < 0.0) ? 1.0 : -1.0; + if ( fabs(LU->me[i][i]) <= tiny*fabs(sum) ) + return HUGE_VAL; + y->ve[i] = sum / LU->me[i][i]; + } + + catch(E_SING, + LTsolve(LU,y,y,1.0); + LUsolve(LU,pivot,y,z); + , + return HUGE_VAL); + + /* now estimate norm of A (even though it is not directly available) */ + /* actually computes ||L||_inf.||U||_inf */ + U_norm = 0.0; + for ( i = 0; i < n; i++ ) + { + sum = 0.0; + for ( j = i; j < n; j++ ) + sum += fabs(LU->me[i][j]); + if ( sum > U_norm ) + U_norm = sum; + } + L_norm = 0.0; + for ( i = 0; i < n; i++ ) + { + sum = 1.0; + for ( j = 0; j < i; j++ ) + sum += fabs(LU->me[i][j]); + if ( sum > L_norm ) + L_norm = sum; + } + + tracecatch(cond_est = U_norm*L_norm*v_norm_inf(z)/v_norm_inf(y), + "LUcondest"); + +#ifdef THREADSAFE + V_FREE(y); V_FREE(z); +#endif + + return cond_est; +} diff --git a/macheps b/macheps new file mode 100755 index 0000000000000000000000000000000000000000..91425f8e963b78adfac17283cb6aa77491fc6235 GIT binary patch literal 8840 zcmeHN-D_M$6rar|c5Rd1T?kT1irdg=tR<;XBvHXl>FO=^BPK0u17Y0VY_c2nBkXRz z1Thkngb>MJ;IqDneN%kdSfPEZz7-S^KT~QkBqAY}uD{>hx!JonCNIADa1YF!`OP`= zo0)TGFE?{?XXnAALqhocLd-V^A%Z9aj|uUf2%{y$lPD&Nlmq>*MTet*jAad!6=p1Zp^3sRo%zuNC`!}(H2#6EW}&GSZHo;`|` zlf}X~)+MLoMI4v?__{22^+P&nT~g+=vNV@V6tZ%%T-?LgrPpUKi`dD>^X7aOQfA`^ z@%6g+h@E`guYHEN1)P&YE?3C2O>ytn)O=xOwJIl{{`u`%rA(A+zp}l2Y0Ved9Z|nO zH(%|&bn(LF*Q4hz*zc6E>$w6`7Im<=PbXIg-g{^05Eg=S2cVBZ+Y$~dlZZgiqmwkW z2TllqSA!5BScE!)GC&Mr99YQ5erH?&>tr1~_PfJrAa@vr@135hQn4qSN%V})Wk-Q2 zZ75vF6VLoT@$E-1z4LDJ!B4|CKKSq?`VdM?epr=LHfA5B3)|qhh+4erQWfXvMWIcF z%KtH1zS`WFe`u~$PUX7Kbz>cw1k8}9Q8-^EZ0+}1jc)@}ohhFSgb% zV#=jk>s6>fS0UFheA5U;w>OO-tKrI)5o)@OPk=2W*z~H>!xeh0(*so~y1~}Q$W7y^ zh~Rj0;rF2VnNM$K%QQ|Yk`@fU-%c98Mc48LT(*qsYnI)7PoU91RP78wucp~~?^n#6=BLrU@6dvNrE~l+ zzKVosN1-@1m%_g{&qA~CZ$%2*{03~smsP9vb>)iyL)6@Cw6cQu-Wn9X*`P1jd?>IA z>uL0Hj@TnC0P-@OD2*I?H28i)BdJ^LZ%F#{8K<@X=V&Y0$DcMb+28X6_*f&3Y5k_w z^mEEF{dZW0)=rz(_9Ea#z>9zv0WShx1iT1%5%415MZk-I7XdEoH*{^Gbur1I05B9e(^(U41nE|r`rr;sF%bDk?IwVG$jcaB#meo<*d zHQ&w_?millVq#hp{LCTw#n-Ivviczm=So{70ws37Z)U2N*CV{XptPco8YwT;XQxb$ zI8s@(tMnWvKFWlhzVCRP7{l$nWJu$zw)0NLKyuH%H(}n5*uFpEJq)pZf5P0F;lp4E z7sxvr+U +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#define HAVE_PROTOTYPES 1 +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +/* #undef REAL_FLT */ +/* #undef REAL_DBL */ + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#define F_MACHEPS 1.19209e-07 +#define D_MACHEPS 2.22045e-16 + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +/* #undef M_MACHEPS */ + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#define M_MAX_INT 2147483647 +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + diff --git a/machine.h.in b/machine.h.in new file mode 100644 index 0000000..f357338 --- /dev/null +++ b/machine.h.in @@ -0,0 +1,227 @@ +/* Any machine specific stuff goes here */ +/* Add details necessary for your own installation here! */ + +/* RCS id: $Id: machine.h.in,v 1.3 1995/03/27 15:36:21 des Exp $ */ + +/* This is for use with "configure" -- if you are not using configure + then use machine.van for the "vanilla" version of machine.h */ + +/* Note special macros: ANSI_C (ANSI C syntax) + SEGMENTED (segmented memory machine e.g. MS-DOS) + MALLOCDECL (declared if malloc() etc have + been declared) */ + +#ifndef _MACHINE_H +#define _MACHINE_H 1 + +#undef const + +#undef MALLOCDECL +#undef NOT_SEGMENTED +#undef HAVE_MEMORY_H +#undef HAVE_COMPLEX_H +#undef HAVE_MALLOC_H +#undef STDC_HEADERS +#undef HAVE_BCOPY +#undef HAVE_BZERO +#undef CHAR0ISDBL0 +#undef WORDS_BIGENDIAN +#undef U_INT_DEF +#undef VARARGS +#undef HAVE_PROTOTYPES +#undef HAVE_PROTOTYPES_IN_STRUCT + +/* for inclusion into C++ files */ +#ifdef __cplusplus +#define ANSI_C 1 +#ifndef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 +#endif +#ifndef HAVE_PROTOTYPES_IN_STRUCT +#define HAVE_PROTOTYPES_IN_STRUCT 1 +#endif +#endif /* __cplusplus */ + +/* example usage: VEC *PROTO(v_get,(int dim)); */ +#ifdef HAVE_PROTOTYPES +#define PROTO(name,args) name args +#else +#define PROTO(name,args) name() +#endif /* HAVE_PROTOTYPES */ +#ifdef HAVE_PROTOTYPES_IN_STRUCT +/* PROTO_() is to be used instead of PROTO() in struct's and typedef's */ +#define PROTO_(name,args) name args +#else +#define PROTO_(name,args) name() +#endif /* HAVE_PROTOTYPES_IN_STRUCT */ + +/* for basic or larger versions */ +#undef COMPLEX +#undef SPARSE + +/* for loop unrolling */ +#undef VUNROLL +#undef MUNROLL + +/* for segmented memory */ +#ifndef NOT_SEGMENTED +#define SEGMENTED +#endif + +/* if the system has malloc.h */ +#ifdef HAVE_MALLOC_H +#define MALLOCDECL 1 +#include +#endif + +/* any compiler should have this header */ +/* if not, change it */ +#include + + +/* Check for ANSI C memmove and memset */ +#ifdef STDC_HEADERS + +/* standard copy & zero functions */ +#define MEM_COPY(from,to,size) memmove((to),(from),(size)) +#define MEM_ZERO(where,size) memset((where),'\0',(size)) + +#ifndef ANSI_C +#define ANSI_C 1 +#endif + +#endif + +/* standard headers */ +#ifdef ANSI_C +#include +#include +#include +#include +#endif + + +/* if have bcopy & bzero and no alternatives yet known, use them */ +#ifdef HAVE_BCOPY +#ifndef MEM_COPY +/* nonstandard copy function */ +#define MEM_COPY(from,to,size) bcopy((char *)(from),(char *)(to),(int)(size)) +#endif +#endif + +#ifdef HAVE_BZERO +#ifndef MEM_ZERO +/* nonstandard zero function */ +#define MEM_ZERO(where,size) bzero((char *)(where),(int)(size)) +#endif +#endif + +/* if the system has complex.h */ +#ifdef HAVE_COMPLEX_H +#include +#endif + +/* If prototypes are available & ANSI_C not yet defined, then define it, + but don't include any header files as the proper ANSI C headers + aren't here */ +#ifdef HAVE_PROTOTYPES +#ifndef ANSI_C +#define ANSI_C 1 +#endif +#endif + +/* floating point precision */ + +/* you can choose single, double or long double (if available) precision */ + +#define FLOAT 1 +#define DOUBLE 2 +#define LONG_DOUBLE 3 + +#undef REAL_FLT +#undef REAL_DBL + +/* if nothing is defined, choose double precision */ +#ifndef REAL_DBL +#ifndef REAL_FLT +#define REAL_DBL 1 +#endif +#endif + +/* single precision */ +#ifdef REAL_FLT +#define Real float +#define LongReal float +#define REAL FLOAT +#define LONGREAL FLOAT +#endif + +/* double precision */ +#ifdef REAL_DBL +#define Real double +#define LongReal double +#define REAL DOUBLE +#define LONGREAL DOUBLE +#endif + + +/* machine epsilon or unit roundoff error */ +/* This is correct on most IEEE Real precision systems */ +#ifdef DBL_EPSILON +#if REAL == DOUBLE +#define MACHEPS DBL_EPSILON +#elif REAL == FLOAT +#define MACHEPS FLT_EPSILON +#elif REAL == LONGDOUBLE +#define MACHEPS LDBL_EPSILON +#endif +#endif + +#undef F_MACHEPS +#undef D_MACHEPS + +#ifndef MACHEPS +#if REAL == DOUBLE +#define MACHEPS D_MACHEPS +#elif REAL == FLOAT +#define MACHEPS F_MACHEPS +#elif REAL == LONGDOUBLE +#define MACHEPS D_MACHEPS +#endif +#endif + +#undef M_MACHEPS + +/******************** +#ifdef DBL_EPSILON +#define MACHEPS DBL_EPSILON +#endif +#ifdef M_MACHEPS +#ifndef MACHEPS +#define MACHEPS M_MACHEPS +#endif +#endif +********************/ + +#undef M_MAX_INT +#ifdef M_MAX_INT +#ifndef MAX_RAND +#define MAX_RAND ((double)(M_MAX_INT)) +#endif +#endif + +/* for non-ANSI systems */ +#ifndef HUGE_VAL +#define HUGE_VAL HUGE +#else +#ifndef HUGE +#define HUGE HUGE_VAL +#endif +#endif + + +#ifdef ANSI_C +extern int isatty(int); +#endif + +#endif diff --git a/makefile b/makefile new file mode 100644 index 0000000..8944cd3 --- /dev/null +++ b/makefile @@ -0,0 +1,202 @@ +# Generated automatically from makefile.in by configure. +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: $ +# + +srcdir = . +VPATH = . + +CC = cc + +DEFS = -DHAVE_CONFIG_H +LIBS = -lm +RANLIB = ranlib + + +# CFLAGS = -O -g +# CFLAGS = -pg -g +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12a +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +all: part1 part2 part3 zpart1 zpart2 +basic: part1 part2 +sparse: part1 part2 part3 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1); $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2); $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3); $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1); $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2); $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST); $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/makefile.in b/makefile.in new file mode 100644 index 0000000..886cd92 --- /dev/null +++ b/makefile.in @@ -0,0 +1,214 @@ +# +# Makefile for Meschach via autoconf +# +# Copyright (C) David Stewart & Zbigniew Leyk 1993 +# +# $Id: makefile.in,v 1.4 1994/03/14 01:24:06 des Exp $ +# + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ + +DEFS = @DEFS@ +LIBS = @LIBS@ +RANLIB = @RANLIB@ + + +CFLAGS = -O + + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $< + +SHELL = /bin/sh +MES_PAK = mesch12b +TAR = tar +SHAR = stree -u +ZIP = zip -r -l +FLIST = FILELIST + +############################### + +LIST1 = copy.o err.o matrixio.o memory.o vecop.o matop.o pxop.o \ + submat.o init.o otherio.o machine.o matlab.o ivecop.o version.o \ + meminfo.o memstat.o +LIST2 = lufactor.o bkpfacto.o chfactor.o qrfactor.o solve.o hsehldr.o \ + givens.o update.o norm.o hessen.o symmeig.o schur.o svd.o fft.o \ + mfunc.o bdfactor.o +LIST3 = sparse.o sprow.o sparseio.o spchfctr.o splufctr.o \ + spbkp.o spswap.o iter0.o itersym.o iternsym.o +ZLIST1 = zmachine.o zcopy.o zmatio.o zmemory.o zvecop.o zmatop.o znorm.o \ + zfunc.o +ZLIST2 = zlufctr.o zsolve.o zmatlab.o zhsehldr.o zqrfctr.o \ + zgivens.o zhessen.o zschur.o + +# they are no longer supported +# if you use them add oldpart to all and sparse +OLDLIST = conjgrad.o lanczos.o arnoldi.o + +ALL_LISTS = $(LIST1) $(LIST2) $(LIST3) $(ZLIST1) $(ZLIST2) $(OLDLIST) + +HBASE = err.h meminfo.h machine.h matrix.h + +HLIST = $(HBASE) iter.h matlab.h matrix2.h oldnames.h sparse.h \ + sparse2.h zmatrix.h zmatrix2.h + +TORTURE = torture.o sptort.o ztorture.o memtort.o itertort.o \ + mfuntort.o iotort.o + +OTHERS = dmacheps.c extras.c fmacheps.c maxint.c makefile.in \ + README configure configure.in machine.h.in copyright \ + tutorial.c tutadv.c rk4.dat ls.dat makefile $(FLIST) + + +# Different configurations +# the dependencies **between** the parts are for dmake +all: @PROGS@ part1 part2 part3 zpart1 zpart2 +part2: part1 +part3: part2 +basic: part1 part2 +sparse: part1 part2 part3 +zpart2: zpart1 +complex: part1 part2 zpart1 zpart2 + + +$(LIST1): $(HBASE) +part1: $(LIST1) + ar ru meschach.a $(LIST1) + $(RANLIB) meschach.a + +$(LIST2): $(HBASE) matrix2.h +part2: $(LIST2) + ar ru meschach.a $(LIST2) + $(RANLIB) meschach.a + +$(LIST3): $(HBASE) sparse.h sparse2.h +part3: $(LIST3) + ar ru meschach.a $(LIST3) + $(RANLIB) meschach.a + +$(ZLIST1): $(HBASDE) zmatrix.h +zpart1: $(ZLIST1) + ar ru meschach.a $(ZLIST1) + $(RANLIB) meschach.a + +$(ZLIST2): $(HBASE) zmatrix.h zmatrix2.h +zpart2: $(ZLIST2) + ar ru meschach.a $(ZLIST2) + $(RANLIB) meschach.a + +$(OLDLIST): $(HBASE) sparse.h sparse2.h +oldpart: $(OLDLIST) + ar ru meschach.a $(OLDLIST) + $(RANLIB) meschach.a + + + +####################################### + +tar: + - /bin/rm -f $(MES_PAK).tar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(TAR) cvf $(MES_PAK).tar \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + +# use this only for PC machines +msdos-zip: + - /bin/rm -f $(MES_PAK).zip + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(ZIP) $(MES_PAK).zip \ + `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC + + +fullshar: + - /bin/rm -f $(MES_PAK).shar; + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + MACHINES DOC > $(MES_PAK).shar + +shar: + - /bin/rm -f meschach1.shar meschach2.shar meschach3.shar \ + meschach4.shar oldmeschach.shar meschach0.shar + chmod 644 `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + $(OTHERS) $(HLIST) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` + chmod 755 configure + $(MAKE) list + $(SHAR) `echo $(LIST1) | sed -e 's/\.o/.c/g'` > meschach1.shar + $(SHAR) `echo $(LIST2) | sed -e 's/\.o/.c/g'` > meschach2.shar + $(SHAR) `echo $(LIST3) | sed -e 's/\.o/.c/g'` > meschach3.shar + $(SHAR) `echo $(ZLIST1) | sed -e 's/\.o/.c/g'` \ + `echo $(ZLIST2) | sed -e 's/\.o/.c/g'` > meschach4.shar + $(SHAR) `echo $(OLDLIST) | sed -e 's/\.o/.c/g'` > oldmeschach.shar + $(SHAR) $(OTHERS) `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) DOC MACHINES > meschach0.shar + +list: + /bin/rm -f $(FLIST) + ls -lR `echo $(ALL_LISTS) | sed -e 's/\.o/.c/g'` \ + `echo $(TORTURE) | sed -e 's/\.o/.c/g'` \ + $(HLIST) $(OTHERS) MACHINES DOC \ + |awk '/^$$/ {print};/^[-d]/ {printf("%s %s %10d %s %s %s %s\n", \ + $$1,$$2,$$5,$$6,$$7,$$8,$$9)}; /^[^-d]/ {print}' \ + > $(FLIST) + + + +clean: + /bin/rm -f *.o core asx5213a.mat iotort.dat + +cleanup: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + +realclean: + /bin/rm -f *.o core asx5213a.mat iotort.dat *.a + /bin/rm -f torture sptort ztorture memtort itertort mfuntort iotort + /bin/rm -f makefile machine.h config.status maxint macheps + +alltorture: torture sptort ztorture memtort itertort mfuntort iotort + +torture:torture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o torture torture.o \ + meschach.a $(LIBS) +sptort:sptort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o sptort sptort.o \ + meschach.a $(LIBS) +memtort: memtort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o memtort memtort.o \ + meschach.a $(LIBS) +ztorture:ztorture.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o ztorture ztorture.o \ + meschach.a $(LIBS) +itertort: itertort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o itertort itertort.o \ + meschach.a $(LIBS) + +iotort: iotort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o iotort iotort.o \ + meschach.a $(LIBS) +mfuntort: mfuntort.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o mfuntort mfuntort.o \ + meschach.a $(LIBS) +tstmove: tstmove.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstmove tstmove.o \ + meschach.a $(LIBS) +tstpxvec: tstpxvec.o meschach.a + $(CC) $(CFLAGS) $(DEFS) -o tstpxvec tstpxvec.o \ + meschach.a $(LIBS) + diff --git a/matlab.c b/matlab.c new file mode 100644 index 0000000..ae74787 --- /dev/null +++ b/matlab.c @@ -0,0 +1,218 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains routines for import/exporting data to/from + MATLAB. The main routines are: + MAT *m_save(FILE *fp,MAT *A,char *name) + VEC *v_save(FILE *fp,VEC *x,char *name) + MAT *m_load(FILE *fp,char **name) +*/ + +#include +#include "matrix.h" +#include "matlab.h" + +static char rcsid[] = "$Id: matlab.c,v 1.8 1995/02/14 20:12:36 des Exp $"; + +/* m_save -- save matrix in ".mat" file for MATLAB + -- returns matrix to be saved */ +#ifndef ANSI_C +MAT *m_save(fp,A,name) +FILE *fp; +MAT *A; +char *name; +#else +MAT *m_save(FILE *fp, MAT *A, const char *name) +#endif +{ + int i, j; + matlab mat; + + if ( ! A ) + error(E_NULL,"m_save"); + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = A->m; + mat.n = A->n; + mat.imag = FALSE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ +#if ORDER == ROW_ORDER + for ( i = 0; i < A->m; i++ ) + fwrite(A->me[i],sizeof(Real),(int)(A->n),fp); +#else /* column major order: ORDER == COL_ORDER */ + for ( j = 0; j < A->n; j++ ) + for ( i = 0; i < A->m; i++ ) + fwrite(&(A->me[i][j]),sizeof(Real),1,fp); +#endif + + return A; +} + + +/* v_save -- save vector in ".mat" file for MATLAB + -- saves it as a row vector + -- returns vector to be saved */ +#ifndef ANSI_C +VEC *v_save(fp,x,name) +FILE *fp; +VEC *x; +char *name; +#else +VEC *v_save(FILE *fp, VEC *x, const char *name) +#endif +{ + matlab mat; + + if ( ! x ) + error(E_NULL,"v_save"); + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = x->dim; + mat.n = 1; + mat.imag = FALSE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ + fwrite(x->ve,sizeof(Real),(int)(x->dim),fp); + + return x; +} + +/* d_save -- save double in ".mat" file for MATLAB + -- saves it as a row vector + -- returns vector to be saved */ +#ifndef ANSI_C +double d_save(fp,x,name) +FILE *fp; +double x; +char *name; +#else +double d_save(FILE *fp, double x, const char *name) +#endif +{ + matlab mat; + Real x1 = x; + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = 1; + mat.n = 1; + mat.imag = FALSE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ + fwrite(&x1,sizeof(Real),1,fp); + + return x; +} + +/* m_load -- loads in a ".mat" file variable as produced by MATLAB + -- matrix returned; imaginary parts ignored */ +#ifndef ANSI_C +MAT *m_load(fp,name) +FILE *fp; +char **name; +#else +MAT *m_load(FILE *fp, char **name) +#endif +{ + MAT *A; + int i; + int m_flag, o_flag, p_flag, t_flag; + float f_temp; + Real d_temp; + matlab mat; + + if ( fread(&mat,sizeof(matlab),1,fp) != 1 ) + error(E_FORMAT,"m_load"); + if ( mat.type >= 10000 ) /* don't load a sparse matrix! */ + error(E_FORMAT,"m_load"); + m_flag = (mat.type/1000) % 10; + o_flag = (mat.type/100) % 10; + p_flag = (mat.type/10) % 10; + t_flag = (mat.type) % 10; + if ( m_flag != MACH_ID ) + error(E_FORMAT,"m_load"); + if ( t_flag != 0 ) + error(E_FORMAT,"m_load"); + if ( p_flag != DOUBLE_PREC && p_flag != SINGLE_PREC ) + error(E_FORMAT,"m_load"); + *name = (char *)malloc((unsigned)(mat.namlen)+1); + if ( fread(*name,sizeof(char),(unsigned)(mat.namlen),fp) == 0 ) + error(E_FORMAT,"m_load"); + A = m_get((unsigned)(mat.m),(unsigned)(mat.n)); + for ( i = 0; i < A->m*A->n; i++ ) + { + if ( p_flag == DOUBLE_PREC ) + fread(&d_temp,sizeof(double),1,fp); + else + { + fread(&f_temp,sizeof(float),1,fp); + d_temp = f_temp; + } + if ( o_flag == ROW_ORDER ) + A->me[i / A->n][i % A->n] = d_temp; + else if ( o_flag == COL_ORDER ) + A->me[i % A->m][i / A->m] = d_temp; + else + error(E_FORMAT,"m_load"); + } + + if ( mat.imag ) /* skip imaginary part */ + for ( i = 0; i < A->m*A->n; i++ ) + { + if ( p_flag == DOUBLE_PREC ) + fread(&d_temp,sizeof(double),1,fp); + else + fread(&f_temp,sizeof(float),1,fp); + } + + return A; +} + diff --git a/matlab.h b/matlab.h new file mode 100644 index 0000000..b3a4f30 --- /dev/null +++ b/matlab.h @@ -0,0 +1,113 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* matlab.h -- Header file for matlab.c, spmatlab.c and zmatlab.c + for save/load formats */ + +#ifndef MATLAB_DEF + +#define MATLAB_DEF + +/* structure required by MATLAB */ +typedef struct { + long type; /* matrix type */ + long m; /* # rows */ + long n; /* # cols */ + long imag; /* is complex? */ + long namlen; /* length of variable name */ + } matlab; + +/* macros for matrix storage type */ +#define INTEL 0 /* for 80x87 format */ +#define PC INTEL +#define MOTOROLA 1 /* 6888x format */ +#define SUN MOTOROLA +#define APOLLO MOTOROLA +#define MAC MOTOROLA +#define VAX_D 2 +#define VAX_G 3 + +#define COL_ORDER 0 +#define ROW_ORDER 1 + +#define DOUBLE_PREC 0 /* double precision */ +#define SINGLE_PREC 1 /* single precision */ +#define INT_32 2 /* 32 bit integers (signed) */ +#define INT_16 3 /* 16 bit integers (signed) */ +#define INT_16u 4 /* 16 bit integers (unsigned) */ +/* end of macros for matrix storage type */ + +#ifndef MACH_ID +#define MACH_ID MOTOROLA +#endif + +#define ORDER COL_ORDER + +#if REAL == DOUBLE +#define PRECISION DOUBLE_PREC +#elif REAL == FLOAT +#define PRECISION SINGLE_PREC +#endif + + +/* prototypes */ + +#ifdef ANSI_C + +MAT *m_save(FILE *,MAT *,const char *); +MAT *m_load(FILE *,char **); +VEC *v_save(FILE *,VEC *,const char *); +double d_save(FILE *,double,const char *); + +#else + +extern MAT *m_save(), *m_load(); +extern VEC *v_save(); +extern double d_save(); +#endif + +/* complex variant */ +#ifdef COMPLEX +#include "zmatrix.h" + +#ifdef ANSI_C +extern ZMAT *zm_save(FILE *fp,ZMAT *A,char *name); +extern ZVEC *zv_save(FILE *fp,ZVEC *x,char *name); +extern complex z_save(FILE *fp,complex z,char *name); +extern ZMAT *zm_load(FILE *fp,char **name); + +#else + +extern ZMAT *zm_save(); +extern ZVEC *zv_save(); +extern complex z_save(); +extern ZMAT *zm_load(); + +#endif + +#endif + +#endif diff --git a/matop.c b/matop.c new file mode 100644 index 0000000..1301ca1 --- /dev/null +++ b/matop.c @@ -0,0 +1,556 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* matop.c 1.3 11/25/87 */ + + +#include +#include "matrix.h" + +static char rcsid[] = "$Id: matop.c,v 1.4 1995/03/27 15:43:57 des Exp $"; + + +/* m_add -- matrix addition -- may be in-situ */ +#ifndef ANSI_C +MAT *m_add(mat1,mat2,out) +MAT *mat1,*mat2,*out; +#else +MAT *m_add(const MAT *mat1, const MAT *mat2, MAT *out) +#endif +{ + unsigned int m,n,i; + + if ( mat1==(MAT *)NULL || mat2==(MAT *)NULL ) + error(E_NULL,"m_add"); + if ( mat1->m != mat2->m || mat1->n != mat2->n ) + error(E_SIZES,"m_add"); + if ( out==(MAT *)NULL || out->m != mat1->m || out->n != mat1->n ) + out = m_resize(out,mat1->m,mat1->n); + m = mat1->m; n = mat1->n; + for ( i=0; ime[i],mat2->me[i],out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = mat1->me[i][j]+mat2->me[i][j]; + **************************************************/ + } + + return (out); +} + +/* m_sub -- matrix subtraction -- may be in-situ */ +#ifndef ANSI_C +MAT *m_sub(mat1,mat2,out) +MAT *mat1,*mat2,*out; +#else +MAT *m_sub(const MAT *mat1, const MAT *mat2, MAT *out) +#endif +{ + unsigned int m,n,i; + + if ( mat1==(MAT *)NULL || mat2==(MAT *)NULL ) + error(E_NULL,"m_sub"); + if ( mat1->m != mat2->m || mat1->n != mat2->n ) + error(E_SIZES,"m_sub"); + if ( out==(MAT *)NULL || out->m != mat1->m || out->n != mat1->n ) + out = m_resize(out,mat1->m,mat1->n); + m = mat1->m; n = mat1->n; + for ( i=0; ime[i],mat2->me[i],out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = mat1->me[i][j]-mat2->me[i][j]; + **************************************************/ + } + + return (out); +} + +/* m_mlt -- matrix-matrix multiplication */ +#ifndef ANSI_C +MAT *m_mlt(A,B,OUT) +MAT *A,*B,*OUT; +#else +MAT *m_mlt(const MAT *A, const MAT *B, MAT *OUT) +#endif +{ + unsigned int i, /* j, */ k, m, n, p; + Real **A_v, **B_v /*, *B_row, *OUT_row, sum, tmp */; + + if ( A==(MAT *)NULL || B==(MAT *)NULL ) + error(E_NULL,"m_mlt"); + if ( A->n != B->m ) + error(E_SIZES,"m_mlt"); + if ( A == OUT || B == OUT ) + error(E_INSITU,"m_mlt"); + m = A->m; n = A->n; p = B->n; + A_v = A->me; B_v = B->me; + + if ( OUT==(MAT *)NULL || OUT->m != A->m || OUT->n != B->n ) + OUT = m_resize(OUT,A->m,B->n); + +/**************************************************************** + for ( i=0; ime[i][j] = sum; + } +****************************************************************/ + m_zero(OUT); + for ( i=0; ime[i],B_v[k],A_v[i][k],(int)p); + /************************************************** + B_row = B_v[k]; OUT_row = OUT->me[i]; + for ( j=0; jn != B->n ) + error(E_SIZES,"mmtr_mlt"); + if ( ! OUT || OUT->m != A->m || OUT->n != B->m ) + OUT = m_resize(OUT,A->m,B->m); + + limit = A->n; + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < B->m; j++ ) + { + OUT->me[i][j] = __ip__(A->me[i],B->me[j],(int)limit); + /************************************************** + sum = 0.0; + A_row = A->me[i]; + B_row = B->me[j]; + for ( k = 0; k < limit; k++ ) + sum += (*A_row++)*(*B_row++); + OUT->me[i][j] = sum; + **************************************************/ + } + + return OUT; +} + +/* mtrm_mlt -- matrix transposed-matrix multiplication + -- A^T.B is returned, result stored in OUT */ +#ifndef ANSI_C +MAT *mtrm_mlt(A,B,OUT) +MAT *A, *B, *OUT; +#else +MAT *mtrm_mlt(const MAT *A, const MAT *B, MAT *OUT) +#endif +{ + int i, k, limit; + /* Real *B_row, *OUT_row, multiplier; */ + + if ( ! A || ! B ) + error(E_NULL,"mmtr_mlt"); + if ( A == OUT || B == OUT ) + error(E_INSITU,"mtrm_mlt"); + if ( A->m != B->m ) + error(E_SIZES,"mmtr_mlt"); + if ( ! OUT || OUT->m != A->n || OUT->n != B->n ) + OUT = m_resize(OUT,A->n,B->n); + + limit = B->n; + m_zero(OUT); + for ( k = 0; k < A->m; k++ ) + for ( i = 0; i < A->n; i++ ) + { + if ( A->me[k][i] != 0.0 ) + __mltadd__(OUT->me[i],B->me[k],A->me[k][i],(int)limit); + /************************************************** + multiplier = A->me[k][i]; + OUT_row = OUT->me[i]; + B_row = B->me[k]; + for ( j = 0; j < limit; j++ ) + *(OUT_row++) += multiplier*(*B_row++); + **************************************************/ + } + + return OUT; +} + +/* mv_mlt -- matrix-vector multiplication + -- Note: b is treated as a column vector */ +#ifndef ANSI_C +VEC *mv_mlt(A,b,out) +MAT *A; +VEC *b,*out; +#else +VEC *mv_mlt(const MAT *A, const VEC *b, VEC *out) +#endif +{ + unsigned int i, m, n; + Real **A_v, *b_v /*, *A_row */; + /* register Real sum; */ + + if ( A==(MAT *)NULL || b==(VEC *)NULL ) + error(E_NULL,"mv_mlt"); + if ( A->n != b->dim ) + error(E_SIZES,"mv_mlt"); + if ( b == out ) + error(E_INSITU,"mv_mlt"); + if ( out == (VEC *)NULL || out->dim != A->m ) + out = v_resize(out,A->m); + + m = A->m; n = A->n; + A_v = A->me; b_v = b->ve; + for ( i=0; ive[i] = __ip__(A_v[i],b_v,(int)n); + /************************************************** + A_row = A_v[i]; b_v = b->ve; + for ( j=0; jve[i] = sum; + **************************************************/ + } + + return out; +} + +/* sm_mlt -- scalar-matrix multiply -- may be in-situ */ +#ifndef ANSI_C +MAT *sm_mlt(scalar,matrix,out) +double scalar; +MAT *matrix,*out; +#else +MAT *sm_mlt(double scalar, const MAT *matrix, MAT *out) +#endif +{ + unsigned int m,n,i; + + if ( matrix==(MAT *)NULL ) + error(E_NULL,"sm_mlt"); + if ( out==(MAT *)NULL || out->m != matrix->m || out->n != matrix->n ) + out = m_resize(out,matrix->m,matrix->n); + m = matrix->m; n = matrix->n; + for ( i=0; ime[i],(double)scalar,out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = scalar*matrix->me[i][j]; + **************************************************/ + return (out); +} + +/* vm_mlt -- vector-matrix multiplication + -- Note: b is treated as a row vector */ +#ifndef ANSI_C +VEC *vm_mlt(A,b,out) +MAT *A; +VEC *b,*out; +#else +VEC *vm_mlt(const MAT *A, const VEC *b, VEC *out) +#endif +{ + unsigned int j,m,n; + /* Real sum,**A_v,*b_v; */ + + if ( A==(MAT *)NULL || b==(VEC *)NULL ) + error(E_NULL,"vm_mlt"); + if ( A->m != b->dim ) + error(E_SIZES,"vm_mlt"); + if ( b == out ) + error(E_INSITU,"vm_mlt"); + if ( out == (VEC *)NULL || out->dim != A->n ) + out = v_resize(out,A->n); + + m = A->m; n = A->n; + + v_zero(out); + for ( j = 0; j < m; j++ ) + if ( b->ve[j] != 0.0 ) + __mltadd__(out->ve,A->me[j],b->ve[j],(int)n); + /************************************************** + A_v = A->me; b_v = b->ve; + for ( j=0; jve[j] = sum; + } + **************************************************/ + + return out; +} + +/* m_transp -- transpose matrix */ +#ifndef ANSI_C +MAT *m_transp(in,out) +MAT *in, *out; +#else +MAT *m_transp(const MAT *in, MAT *out) +#endif +{ + int i, j; + int in_situ; + Real tmp; + + if ( in == (MAT *)NULL ) + error(E_NULL,"m_transp"); + if ( in == out && in->n != in->m ) + error(E_INSITU2,"m_transp"); + in_situ = ( in == out ); + if ( out == (MAT *)NULL || out->m != in->n || out->n != in->m ) + out = m_resize(out,in->n,in->m); + + if ( ! in_situ ) + for ( i = 0; i < in->m; i++ ) + for ( j = 0; j < in->n; j++ ) + out->me[j][i] = in->me[i][j]; + else + for ( i = 1; i < in->m; i++ ) + for ( j = 0; j < i; j++ ) + { tmp = in->me[i][j]; + in->me[i][j] = in->me[j][i]; + in->me[j][i] = tmp; + } + + return out; +} + +/* swap_rows -- swaps rows i and j of matrix A for cols lo through hi */ +#ifndef ANSI_C +MAT *swap_rows(A,i,j,lo,hi) +MAT *A; +int i, j, lo, hi; +#else +MAT *swap_rows(MAT *A, int i, int j, int lo, int hi) +#endif +{ + int k; + Real **A_me, tmp; + + if ( ! A ) + error(E_NULL,"swap_rows"); + if ( i < 0 || j < 0 || i >= A->m || j >= A->m ) + error(E_SIZES,"swap_rows"); + lo = max(0,lo); + hi = min(hi,A->n-1); + A_me = A->me; + + for ( k = lo; k <= hi; k++ ) + { + tmp = A_me[k][i]; + A_me[k][i] = A_me[k][j]; + A_me[k][j] = tmp; + } + return A; +} + +/* swap_cols -- swap columns i and j of matrix A for cols lo through hi */ +#ifndef ANSI_C +MAT *swap_cols(A,i,j,lo,hi) +MAT *A; +int i, j, lo, hi; +#else +MAT *swap_cols(MAT *A, int i, int j, int lo, int hi) +#endif +{ + int k; + Real **A_me, tmp; + + if ( ! A ) + error(E_NULL,"swap_cols"); + if ( i < 0 || j < 0 || i >= A->n || j >= A->n ) + error(E_SIZES,"swap_cols"); + lo = max(0,lo); + hi = min(hi,A->m-1); + A_me = A->me; + + for ( k = lo; k <= hi; k++ ) + { + tmp = A_me[i][k]; + A_me[i][k] = A_me[j][k]; + A_me[j][k] = tmp; + } + return A; +} + +/* ms_mltadd -- matrix-scalar multiply and add + -- may be in situ + -- returns out == A1 + s*A2 */ +#ifndef ANSI_C +MAT *ms_mltadd(A1,A2,s,out) +MAT *A1, *A2, *out; +double s; +#else +MAT *ms_mltadd(const MAT *A1, const MAT *A2, double s, MAT *out) +#endif +{ + /* register Real *A1_e, *A2_e, *out_e; */ + /* register int j; */ + int i, m, n; + + if ( ! A1 || ! A2 ) + error(E_NULL,"ms_mltadd"); + if ( A1->m != A2->m || A1->n != A2->n ) + error(E_SIZES,"ms_mltadd"); + + if ( out != A1 && out != A2 ) + out = m_resize(out,A1->m,A1->n); + + if ( s == 0.0 ) + return m_copy(A1,out); + if ( s == 1.0 ) + return m_add(A1,A2,out); + + tracecatch(out = m_copy(A1,out),"ms_mltadd"); + + m = A1->m; n = A1->n; + for ( i = 0; i < m; i++ ) + { + __mltadd__(out->me[i],A2->me[i],s,(int)n); + /************************************************** + A1_e = A1->me[i]; + A2_e = A2->me[i]; + out_e = out->me[i]; + for ( j = 0; j < n; j++ ) + out_e[j] = A1_e[j] + s*A2_e[j]; + **************************************************/ + } + + return out; +} + +/* mv_mltadd -- matrix-vector multiply and add + -- may not be in situ + -- returns out == v1 + alpha*A*v2 */ +#ifndef ANSI_C +VEC *mv_mltadd(v1,v2,A,alpha,out) +VEC *v1, *v2, *out; +MAT *A; +double alpha; +#else +VEC *mv_mltadd(const VEC *v1, const VEC *v2, const MAT *A, + double alpha, VEC *out) +#endif +{ + /* register int j; */ + int i, m, n; + Real *v2_ve, *out_ve; + + if ( ! v1 || ! v2 || ! A ) + error(E_NULL,"mv_mltadd"); + if ( out == v2 ) + error(E_INSITU,"mv_mltadd"); + if ( v1->dim != A->m || v2->dim != A->n ) + error(E_SIZES,"mv_mltadd"); + + tracecatch(out = v_copy(v1,out),"mv_mltadd"); + + v2_ve = v2->ve; out_ve = out->ve; + m = A->m; n = A->n; + + if ( alpha == 0.0 ) + return out; + + for ( i = 0; i < m; i++ ) + { + out_ve[i] += alpha*__ip__(A->me[i],v2_ve,(int)n); + /************************************************** + A_e = A->me[i]; + sum = 0.0; + for ( j = 0; j < n; j++ ) + sum += A_e[j]*v2_ve[j]; + out_ve[i] = v1->ve[i] + alpha*sum; + **************************************************/ + } + + return out; +} + +/* vm_mltadd -- vector-matrix multiply and add + -- may not be in situ + -- returns out' == v1' + v2'*A */ +#ifndef ANSI_C +VEC *vm_mltadd(v1,v2,A,alpha,out) +VEC *v1, *v2, *out; +MAT *A; +double alpha; +#else +VEC *vm_mltadd(const VEC *v1, const VEC *v2, const MAT *A, + double alpha, VEC *out) +#endif +{ + int /* i, */ j, m, n; + Real tmp, /* *A_e, */ *out_ve; + + if ( ! v1 || ! v2 || ! A ) + error(E_NULL,"vm_mltadd"); + if ( v2 == out ) + error(E_INSITU,"vm_mltadd"); + if ( v1->dim != A->n || A->m != v2->dim ) + error(E_SIZES,"vm_mltadd"); + + tracecatch(out = v_copy(v1,out),"vm_mltadd"); + + out_ve = out->ve; m = A->m; n = A->n; + for ( j = 0; j < m; j++ ) + { + tmp = v2->ve[j]*alpha; + if ( tmp != 0.0 ) + __mltadd__(out_ve,A->me[j],tmp,(int)n); + /************************************************** + A_e = A->me[j]; + for ( i = 0; i < n; i++ ) + out_ve[i] += A_e[i]*tmp; + **************************************************/ + } + + return out; +} + diff --git a/matrix.h b/matrix.h new file mode 100644 index 0000000..93c5ce9 --- /dev/null +++ b/matrix.h @@ -0,0 +1,689 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Type definitions for general purpose maths package +*/ + +#ifndef MATRIXH + +/* RCS id: $Id: matrix.h,v 1.18 1994/04/16 00:33:37 des Exp $ */ + +#define MATRIXH + +#include "machine.h" +#include "err.h" +#include "meminfo.h" + +/* unsigned integer type */ +/************************************************************ +#ifndef U_INT_DEF +typedef unsigned int u_int; +#define U_INT_DEF +#endif +************************************************************/ + +/* vector definition */ +typedef struct { + unsigned int dim, max_dim; + Real *ve; + } VEC; + +/* matrix definition */ +typedef struct { + unsigned int m, n; + unsigned int max_m, max_n, max_size; + Real **me,*base; /* base is base of alloc'd mem */ + } MAT; + +/* band matrix definition */ +typedef struct { + MAT *mat; /* matrix */ + int lb,ub; /* lower and upper bandwidth */ + } BAND; + + +/* permutation definition */ +typedef struct { + unsigned int size, max_size, *pe; + } PERM; + +/* integer vector definition */ +typedef struct { + unsigned int dim, max_dim; + int *ive; + } IVEC; + + +#ifndef MALLOCDECL +#ifndef ANSI_C +extern char *malloc(), *calloc(), *realloc(); +#else +extern void *malloc(size_t), + *calloc(size_t,size_t), + *realloc(void *,size_t); +#endif +#endif /* MALLOCDECL */ + +/* For creating MEX files (for use with Matlab) using Meschach + See also: mexmesch.h */ +#ifdef MEX +#include "mex.h" +#define malloc(len) mxMalloc(len) +#define calloc(n,len) mxCalloc(n,len) +#define realloc(ptr,len) mxRealloc(ptr,len) +#define free(ptr) mxFree(ptr) +#define printf mexPrintf +#ifndef THREADSAFE /* for use as a shared library */ +#define THREADSAFE 1 +#endif +#endif /* MEX */ + +#ifdef THREADSAFE +#define STATIC +#else +#define STATIC static +#endif /* THREADSAFE */ + +#ifndef ANSI_C +extern void m_version(); +#else +void m_version( void ); +#endif + +#ifndef ANSI_C +/* allocate one object of given type */ +#define NEW(type) ((type *)calloc((size_t)1,sizeof(type))) + +/* allocate num objects of given type */ +#define NEW_A(num,type) ((type *)calloc((size_t)(num),sizeof(type))) + + /* re-allocate arry to have num objects of the given type */ +#define RENEW(var,num,type) \ + ((var)=(type *)((var) ? \ + realloc((char *)(var),(size_t)(num)*sizeof(type)) : \ + calloc((size_t)(num),sizeof(type)))) + +#define MEMCOPY(from,to,n_items,type) \ + MEM_COPY((char *)(from),(char *)(to),(size_t)(n_items)*sizeof(type)) + +#else +/* allocate one object of given type */ +#define NEW(type) ((type *)calloc((size_t)1,(size_t)sizeof(type))) + +/* allocate num objects of given type */ +#define NEW_A(num,type) ((type *)calloc((size_t)(num),(size_t)sizeof(type))) + + /* re-allocate arry to have num objects of the given type */ +#define RENEW(var,num,type) \ + ((var)=(type *)((var) ? \ + realloc((char *)(var),(size_t)((num)*sizeof(type))) : \ + calloc((size_t)(num),(size_t)sizeof(type)))) + +#define MEMCOPY(from,to,n_items,type) \ + MEM_COPY((char *)(from),(char *)(to),(unsigned)(n_items)*sizeof(type)) + +#endif /* ANSI_C */ + +/* type independent min and max operations */ +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif /* max */ +#ifndef min +#define min(a,b) ((a) > (b) ? (b) : (a)) +#endif /* min */ + + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + + +/* for input routines */ +#define MAXLINE 81 + + +/* Dynamic memory allocation */ + +/* Should use M_FREE/V_FREE/PX_FREE in programs instead of m/v/px_free() + as this is considerably safer -- also provides a simple type check ! */ + +#ifndef ANSI_C + +extern VEC *v_get(), *v_resize(); +extern MAT *m_get(), *m_resize(); +extern PERM *px_get(), *px_resize(); +extern IVEC *iv_get(), *iv_resize(); +extern int m_free(),v_free(); +extern int px_free(); +extern int iv_free(); +extern BAND *bd_get(), *bd_resize(); +extern int bd_free(); + +#else + +/* get/resize vector to given dimension */ +extern VEC *v_get(int), *v_resize(VEC *,int); +/* get/resize matrix to be m x n */ +extern MAT *m_get(int,int), *m_resize(MAT *,int,int); +/* get/resize permutation to have the given size */ +extern PERM *px_get(int), *px_resize(PERM *,int); +/* get/resize an integer vector to given dimension */ +extern IVEC *iv_get(int), *iv_resize(IVEC *,int); +/* get/resize a band matrix to given dimension */ +extern BAND *bd_get(int,int,int), *bd_resize(BAND *,int,int,int); + +/* free (de-allocate) (band) matrices, vectors, permutations and + integer vectors */ +extern int iv_free(IVEC *); +extern m_free(MAT *),v_free(VEC *),px_free(PERM *); +extern int bd_free(BAND *); + +#endif /* ANSI_C */ + + +/* MACROS */ + +/* macros that also check types and sets pointers to NULL */ +#define M_FREE(mat) ( m_free(mat), (mat)=(MAT *)NULL ) +#define V_FREE(vec) ( v_free(vec), (vec)=(VEC *)NULL ) +#define PX_FREE(px) ( px_free(px), (px)=(PERM *)NULL ) +#define IV_FREE(iv) ( iv_free(iv), (iv)=(IVEC *)NULL ) + +#define MAXDIM 10000001 + + +/* Entry level access to data structures */ +/* routines to check indexes */ +#define m_chk_idx(A,i,j) ((i)>=0 && (i)<(A)->m && (j)>=0 && (j)<=(A)->n) +#define v_chk_idx(x,i) ((i)>=0 && (i)<(x)->dim) +#define bd_chk_idx(A,i,j) ((i)>=max(0,(j)-(A)->ub) && \ + (j)>=max(0,(i)-(A)->lb) && (i)<(A)->mat->n && (j)<(A)->mat->n) + +#define m_entry(A,i,j) m_get_val(A,i,j) +#define v_entry(x,i) v_get_val(x,i) +#define bd_entry(A,i,j) bd_get_val(A,i,j) +#ifdef DEBUG +#define m_set_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] = (val) : (error(E_BOUNDS,"m_set_val"), 0.0)) +#define m_add_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] += (val) : (error(E_BOUNDS,"m_add_val"), 0.0)) +#define m_sub_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] -= (val) : (error(E_BOUNDS,"m_sub_val"), 0.0)) +#define m_get_val(A,i,j) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] : (error(E_BOUNDS,"m_get_val"), 0.0)) +#define v_set_val(x,i,val) ( v_chk_idx(x,i) ? (x)->ve[(i)] = (val) : \ + (error(E_BOUNDS,"v_set_val"), 0.0)) +#define v_add_val(x,i,val) ( v_chk_idx(x,i) ? (x)->ve[(i)] += (val) : \ + (error(E_BOUNDS,"v_set_val"), 0.0)) +#define v_sub_val(x,i,val) ( v_chk_idx(x,i) ? (x)->ve[(i)] -= (val) : \ + (error(E_BOUNDS,"v_set_val"), 0.0)) +#define v_get_val(x,i) ( v_chk_idx(x,i) ? (x)->ve[(i)] : \ + (error(E_BOUNDS,"v_get_val"), 0.0)) +#define bd_set_val(A,i,j,val) ( bd_chk_idx(A,i,j) ? \ + (A)->mat->me[(A)->lb+(j)-(i)][(j)] = (val) : \ + (error(E_BOUNDS,"bd_set_val"), 0.0)) +#define bd_add_val(A,i,j,val) ( bd_chk_idx(A,i,j) ? \ + (A)->mat->me[(A)->lb+(j)-(i)][(j)] += (val) : \ + (error(E_BOUNDS,"bd_set_val"), 0.0)) +#define bd_get_val(A,i,j) ( bd_chk_idx(A,i,j) ? \ + (A)->mat->me[(A)->lb+(j)-(i)][(j)] : \ + (error(E_BOUNDS,"bd_get_val"), 0.0)) +#else /* no DEBUG */ +#define m_set_val(A,i,j,val) ((A)->me[(i)][(j)] = (val)) +#define m_add_val(A,i,j,val) ((A)->me[(i)][(j)] += (val)) +#define m_sub_val(A,i,j,val) ((A)->me[(i)][(j)] -= (val)) +#define m_get_val(A,i,j) ((A)->me[(i)][(j)]) +#define v_set_val(x,i,val) ((x)->ve[(i)] = (val)) +#define v_add_val(x,i,val) ((x)->ve[(i)] += (val)) +#define v_sub_val(x,i,val) ((x)->ve[(i)] -= (val)) +#define v_get_val(x,i) ((x)->ve[(i)]) +#define bd_set_val(A,i,j,val) ((A)->mat->me[(A)->lb+(j)-(i)][(j)] = (val)) +#define bd_add_val(A,i,j,val) ((A)->mat->me[(A)->lb+(j)-(i)][(j)] += (val)) +#define bd_get_val(A,i,j) ((A)->mat->me[(A)->lb+(j)-(i)][(j)]) +#endif /* DEBUG */ + + +/* I/O routines */ +#ifndef ANSI_C + +extern void v_foutput(),m_foutput(),px_foutput(); +extern void iv_foutput(); +extern VEC *v_finput(); +extern MAT *m_finput(); +extern PERM *px_finput(); +extern IVEC *iv_finput(); +extern int fy_or_n(), fin_int(), yn_dflt(), skipjunk(); +extern double fin_double(); + +#else + +/* print x on file fp */ +void v_foutput(FILE *fp,const VEC *x), + /* print A on file fp */ + m_foutput(FILE *fp,const MAT *A), + /* print px on file fp */ + px_foutput(FILE *fp,const PERM *px); +/* print ix on file fp */ +void iv_foutput(FILE *fp,const IVEC *ix); + +/* Note: if out is NULL, then returned object is newly allocated; + Also: if out is not NULL, then that size is assumed */ + +/* read in vector from fp */ +VEC *v_finput(FILE *fp,VEC *out); +/* read in matrix from fp */ +MAT *m_finput(FILE *fp,MAT *out); +/* read in permutation from fp */ +PERM *px_finput(FILE *fp,PERM *out); +/* read in int vector from fp */ +IVEC *iv_finput(FILE *fp,IVEC *out); + +/* fy_or_n -- yes-or-no to question in string s + -- question written to stderr, input from fp + -- if fp is NOT a tty then return y_n_dflt */ +int fy_or_n(FILE *fp, const char *s); + +/* yn_dflt -- sets the value of y_n_dflt to val */ +int yn_dflt(int val); + +/* fin_int -- return integer read from file/stream fp + -- prompt s on stderr if fp is a tty + -- check that x lies between low and high: re-prompt if + fp is a tty, error exit otherwise + -- ignore check if low > high */ +int fin_int(FILE *fp,const char *s,int low,int high); + +/* fin_double -- return double read from file/stream fp + -- prompt s on stderr if fp is a tty + -- check that x lies between low and high: re-prompt if + fp is a tty, error exit otherwise + -- ignore check if low > high */ +double fin_double(FILE *fp,const char *s,double low,double high); + +/* it skips white spaces and strings of the form #....\n + Here .... is a comment string */ +int skipjunk(FILE *fp); + +#endif /* ANSI_C */ + + +/* MACROS */ + +/* macros to use stdout and stdin instead of explicit fp */ +#define v_output(vec) v_foutput(stdout,vec) +#define v_input(vec) v_finput(stdin,vec) +#define m_output(mat) m_foutput(stdout,mat) +#define m_input(mat) m_finput(stdin,mat) +#define px_output(px) px_foutput(stdout,px) +#define px_input(px) px_finput(stdin,px) +#define iv_output(iv) iv_foutput(stdout,iv) +#define iv_input(iv) iv_finput(stdin,iv) + +/* general purpose input routine; skips comments # ... \n */ +#define finput(fp,prompt,fmt,var) \ + ( ( isatty(fileno(fp)) ? fprintf(stderr,prompt) : skipjunk(fp) ), \ + fscanf(fp,fmt,var) ) +#define input(prompt,fmt,var) finput(stdin,prompt,fmt,var) +#define fprompter(fp,prompt) \ + ( isatty(fileno(fp)) ? fprintf(stderr,prompt) : skipjunk(fp) ) +#define prompter(prompt) fprompter(stdin,prompt) +#define y_or_n(s) fy_or_n(stdin,s) +#define in_int(s,lo,hi) fin_int(stdin,s,lo,hi) +#define in_double(s,lo,hi) fin_double(stdin,s,lo,hi) + + +/* special purpose access routines */ + +/* Copying routines */ +#ifndef ANSI_C +extern MAT *_m_copy(), *m_move(), *vm_move(); +extern VEC *_v_copy(), *v_move(), *mv_move(); +extern PERM *px_copy(); +extern IVEC *iv_copy(), *iv_move(); +extern BAND *bd_copy(); + +#else + +/* copy in to out starting at out[i0][j0] */ +extern MAT *_m_copy(const MAT *in,MAT *out,unsigned int i0,unsigned int j0), + * m_move(const MAT *in, int, int, int, int, MAT *out, int, int), + *vm_move(const VEC *in, int, MAT *out, int, int, int, int); +/* copy in to out starting at out[i0] */ +extern VEC *_v_copy(const VEC *in,VEC *out,unsigned int i0), + * v_move(const VEC *in, int, int, VEC *out, int), + *mv_move(const MAT *in, int, int, int, int, VEC *out, int); +extern PERM *px_copy(const PERM *in,PERM *out); +extern IVEC *iv_copy(const IVEC *in,IVEC *out), + *iv_move(const IVEC *in, int, int, IVEC *out, int); +extern BAND *bd_copy(const BAND *in,BAND *out); + +#endif /* ANSI_C */ + + +/* MACROS */ +#define m_copy(in,out) _m_copy(in,out,0,0) +#define v_copy(in,out) _v_copy(in,out,0) + + +/* Initialisation routines -- to be zero, ones, random or identity */ +#ifndef ANSI_C +extern VEC *v_zero(), *v_rand(), *v_ones(); +extern MAT *m_zero(), *m_ident(), *m_rand(), *m_ones(); +extern PERM *px_ident(); +extern IVEC *iv_zero(); +#else +extern VEC *v_zero(VEC *), *v_rand(VEC *), *v_ones(VEC *); +extern MAT *m_zero(MAT *), *m_ident(MAT *), *m_rand(MAT *), + *m_ones(MAT *); +extern PERM *px_ident(PERM *); +extern IVEC *iv_zero(IVEC *); +#endif /* ANSI_C */ + +/* Basic vector operations */ +#ifndef ANSI_C +extern VEC *sv_mlt(), *mv_mlt(), *vm_mlt(), *v_add(), *v_sub(), + *px_vec(), *pxinv_vec(), *v_mltadd(), *v_map(), *_v_map(), + *v_lincomb(), *v_linlist(); +extern double v_min(), v_max(), v_sum(); +extern VEC *v_star(), *v_slash(), *v_sort(); +extern double _in_prod(), __ip__(); +extern void __mltadd__(), __add__(), __sub__(), + __smlt__(), __zero__(); +#else + +extern VEC *sv_mlt(double s,const VEC *x,VEC *out), /* out <- s.x */ + *mv_mlt(const MAT *A,const VEC *s,VEC *out), /* out <- A.x */ + *vm_mlt(const MAT *A,const VEC *x,VEC *out), /* out^T <- x^T.A */ + *v_add(const VEC *x,const VEC *y,VEC *out), /* out <- x + y */ + *v_sub(const VEC *x,const VEC *y,VEC *out), /* out <- x - y */ + *px_vec(PERM *px,const VEC *x,VEC *out), /* out <- P.x */ + *pxinv_vec(PERM *px,const VEC *x,VEC *out), /* out <- P^{-1}.x */ + *v_mltadd(const VEC *x,const VEC *y,double s,VEC *out), /* out <- x + s.y */ +#ifdef PROTOTYPES_IN_STRUCT + *v_map(double (*f)(double),const VEC *x,VEC *y), + /* out[i] <- f(x[i]) */ + *_v_map(double (*f)(void *,double),void *p,const VEC *x,VEC *y), +#else + *v_map(double (*f)(),const VEC *,VEC *), /* out[i] <- f(x[i]) */ + *_v_map(double (*f)(),void *,const VEC *,VEC *), +#endif /* PROTOTYPES_IN_STRUCT */ + *v_lincomb(int,const VEC **,const Real *,VEC *), + /* out <- sum_i s[i].x[i] */ + *v_linlist(VEC *out,VEC *v1,double a1,...); + /* out <- s1.x1 + s2.x2 + ... */ + +/* returns min_j x[j] (== x[i]) */ +extern double v_min(const VEC *, int *), + /* returns max_j x[j] (== x[i]) */ + v_max(const VEC *, int *), + /* returns sum_i x[i] */ + v_sum(const VEC *); + +/* Hadamard product: out[i] <- x[i].y[i] */ +extern VEC *v_star(const VEC *, const VEC *, VEC *), + /* out[i] <- x[i] / y[i] */ + *v_slash(const VEC *, const VEC *, VEC *), + /* sorts x, and sets order so that sorted x[i] = x[order[i]] */ + *v_sort(VEC *, PERM *); + +/* returns inner product starting at component i0 */ +extern double _in_prod(const VEC *x, const VEC *y,unsigned int i0), + /* returns sum_{i=0}^{len-1} x[i].y[i] */ + __ip__(const Real *,const Real *,int); + +/* see v_mltadd(), v_add(), v_sub() and v_zero() */ +extern void __mltadd__(Real *,const Real *,double,int), + __add__(const Real *,const Real *,Real *,int), + __sub__(const Real *,const Real *,Real *,int), + __smlt__(const Real *,double,Real *,int), + __zero__(Real *,int); + +#endif /* ANSI_C */ + + +/* MACRO */ +/* usual way of computing the inner product */ +#define in_prod(a,b) _in_prod(a,b,0) + +/* Norms */ +/* scaled vector norms -- scale == NULL implies unscaled */ +#ifndef ANSI_C + +extern double _v_norm1(), _v_norm2(), _v_norm_inf(), + m_norm1(), m_norm_inf(), m_norm_frob(); + +#else + /* returns sum_i |x[i]/scale[i]| */ +extern double _v_norm1(const VEC *x,const VEC *scale), + /* returns (scaled) Euclidean norm */ + _v_norm2(const VEC *x,const VEC *scale), + /* returns max_i |x[i]/scale[i]| */ + _v_norm_inf(const VEC *x,const VEC *scale); + +/* unscaled matrix norms */ +extern double m_norm1(const MAT *A), + m_norm_inf(const MAT *A), + m_norm_frob(const MAT *A); + +#endif /* ANSI_C */ + + +/* MACROS */ +/* unscaled vector norms */ +#define v_norm1(x) _v_norm1(x,VNULL) +#define v_norm2(x) _v_norm2(x,VNULL) +#define v_norm_inf(x) _v_norm_inf(x,VNULL) + +/* Basic matrix operations */ +#ifndef ANSI_C + +extern MAT *sm_mlt(), *m_mlt(), *mmtr_mlt(), *mtrm_mlt(), *m_add(), *m_sub(), + *sub_mat(), *m_transp(), *ms_mltadd(); + +extern BAND *bd_transp(), *sbd_mlt(), *bds_mltadd(), *bd_zero(); +extern MAT *px_rows(), *px_cols(), *swap_rows(), *swap_cols(), + *_set_row(), *_set_col(); +extern VEC *get_row(), *get_col(), *sub_vec(), + *mv_mltadd(), *vm_mltadd(), *bdv_mltadd(); + +#else + +extern MAT *sm_mlt(double s, const MAT *A,MAT *out), /* out <- s.A */ + *m_mlt(const MAT *A,const MAT *B,MAT *out), /* out <- A.B */ + *mmtr_mlt(const MAT *A,const MAT *B,MAT *out), /* out <- A.B^T */ + *mtrm_mlt(const MAT *A,const MAT *B,MAT *out), /* out <- A^T.B */ + *m_add(const MAT *A,const MAT *B,MAT *out), /* out <- A + B */ + *m_sub(const MAT *A,const MAT *B,MAT *out), /* out <- A - B */ + *sub_mat(const MAT *A,unsigned int,unsigned int,unsigned int, + unsigned int,MAT *out), + *m_transp(const MAT *A,MAT *out), /* out <- A^T */ + /* out <- A + s.B */ + *ms_mltadd(const MAT *A,const MAT *B,double s,MAT *out); + + +extern BAND *bd_transp(const BAND *in, BAND *out), /* out <- A^T */ + *sbd_mlt(Real s, const BAND *A, BAND *OUT), /* OUT <- s.A */ + *bds_mltadd(const BAND *A, const BAND *B,double alpha, BAND *OUT), + /* OUT <- A+alpha.B */ + *bd_zero(BAND *A); /* A <- 0 */ + +extern MAT *px_rows(const PERM *px,const MAT *A,MAT *out), /* out <- P.A */ + *px_cols(const PERM *px,const MAT *A,MAT *out), /* out <- A.P^T */ + *swap_rows(MAT *,int,int,int,int), + *swap_cols(MAT *,int,int,int,int), + /* A[i][j] <- out[j], j >= j0 */ + *_set_col(MAT *A,unsigned int i,const VEC *col,unsigned int j0), + /* A[i][j] <- out[i], i >= i0 */ + *_set_row(MAT *A,unsigned int j,const VEC *row,unsigned int i0); + +extern VEC *get_row(const MAT *,unsigned int,VEC *), + *get_col(const MAT *,unsigned int,VEC *), + *sub_vec(const VEC *,int,int,VEC *), + /* mv_mltadd: out <- x + s.A.y */ + *mv_mltadd(const VEC *x,const VEC *y,const MAT *A, + double s,VEC *out), + /* vm_mltadd: out^T <- x^T + s.y^T.A */ + *vm_mltadd(const VEC *x,const VEC *y,const MAT *A, + double s,VEC *out), + /* bdv_mltadd: out <- x + s.A.y */ + *bdv_mltadd(const VEC *x,const VEC *y,const BAND *A, + double s,VEC *out); +#endif /* ANSI_C */ + + +/* MACROS */ +/* row i of A <- vec */ +#define set_row(mat,row,vec) _set_row(mat,row,vec,0) +/* col j of A <- vec */ +#define set_col(mat,col,vec) _set_col(mat,col,vec,0) + + +/* Basic permutation operations */ +#ifndef ANSI_C + +extern PERM *px_mlt(), *px_inv(), *px_transp(); +extern int px_sign(); + +#else + +extern PERM *px_mlt(const PERM *px1,const PERM *px2,PERM *out), /* out <- px1.px2 */ + *px_inv(const PERM *px,PERM *out), /* out <- px^{-1} */ + /* swap px[i] and px[j] */ + *px_transp(PERM *px,unsigned int i,unsigned int j); + + /* returns sign(px) = +1 if px product of even # transpositions + -1 if ps product of odd # transpositions */ +extern int px_sign(const PERM *); + +#endif /* ANSI_C */ + + +/* Basic integer vector operations */ +#ifndef ANSI_C + +extern IVEC *iv_add(), *iv_sub(), *iv_sort(); + +#else + +extern IVEC *iv_add(const IVEC *ix,const IVEC *iy,IVEC *out), + /* out <- ix + iy */ + *iv_sub(const IVEC *ix,const IVEC *iy,IVEC *out), + /* out <- ix - iy */ + /* sorts ix & sets order so that sorted ix[i] = old ix[order[i]] */ + *iv_sort(IVEC *ix, PERM *order); + +#endif /* ANSI_C */ + + +/* miscellaneous functions */ + +#ifndef ANSI_C + +extern double square(), cube(), mrand(); +extern void smrand(), mrandlist(); +extern void m_dump(), px_dump(), v_dump(), iv_dump(); +extern MAT *band2mat(); +extern BAND *mat2band(); + +#else + +double square(double x), /* returns x^2 */ + cube(double x), /* returns x^3 */ + mrand(void); /* returns random # in [0,1) */ + +void smrand(int seed), /* seeds mrand() */ + mrandlist(Real *x, int len); /* generates len random numbers */ + +void m_dump(FILE *fp,const MAT *a), px_dump(FILE *fp, const PERM *px), + v_dump(FILE *fp,const VEC *x), iv_dump(FILE *fp, const IVEC *ix); + +MAT *band2mat(const BAND *bA, MAT *A); +BAND *mat2band(const MAT *A, int lb,int ub, BAND *bA); + +#endif /* ANSI_C */ + + +/* miscellaneous constants */ +#define VNULL ((VEC *)NULL) +#define MNULL ((MAT *)NULL) +#define PNULL ((PERM *)NULL) +#define IVNULL ((IVEC *)NULL) +#define BDNULL ((BAND *)NULL) + + + +/* varying number of arguments */ + +#ifdef ANSI_C +#include + +/* prototypes */ + +int v_get_vars(int dim,...); +int iv_get_vars(int dim,...); +int m_get_vars(int m,int n,...); +int px_get_vars(int dim,...); + +int v_resize_vars(int new_dim,...); +int iv_resize_vars(int new_dim,...); +int m_resize_vars(int m,int n,...); +int px_resize_vars(int new_dim,...); + +int v_free_vars(VEC **,...); +int iv_free_vars(IVEC **,...); +int px_free_vars(PERM **,...); +int m_free_vars(MAT **,...); + +#elif VARARGS +/* old varargs is used */ + +#include + +/* prototypes */ + +int v_get_vars(); +int iv_get_vars(); +int m_get_vars(); +int px_get_vars(); + +int v_resize_vars(); +int iv_resize_vars(); +int m_resize_vars(); +int px_resize_vars(); + +int v_free_vars(); +int iv_free_vars(); +int px_free_vars(); +int m_free_vars(); + +#endif /* ANSI_C */ + + +#endif /* MATRIXH */ + + diff --git a/matrix2.h b/matrix2.h new file mode 100644 index 0000000..fe631f0 --- /dev/null +++ b/matrix2.h @@ -0,0 +1,236 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Header file for ``matrix2.a'' library file +*/ + + +#ifndef MATRIX2H +#define MATRIX2H + +#include "matrix.h" + +/* Unless otherwise specified, factorisation routines overwrite the + matrix that is being factorised */ + +#ifndef ANSI_C + +extern MAT *BKPfactor(), *CHfactor(), *LUfactor(), *QRfactor(), + *QRCPfactor(), *LDLfactor(), *Hfactor(), *MCHfactor(), + *m_inverse(); +extern double LUcondest(), QRcondest(); +extern MAT *makeQ(), *makeR(), *makeHQ(), *makeH(); +extern MAT *LDLupdate(), *QRupdate(); + +extern VEC *BKPsolve(), *CHsolve(), *LUsolve(), *_Qsolve(), *QRsolve(), + *LDLsolve(), *Usolve(), *Lsolve(), *Dsolve(), *LTsolve(), + *UTsolve(), *LUTsolve(), *QRCPsolve(); + +extern BAND *bdLUfactor(), *bdLDLfactor(); +extern VEC *bdLUsolve(), *bdLDLsolve(); + +extern VEC *hhvec(); +extern VEC *hhtrvec(); +extern MAT *hhtrrows(); +extern MAT *hhtrcols(), *_hhtrcols(); + +extern void givens(); +extern VEC *rot_vec(); /* in situ */ +extern MAT *rot_rows(); /* in situ */ +extern MAT *rot_cols(); /* in situ */ + + +/* eigenvalue routines */ +extern VEC *trieig(), *symmeig(); +extern MAT *schur(); +extern void schur_evals(); +extern MAT *schur_vecs(); + +/* singular value decomposition */ +extern VEC *bisvd(), *svd(); + +/* matrix powers and exponent */ +MAT *_m_pow(); +MAT *m_pow(); +MAT *m_exp(), *_m_exp(); +MAT *m_poly(); + +/* FFT */ +void fft(); +void ifft(); + + +#else + + /* forms Bunch-Kaufman-Parlett factorisation for + symmetric indefinite matrices */ +extern MAT *BKPfactor(MAT *A,PERM *pivot,PERM *blocks), + /* Cholesky factorisation of A + (symmetric, positive definite) */ + *CHfactor(MAT *A), + /* LU factorisation of A (with partial pivoting) */ + *LUfactor(MAT *A,PERM *pivot), + /* QR factorisation of A; need dim(diag) >= # rows of A */ + *QRfactor(MAT *A,VEC *diag), + /* QR factorisation of A with column pivoting */ + *QRCPfactor(MAT *A,VEC *diag,PERM *pivot), + /* L.D.L^T factorisation of A */ + *LDLfactor(MAT *A), + /* Hessenberg factorisation of A -- for schur() */ + *Hfactor(MAT *A,VEC *diag1,VEC *diag2), + /* modified Cholesky factorisation of A; + actually factors A+D, D diagonal with no + diagonal entry in the factor < sqrt(tol) */ + *MCHfactor(MAT *A,double tol), + *m_inverse(const MAT *A,MAT *out); + + /* returns condition estimate for A after LUfactor() */ +extern double LUcondest(const MAT *A, PERM *pivot), + /* returns condition estimate for Q after QRfactor() */ + QRcondest(const MAT *A); + +/* Note: The make..() and ..update() routines assume that the factorisation + has already been carried out */ + + /* Qout is the "Q" (orthongonal) matrix from QR factorisation */ +extern MAT *makeQ(const MAT *QR,const VEC *diag,MAT *Qout), + /* Rout is the "R" (upper triangular) matrix + from QR factorisation */ + *makeR(const MAT *A,MAT *Rout), + /* Qout is orthogonal matrix in Hessenberg factorisation */ + *makeHQ(MAT *A,VEC *diag1,VEC *diag2,MAT *Qout), + /* Hout is the Hessenberg matrix in Hessenberg factorisation */ + *makeH(const MAT *A,MAT *Hout); + + /* updates L.D.L^T factorisation for A <- A + alpha.u.u^T */ +extern MAT *LDLupdate(MAT *A,VEC *u,double alpha), + /* updates QR factorisation for QR <- Q.(R+u.v^T) + Note: we need explicit Q & R matrices, + from makeQ() and makeR() */ + *QRupdate(MAT *Q,MAT *R,VEC *u,VEC *v); + +/* Solve routines assume that the corresponding factorisation routine + has already been applied to the matrix along with auxiliary + objects (such as pivot permutations) + + These solve the system A.x = b, + except for LUTsolve and QRTsolve which solve the transposed system + A^T.x. = b. + If x is NULL on entry, then it is created. +*/ + +extern VEC *BKPsolve(const MAT *A,PERM *pivot,const PERM *blocks, + const VEC *b,VEC *x), + *CHsolve(const MAT *A,const VEC *b,VEC *x), + *LDLsolve(const MAT *A,const VEC *b,VEC *x), + *LUsolve(const MAT *A, PERM *pivot, const VEC *b,VEC *x), + *_Qsolve(const MAT *A, const VEC *diag, const VEC *b, + VEC *x, VEC *tmp), + *QRsolve(const MAT *A, const VEC *diag, const VEC *b,VEC *x), + *QRTsolve(const MAT *A,const VEC *,const VEC *b,VEC *x), + + + /* Triangular equations solve routines; + U for upper triangular, L for lower traingular, D for diagonal + if diag_val == 0.0 use that values in the matrix */ + + *Usolve(const MAT *A,const VEC *b,VEC *x,double diag_val), + *Lsolve(const MAT *A,const VEC *b,VEC *x,double diag_val), + *Dsolve(const MAT *A,const VEC *b,VEC *x), + *LTsolve(const MAT *A,const VEC *b,VEC *x,double diag_val), + *UTsolve(const MAT *A,const VEC *b,VEC *x,double diag_val), + *LUTsolve(const MAT *A,PERM *pivot,const VEC *b, VEC *x), + *QRCPsolve(const MAT *QR,const VEC *diag,PERM *pivot, + const VEC *b,VEC *x); + +extern BAND *bdLUfactor(BAND *A,PERM *pivot), + *bdLDLfactor(BAND *A); +extern VEC *bdLUsolve(const BAND *A,PERM *pivot,const VEC *b,VEC *x), + *bdLDLsolve(const BAND *A,const VEC *b,VEC *x); + + + +extern VEC *hhvec(const VEC *,unsigned int,Real *,VEC *,Real *); +extern VEC *hhtrvec(const VEC *,double,unsigned int,const VEC *,VEC *); +extern MAT *hhtrrows(MAT *,unsigned int,unsigned int,const VEC *,double); +extern MAT *hhtrcols(MAT *,unsigned int,unsigned int,const VEC *,double); +extern MAT *_hhtrcols(MAT *,unsigned int,unsigned int,const VEC *,double,VEC *); + +extern void givens(double,double,Real *,Real *); +extern VEC *rot_vec(const VEC *,unsigned int,unsigned int, + double,double,VEC *); /* in situ */ +extern MAT *rot_rows(const MAT *,unsigned int,unsigned int, + double,double,MAT *); /* in situ */ +extern MAT *rot_cols(const MAT *,unsigned int,unsigned int, + double,double,MAT *); /* in situ */ + + +/* eigenvalue routines */ + + /* compute eigenvalues of tridiagonal matrix + with diagonal entries a[i], super & sub diagonal entries + b[i]; eigenvectors stored in Q (if not NULL) */ +extern VEC *trieig(VEC *a,VEC *b,MAT *Q), + /* sets out to be vector of eigenvectors; eigenvectors + stored in Q (if not NULL). A is unchanged */ + *symmeig(const MAT *A,MAT *Q,VEC *out); + + /* computes real Schur form = Q^T.A.Q */ +extern MAT *schur(MAT *A,MAT *Q); + /* computes real and imaginary parts of the eigenvalues + of A after schur() */ +extern void schur_evals(MAT *A,VEC *re_part,VEC *im_part); + /* computes real and imaginary parts of the eigenvectors + of A after schur() */ +extern MAT *schur_vecs(MAT *T,MAT *Q,MAT *X_re,MAT *X_im); + + +/* singular value decomposition */ + + /* computes singular values of bi-diagonal matrix with + diagonal entries a[i] and superdiagonal entries b[i]; + singular vectors stored in U and V (if not NULL) */ +VEC *bisvd(VEC *a,VEC *b,MAT *U,MAT *V), + /* sets "out" to be vector of singular values; + singular vectors stored in U and V */ + *svd(MAT *A,MAT *U,MAT *V,VEC *out); + +/* matrix powers and exponent */ +MAT *_m_pow(const MAT *A, int p, MAT *tmp,MAT *out); +MAT *m_pow(const MAT *A, int p, MAT *out); +MAT *m_exp(MAT *,double,MAT *); +MAT *_m_exp(MAT *A, double eps, MAT *out, int *q_out, int *j_out); +MAT *m_poly(const MAT *,const VEC *,MAT *); + +/* FFT */ +void fft(VEC *,VEC *); +void ifft(VEC *,VEC *); + +#endif + + +#endif diff --git a/matrixio.c b/matrixio.c new file mode 100644 index 0000000..2e98049 --- /dev/null +++ b/matrixio.c @@ -0,0 +1,772 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* 1.6 matrixio.c 11/25/87 */ + + +#include +#include +#include "matrix.h" + +static char rcsid[] = "$Id: matrixio.c,v 1.4 1994/01/13 05:31:10 des Exp $"; + + +/* local variables */ +static char line[MAXLINE]; + + +/************************************************************************** + Input routines + **************************************************************************/ +/* skipjunk -- skips white spaces and strings of the form #....\n + Here .... is a comment string */ +#ifndef ANSI_C +int skipjunk(fp) +FILE *fp; +#else +int skipjunk(FILE *fp) +#endif +{ + int c; + + for ( ; ; ) /* forever do... */ + { + /* skip blanks */ + do + c = getc(fp); + while ( isspace(c) ); + + /* skip comments (if any) */ + if ( c == '#' ) + /* yes it is a comment (line) */ + while ( (c=getc(fp)) != '\n' ) + ; + else + { + ungetc(c,fp); + break; + } + } + return 0; +} + +/* m_finput -- input matrix + -- input from a terminal is handled interactively + -- batch/file input has the same format as produced by m_foutput + except that whitespace and comments ("#..\n") are skipped + -- returns a, which is created if a == NULL on entry */ +#ifndef ANSI_C +MAT *m_finput(fp,a) +FILE *fp; +MAT *a; +#else +MAT *m_finput(FILE *fp, MAT *a) +#endif +{ + MAT *im_finput(),*bm_finput(); + + if ( isatty(fileno(fp)) ) + return im_finput(fp,a); + else + return bm_finput(fp,a); +} + +/* im_finput -- interactive input of matrix */ +#ifndef ANSI_C +MAT *im_finput(fp,mat) +FILE *fp; +MAT *mat; +#else +MAT *im_finput(FILE *fp,MAT *mat) +#endif +{ + char c; + unsigned int i, j, m, n, dynamic; + /* dynamic set to TRUE if memory allocated here */ + + /* get matrix size */ + if ( mat != (MAT *)NULL && mat->mnm; n = mat->n; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"Matrix: rows cols:"); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"im_finput"); + } while ( sscanf(line,"%u%u",&m,&n)<2 || m>MAXDIM || n>MAXDIM ); + mat = m_get(m,n); + } + + /* input elements */ + for ( i=0; ime[i][j]); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"im_finput"); + if ( (*line == 'b' || *line == 'B') && j > 0 ) + { j--; dynamic = FALSE; goto redo2; } + if ( (*line == 'f' || *line == 'F') && j < n-1 ) + { j++; dynamic = FALSE; goto redo2; } +#if REAL == DOUBLE + } while ( *line=='\0' || sscanf(line,"%lf",&mat->me[i][j])<1 ); +#elif REAL == FLOAT + } while ( *line=='\0' || sscanf(line,"%f",&mat->me[i][j])<1 ); +#endif + fprintf(stderr,"Continue: "); + fscanf(fp,"%c",&c); + if ( c == 'n' || c == 'N' ) + { dynamic = FALSE; goto redo; } + if ( (c == 'b' || c == 'B') /* && i > 0 */ ) + { if ( i > 0 ) + i--; + dynamic = FALSE; goto redo; + } + } + + return (mat); +} + +/* bm_finput -- batch-file input of matrix */ +#ifndef ANSI_C +MAT *bm_finput(fp,mat) +FILE *fp; +MAT *mat; +#else +MAT *bm_finput(FILE *fp,MAT *mat) +#endif +{ + unsigned int i,j,m,n,dummy; + int io_code; + + /* get dimension */ + skipjunk(fp); + if ((io_code=fscanf(fp," Matrix: %u by %u",&m,&n)) < 2 || + m>MAXDIM || n>MAXDIM ) + error(io_code==EOF ? E_EOF : E_FORMAT,"bm_finput"); + + /* allocate memory if necessary */ + if ( mat==(MAT *)NULL ) + mat = m_resize(mat,m,n); + + /* get entries */ + for ( i=0; ime[i][j])) < 1 ) +#elif REAL == FLOAT + if ((io_code=fscanf(fp,"%f",&mat->me[i][j])) < 1 ) +#endif + error(io_code==EOF ? 7 : 6,"bm_finput"); + } + + return (mat); +} + +/* px_finput -- inputs permutation from file/stream fp + -- input from a terminal is handled interactively + -- batch/file input has the same format as produced by px_foutput + except that whitespace and comments ("#..\n") are skipped + -- returns px, which is created if px == NULL on entry */ +#ifndef ANSI_C +PERM *px_finput(fp,px) +FILE *fp; +PERM *px; +#else +PERM *px_finput(FILE *fp,PERM *px) +#endif +{ + PERM *ipx_finput(),*bpx_finput(); + + if ( isatty(fileno(fp)) ) + return ipx_finput(fp,px); + else + return bpx_finput(fp,px); +} + + +/* ipx_finput -- interactive input of permutation */ +#ifndef ANSI_C +PERM *ipx_finput(fp,px) +FILE *fp; +PERM *px; +#else +PERM *ipx_finput(FILE *fp,PERM *px) +#endif +{ + unsigned int i,j,size,dynamic; /* dynamic set if memory allocated here */ + unsigned int entry,ok; + + /* get permutation size */ + if ( px!=(PERM *)NULL && px->sizesize; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"Permutation: size: "); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"ipx_finput"); + } while ( sscanf(line,"%u",&size)<1 || size>MAXDIM ); + px = px_get(size); + } + + /* get entries */ + i = 0; + while ( i%u new: ", + i,px->pe[i]); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"ipx_finput"); + if ( (*line == 'b' || *line == 'B') && i > 0 ) + { i--; dynamic = FALSE; goto redo; } + } while ( *line=='\0' || sscanf(line,"%u",&entry) < 1 ); + /* check entry */ + ok = (entry < size); + for ( j=0; jpe[j]); + if ( ok ) + { + px->pe[i] = entry; + i++; + } + } + + return (px); +} + +/* bpx_finput -- batch-file input of permutation */ +#ifndef ANSI_C +PERM *bpx_finput(fp,px) +FILE *fp; +PERM *px; +#else +PERM *bpx_finput(FILE *fp,PERM *px) +#endif +{ + unsigned int i,j,size,entry,ok; + int io_code; + + /* get size of permutation */ + skipjunk(fp); + if ((io_code=fscanf(fp," Permutation: size:%u",&size)) < 1 || + size>MAXDIM ) + error(io_code==EOF ? 7 : 6,"bpx_finput"); + + /* allocate memory if necessary */ + if ( px==(PERM *)NULL || px->size %u",&entry)) < 1 ) + error(io_code==EOF ? 7 : 6,"bpx_finput"); + /* check entry */ + ok = (entry < size); + for ( j=0; jpe[j]); + if ( ok ) + { + px->pe[i] = entry; + i++; + } + else + error(E_BOUNDS,"bpx_finput"); + } + + return (px); +} + +/* v_finput -- inputs vector from file/stream fp + -- input from a terminal is handled interactively + -- batch/file input has the same format as produced by px_foutput + except that whitespace and comments ("#..\n") are skipped + -- returns x, which is created if x == NULL on entry */ +#ifndef ANSI_C +VEC *v_finput(fp,x) +FILE *fp; +VEC *x; +#else +VEC *v_finput(FILE *fp,VEC *x) +#endif +{ + VEC *ifin_vec(),*bfin_vec(); + + if ( isatty(fileno(fp)) ) + return ifin_vec(fp,x); + else + return bfin_vec(fp,x); +} + +/* ifin_vec -- interactive input of vector */ +#ifndef ANSI_C +VEC *ifin_vec(fp,vec) +FILE *fp; +VEC *vec; +#else +VEC *ifin_vec(FILE *fp,VEC *vec) +#endif +{ + unsigned int i,dim,dynamic; /* dynamic set if memory allocated here */ + + /* get vector dimension */ + if ( vec != (VEC *)NULL && vec->dimdim; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"Vector: dim: "); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"ifin_vec"); + } while ( sscanf(line,"%u",&dim)<1 || dim>MAXDIM ); + vec = v_get(dim); + } + + /* input elements */ + for ( i=0; ive[i]); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"ifin_vec"); + if ( (*line == 'b' || *line == 'B') && i > 0 ) + { i--; dynamic = FALSE; goto redo; } + if ( (*line == 'f' || *line == 'F') && i < dim-1 ) + { i++; dynamic = FALSE; goto redo; } +#if REAL == DOUBLE + } while ( *line=='\0' || sscanf(line,"%lf",&vec->ve[i]) < 1 ); +#elif REAL == FLOAT + } while ( *line=='\0' || sscanf(line,"%f",&vec->ve[i]) < 1 ); +#endif + + return (vec); +} + +/* bfin_vec -- batch-file input of vector */ +#ifndef ANSI_C +VEC *bfin_vec(fp,vec) +FILE *fp; +VEC *vec; +#else +VEC *bfin_vec(FILE *fp,VEC *vec) +#endif +{ + unsigned int i,dim; + int io_code; + + /* get dimension */ + skipjunk(fp); + if ((io_code=fscanf(fp," Vector: dim:%u",&dim)) < 1 || + dim>MAXDIM ) + error(io_code==EOF ? 7 : 6,"bfin_vec"); + + /* allocate memory if necessary */ + if ( vec==(VEC *)NULL ) + vec = v_resize(vec,dim); + + /* get entries */ + skipjunk(fp); + for ( i=0; ive[i])) < 1 ) +#elif REAL == FLOAT + if ((io_code=fscanf(fp,"%f",&vec->ve[i])) < 1 ) +#endif + error(io_code==EOF ? 7 : 6,"bfin_vec"); + + return (vec); +} + +/************************************************************************** + Output routines + **************************************************************************/ +static const char *format = "%14.9g "; + +/* setformat -- sets the printf format string for the Meschach I/O operations + -- returns the previous format string */ +#ifndef ANSI_C +char *setformat(f_string) +char *f_string; +#else +const char *setformat(const char *f_string) +#endif +{ + const char *old_f_string; + old_f_string = format; + if ( f_string != (char *)NULL && *f_string != '\0' ) + format = f_string; + + return old_f_string; +} + +/* m_foutput -- prints a representation of the matrix a onto file/stream fp */ +#ifndef ANSI_C +void m_foutput(fp,a) +FILE *fp; +MAT *a; +#else +void m_foutput(FILE *fp, const MAT *a) +#endif +{ + unsigned int i, j, tmp; + + if ( a == (MAT *)NULL ) + { fprintf(fp,"Matrix: NULL\n"); return; } + fprintf(fp,"Matrix: %d by %d\n",a->m,a->n); + if ( a->me == (Real **)NULL ) + { fprintf(fp,"NULL\n"); return; } + for ( i=0; im; i++ ) /* for each row... */ + { + fprintf(fp,"row %u: ",i); + for ( j=0, tmp=2; jn; j++, tmp++ ) + { /* for each col in row... */ + fprintf(fp,format,a->me[i][j]); + if ( ! (tmp % 5) ) putc('\n',fp); + } + if ( tmp % 5 != 1 ) putc('\n',fp); + } +} + +/* px_foutput -- prints a representation of px onto file/stream fp */ +#ifndef ANSI_C +void px_foutput(fp,px) +FILE *fp; +PERM *px; +#else +void px_foutput(FILE *fp, const PERM *px) +#endif +{ + unsigned int i; + + if ( px == (PERM *)NULL ) + { fprintf(fp,"Permutation: NULL\n"); return; } + fprintf(fp,"Permutation: size: %u\n",px->size); + if ( px->pe == (unsigned int *)NULL ) + { fprintf(fp,"NULL\n"); return; } + for ( i=0; isize; i++ ) + if ( ! (i % 8) && i != 0 ) + fprintf(fp,"\n %u->%u ",i,px->pe[i]); + else + fprintf(fp,"%u->%u ",i,px->pe[i]); + fprintf(fp,"\n"); +} + +/* v_foutput -- prints a representation of x onto file/stream fp */ +#ifndef ANSI_C +void v_foutput(fp,x) +FILE *fp; +VEC *x; +#else +void v_foutput(FILE *fp, const VEC *x) +#endif +{ + unsigned int i, tmp; + + if ( x == (VEC *)NULL ) + { fprintf(fp,"Vector: NULL\n"); return; } + fprintf(fp,"Vector: dim: %d\n",x->dim); + if ( x->ve == (Real *)NULL ) + { fprintf(fp,"NULL\n"); return; } + for ( i=0, tmp=0; idim; i++, tmp++ ) + { + fprintf(fp,format,x->ve[i]); + if ( tmp % 5 == 4 ) putc('\n',fp); + } + if ( tmp % 5 != 0 ) putc('\n',fp); +} + +/* m_dump -- prints a dump of all pointers and data in a onto fp + -- suitable for low-level debugging */ +#ifndef ANSI_C +void m_dump(fp,a) +FILE *fp; +MAT *a; +#else +void m_dump(FILE *fp, const MAT *a) +#endif +{ + unsigned int i, j, tmp; + + if ( a == (MAT *)NULL ) + { fprintf(fp,"Matrix: NULL\n"); return; } + fprintf(fp,"Matrix: %d by %d @ 0x%lx\n",a->m,a->n,(long)a); + fprintf(fp,"\tmax_m = %d, max_n = %d, max_size = %d\n", + a->max_m, a->max_n, a->max_size); + if ( a->me == (Real **)NULL ) + { fprintf(fp,"NULL\n"); return; } + fprintf(fp,"a->me @ 0x%lx\n",(long)(a->me)); + fprintf(fp,"a->base @ 0x%lx\n",(long)(a->base)); + for ( i=0; im; i++ ) /* for each row... */ + { + fprintf(fp,"row %u: @ 0x%lx ",i,(long)(a->me[i])); + for ( j=0, tmp=2; jn; j++, tmp++ ) + { /* for each col in row... */ + fprintf(fp,format,a->me[i][j]); + if ( ! (tmp % 5) ) putc('\n',fp); + } + if ( tmp % 5 != 1 ) putc('\n',fp); + } +} + +/* px_dump -- prints a dump of all pointers and data in a onto fp + -- suitable for low-level debugging */ +#ifndef ANSI_C +void px_dump(fp,px) +FILE *fp; +PERM *px; +#else +void px_dump(FILE *fp, const PERM *px) +#endif +{ + unsigned int i; + + if ( ! px ) + { fprintf(fp,"Permutation: NULL\n"); return; } + fprintf(fp,"Permutation: size: %u @ 0x%lx\n",px->size,(long)(px)); + if ( ! px->pe ) + { fprintf(fp,"NULL\n"); return; } + fprintf(fp,"px->pe @ 0x%lx\n",(long)(px->pe)); + for ( i=0; isize; i++ ) + fprintf(fp,"%u->%u ",i,px->pe[i]); + fprintf(fp,"\n"); +} + + +/* v_dump -- prints a dump of all pointers and data in a onto fp + -- suitable for low-level debugging */ +#ifndef ANSI_C +void v_dump(fp,x) +FILE *fp; +VEC *x; +#else +void v_dump(FILE *fp, const VEC *x) +#endif +{ + unsigned int i, tmp; + + if ( ! x ) + { fprintf(fp,"Vector: NULL\n"); return; } + fprintf(fp,"Vector: dim: %d @ 0x%lx\n",x->dim,(long)(x)); + if ( ! x->ve ) + { fprintf(fp,"NULL\n"); return; } + fprintf(fp,"x->ve @ 0x%lx\n",(long)(x->ve)); + for ( i=0, tmp=0; idim; i++, tmp++ ) + { + fprintf(fp,format,x->ve[i]); + if ( tmp % 5 == 4 ) putc('\n',fp); + } + if ( tmp % 5 != 0 ) putc('\n',fp); +} + + +/* iv_foutput -- print a representation of iv on stream fp */ +#ifndef ANSI_C +void iv_foutput(fp,iv) +FILE *fp; +IVEC *iv; +#else +void iv_foutput(FILE *fp, const IVEC *iv) +#endif +{ + int i; + + fprintf(fp,"IntVector: "); + if ( iv == IVNULL ) + { + fprintf(fp,"**** NULL ****\n"); + return; + } + fprintf(fp,"dim: %d\n",iv->dim); + for ( i = 0; i < iv->dim; i++ ) + { + if ( (i+1) % 8 ) + fprintf(fp,"%8d ",iv->ive[i]); + else + fprintf(fp,"%8d\n",iv->ive[i]); + } + if ( i % 8 ) + fprintf(fp,"\n"); +} + + +/* iv_finput -- input integer vector from stream fp + -- input from a terminal is handled interactively + -- batch/file input has the same format as produced by + iv_foutput except that whitespace and comments ("#...\n") + are skipped */ +#ifndef ANSI_C +IVEC *iv_finput(fp,x) +FILE *fp; +IVEC *x; +#else +IVEC *iv_finput(FILE *fp, IVEC *x) +#endif +{ + IVEC *iiv_finput(),*biv_finput(); + + if ( isatty(fileno(fp)) ) + return iiv_finput(fp,x); + else + return biv_finput(fp,x); +} + +/* iiv_finput -- interactive input of IVEC iv */ +#ifndef ANSI_C +IVEC *iiv_finput(fp,iv) +FILE *fp; +IVEC *iv; +#else +IVEC *iiv_finput(FILE *fp, IVEC *iv) +#endif +{ + unsigned int i,dim,dynamic; /* dynamic set if memory allocated here */ + + /* get dimension */ + if ( iv != (IVEC *)NULL && iv->dimdim; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"IntVector: dim: "); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"iiv_finput"); + } while ( sscanf(line,"%u",&dim)<1 || dim>MAXDIM ); + iv = iv_get(dim); + } + + /* input elements */ + for ( i=0; iive[i]); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"iiv_finput"); + if ( (*line == 'b' || *line == 'B') && i > 0 ) + { i--; dynamic = FALSE; goto redo; } + if ( (*line == 'f' || *line == 'F') && i < dim-1 ) + { i++; dynamic = FALSE; goto redo; } + } while ( *line=='\0' || sscanf(line,"%d",&iv->ive[i]) < 1 ); + + return (iv); +} + +/* biv_finput -- batch-file input of IVEC iv */ +#ifndef ANSI_C +IVEC *biv_finput(fp,iv) +FILE *fp; +IVEC *iv; +#else +IVEC *biv_finput(FILE *fp, IVEC *iv) +#endif +{ + unsigned int i,dim; + int io_code; + + /* get dimension */ + skipjunk(fp); + if ((io_code=fscanf(fp," IntVector: dim:%u",&dim)) < 1 || + dim>MAXDIM ) + error(io_code==EOF ? 7 : 6,"biv_finput"); + + /* allocate memory if necessary */ + if ( iv==(IVEC *)NULL || iv->dimive[i])) < 1 ) + error(io_code==EOF ? 7 : 6,"biv_finput"); + + return (iv); +} + +/* iv_dump -- dumps all the contents of IVEC iv onto stream fp */ +#ifndef ANSI_C +void iv_dump(fp,iv) +FILE*fp; +IVEC*iv; +#else +void iv_dump(FILE *fp, const IVEC *iv) +#endif +{ + int i; + + fprintf(fp,"IntVector: "); + if ( ! iv ) + { + fprintf(fp,"**** NULL ****\n"); + return; + } + fprintf(fp,"dim: %d, max_dim: %d\n",iv->dim,iv->max_dim); + fprintf(fp,"ive @ 0x%lx\n",(long)(iv->ive)); + for ( i = 0; i < iv->max_dim; i++ ) + { + if ( (i+1) % 8 ) + fprintf(fp,"%8d ",iv->ive[i]); + else + fprintf(fp,"%8d\n",iv->ive[i]); + } + if ( i % 8 ) + fprintf(fp,"\n"); +} + diff --git a/maxint b/maxint new file mode 100755 index 0000000000000000000000000000000000000000..9878dae388b3d6d0d6b39b7721ba1ccfa35b3bb8 GIT binary patch literal 8760 zcmeHN(Q8{(82@e?x430n3RM&>#Ib61((b{B4*HOmU3SMxZM#;ASk96(Z6iq$Af7;N0*0&Ufzb zJLfy+mXq`Khy90-kBV5GB5NHY5=FWGjL0VvLrvsG6bD7A@!^a1yY}SUY;6^*75*zC zPahm8HD%9CwRZ8|r{kb#jIjxZBS*ANsZx5S)a=;KS38Nx!2G%HLL6##Cs+$YrHZ9; zviPK_ov;5?gD;|c_}G6TtofSbBcEDKXA5Z;o!a?^G~XFbK+L#5kptsP6-#a=zo0v` z^Ig?^{v3&e(!vdcQsw*ynf#o}+`1lfnr~c_5FaK=r5Dw_o5-abz1qijL-TPD zQHZhEo+{iY*RX&}T^ODk4s^qQXxS(JehKUo^7?U5s^BgyU|ecB;bM88#@FY&0MB9L zQYxQS#noJLDXR)4_W)m?9-luf;vgUQM{q5a$|eru8*Jkv4)XE4@aM`YD3w~u<(BfS zQ`+b2Xug$J$)Id+JNgrUOF zFF^Yei+LuAL$9EbG@ktxk>jXuK^LG|A4j2By3iLngYy7vk?VNh|2BgL{8^9~3cu@t za?u^gW|9MQtJyhV%1bC5#~&xYEY~N7_CC9FcH(v_(tQSP2qhdJ^U51OW*Y?iX^rpQ zqJx0Y&manIUZ^_1K+S6UhW{(8#Zo%gKhlqJWRfsLUPYn58?nY*U)T66V9Hq(+KJ=P zMoa`u1WW`>1WW`>1WW|}ZxMK3oa%2*<<}i&{iCq6QI1ykD_>hT?{zxXUrzP*gOF3X z8Fnh?rTjN*+dNlQH@8zzyEVwP_xhjFO?%fu+k@xV?cJ)qgXc!bW-uySR@L4GuI$Oj z_tx#5bKg4~&rQSPRDY~~cWrCC2lY*RkDb@;y{i3a-G1a$zKza)Q>*uez*_G;LT(w| z=y?b=e5Ky|Gjwf{jrV`A*XxTM*8MxE_0Aph&Z{re1_^4O1Nr;(Eoc`0wxqDmGi?MX z#qP#w(TW2@Jin}T^8v9woD^#%YDFVQ!!=mnL>qnVJ%)40EIUy+a5)+Mv?E076Tvev zE&lI=aU3RzXSBYmHJVyvRR6AfN9z`&0VV<_0ww|`0ww|`0ww|`0ww|`0ww|`0ww|` z0{^K9be)#zkx7xRIFnyqGF&B*A4c+e!tJYxJJ=Oh>6J`LP>-WtKr*^C52U3-Nu*dx zxFxwPAtkTn5}CY=kIf9b3o@O~FK1jNB^RV4w+Nbas$5DVIi4W@MK490XX-f1tB_8q z_26*}_b(kOnO&A-r) 0 ) + { + old_i = i; + i = (i << 1) | 1; + } + printf("%d\n", old_i); +} diff --git a/meminfo.c b/meminfo.c new file mode 100644 index 0000000..39d2495 --- /dev/null +++ b/meminfo.c @@ -0,0 +1,442 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* meminfo.c revised 22/11/93 */ + +/* + contains basic functions, types and arrays + to keep track of memory allocation/deallocation +*/ + +#include +#include "matrix.h" +#include "meminfo.h" +#ifdef COMPLEX +#include "zmatrix.h" +#endif +#ifdef SPARSE +#include "sparse.h" +#include "iter.h" +#endif + +static char rcsid[] = "$Id: meminfo.c,v 1.1 1994/01/13 05:31:39 des Exp $"; + +/* this array is defined further in this file */ +extern MEM_CONNECT mem_connect[MEM_CONNECT_MAX_LISTS]; + + +/* names of types */ +static char *mem_type_names[] = { + "MAT", + "BAND", + "PERM", + "VEC", + "IVEC" +#ifdef SPARSE + ,"ITER", + "SPROW", + "SPMAT" +#endif +#ifdef COMPLEX + ,"ZVEC", + "ZMAT" +#endif + }; + + +#define MEM_NUM_STD_TYPES (sizeof(mem_type_names)/sizeof(mem_type_names[0])) + + +/* local array for keeping track of memory */ +static MEM_ARRAY mem_info_sum[MEM_NUM_STD_TYPES]; + + +/* for freeing various types */ +static int (*mem_free_funcs[MEM_NUM_STD_TYPES])() = { + m_free, + bd_free, + px_free, + v_free, + iv_free +#ifdef SPARSE + ,iter_free, + sprow_free, + sp_free +#endif +#ifdef COMPLEX + ,zv_free, + zm_free +#endif + }; + + + +/* it is a global variable for passing + pointers to local arrays defined here */ +MEM_CONNECT mem_connect[MEM_CONNECT_MAX_LISTS] = { + { mem_type_names, mem_free_funcs, MEM_NUM_STD_TYPES, + mem_info_sum } +}; + + +/* attach a new list of types */ +#ifndef ANSI_C +int mem_attach_list(list, ntypes, type_names, free_funcs, info_sum) +int list,ntypes; /* number of a list and number of types there */ +char *type_names[]; /* list of names of types */ +int (*free_funcs[])(); /* list of releasing functions */ +MEM_ARRAY info_sum[]; /* local table */ +#else +int mem_attach_list(int list, int ntypes, + char *type_names[], + int (*free_funcs[])(void *), + MEM_ARRAY info_sum[]) +#endif +{ + if (list < 0 || list >= MEM_CONNECT_MAX_LISTS) + return -1; + + if (type_names == NULL || free_funcs == NULL + || info_sum == NULL || ntypes < 0) + return -1; + + /* if a list exists do not overwrite */ + if ( mem_connect[list].ntypes != 0 ) + error(E_OVERWRITE,"mem_attach_list"); + + mem_connect[list].ntypes = ntypes; + mem_connect[list].type_names = type_names; + mem_connect[list].free_funcs = free_funcs; + mem_connect[list].info_sum = info_sum; + return 0; +} + + +/* release a list of types */ +#ifndef ANSI_C +int mem_free_vars(list) +int list; +#else +int mem_free_vars(int list) +#endif +{ + if (list < 0 || list >= MEM_CONNECT_MAX_LISTS) + return -1; + + mem_connect[list].ntypes = 0; + mem_connect[list].type_names = NULL; + mem_connect[list].free_funcs = NULL; + mem_connect[list].info_sum = NULL; + + return 0; +} + + + +/* check if list is attached */ +#ifndef ANSI_C +int mem_is_list_attached(list) +int list; +#else +int mem_is_list_attached(int list) +#endif +{ + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return FALSE; + + if ( mem_connect[list].type_names != NULL && + mem_connect[list].free_funcs != NULL && + mem_connect[list].info_sum != NULL) + return TRUE; + else return FALSE; +} + +/* to print out the contents of mem_connect[list] */ +#ifndef MEX + +#ifndef ANSI_C +void mem_dump_list(fp,list) +FILE *fp; +int list; +#else +void mem_dump_list(FILE *fp, int list) +#endif +{ + int i; + MEM_CONNECT *mlist; + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return; + + mlist = &mem_connect[list]; + fprintf(fp," %15s[%d]:\n","CONTENTS OF mem_connect",list); + fprintf(fp," %-7s %-12s %-9s %s\n", + "name of", + "alloc.", "# alloc.", + "address" + ); + fprintf(fp," %-7s %-12s %-9s %s\n", + " type", + "bytes", "variables", + "of *_free()" + ); + + for (i=0; i < mlist->ntypes; i++) + fprintf(fp," %-7s %-12ld %-9d %p\n", + mlist->type_names[i], mlist->info_sum[i].bytes, + mlist->info_sum[i].numvar, mlist->free_funcs[i] + ); + + fprintf(fp,"\n"); +} +#endif /* MEX */ + + + +/*=============================================================*/ + + +/* local variables */ + +static int mem_switched_on = MEM_SWITCH_ON_DEF; /* on/off */ + + +/* switch on/off memory info */ +#ifndef ANSI_C +int mem_info_on(sw) +int sw; +#else +int mem_info_on(int sw) +#endif +{ + int old = mem_switched_on; + + mem_switched_on = sw; + return old; +} + +#ifdef ANSI_C +int mem_info_is_on(void) +#else +int mem_info_is_on() +#endif +{ + return mem_switched_on; +} + + +/* information about allocated memory */ + +/* return the number of allocated bytes for type 'type' */ +#ifndef ANSI_C +long mem_info_bytes(type,list) +int type,list; +#else +long mem_info_bytes(int type, int list) +#endif +{ + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return 0l; + if ( !mem_switched_on || type < 0 + || type >= mem_connect[list].ntypes + || mem_connect[list].free_funcs[type] == NULL ) + return 0l; + + return mem_connect[list].info_sum[type].bytes; +} + +/* return the number of allocated variables for type 'type' */ +#ifndef ANSI_C +int mem_info_numvar(type,list) +int type,list; +#else +int mem_info_numvar(int type, int list) +#endif +{ + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return 0l; + if ( !mem_switched_on || type < 0 + || type >= mem_connect[list].ntypes + || mem_connect[list].free_funcs[type] == NULL ) + return 0l; + + return mem_connect[list].info_sum[type].numvar; +} + + +#ifndef MEX + +/* print out memory info to the file fp */ +#ifndef ANSI_C +void mem_info_file(fp,list) +FILE *fp; +int list; +#else +void mem_info_file(FILE *fp, int list) +#endif +{ + unsigned int type; + long t = 0l, d; + int n = 0, nt = 0; + MEM_CONNECT *mlist; + + if (!mem_switched_on) return; + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return; + + if (list == 0) + fprintf(fp," MEMORY INFORMATION (standard types):\n"); + else + fprintf(fp," MEMORY INFORMATION (list no. %d):\n",list); + + mlist = &mem_connect[list]; + + for (type=0; type < mlist->ntypes; type++) { + if (mlist->type_names[type] == NULL ) continue; + d = mlist->info_sum[type].bytes; + t += d; + n = mlist->info_sum[type].numvar; + nt += n; + fprintf(fp," type %-7s %10ld alloc. byte%c %6d alloc. variable%c\n", + mlist->type_names[type], d, (d!=1 ? 's' : ' '), + n, (n!=1 ? 's' : ' ')); + } + + fprintf(fp," %-12s %10ld alloc. byte%c %6d alloc. variable%c\n\n", + "total:",t, (t!=1 ? 's' : ' '), + nt, (nt!=1 ? 's' : ' ')); +} +#endif + + +/* function for memory information */ + + +/* mem_bytes_list + + Arguments: + type - the number of type; + old_size - old size of allocated memory (in bytes); + new_size - new size of allocated memory (in bytes); + list - list of types + */ +#ifndef ANSI_C +void mem_bytes_list(type,old_size,new_size,list) +int type,list; +int old_size,new_size; +#else +void mem_bytes_list(int type, int old_size, int new_size, int list) +#endif +{ + MEM_CONNECT *mlist; + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return; + + mlist = &mem_connect[list]; + if ( type < 0 || type >= mlist->ntypes + || mlist->free_funcs[type] == NULL ) + return; + + if ( old_size < 0 || new_size < 0 ) + error(E_NEG,"mem_bytes_list"); + + mlist->info_sum[type].bytes += new_size - old_size; + + /* check if the number of bytes is non-negative */ + if ( old_size > 0 ) { + + if (mlist->info_sum[type].bytes < 0) + { +#ifndef MEX + fprintf(stderr, + "\n WARNING !! memory info: allocated memory is less than 0\n"); + fprintf(stderr,"\t TYPE %s \n\n", mlist->type_names[type]); + + if ( !isatty(fileno(stdout)) ) { + fprintf(stdout, + "\n WARNING !! memory info: allocated memory is less than 0\n"); + fprintf(stdout,"\t TYPE %s \n\n", mlist->type_names[type]); + } +#else + mexPrintf("\n WARNING !! memory info: allocated memory < 0\n"); + mexPrintf("\t TYPE %s \n\n", mlist->type_names[type]); +#endif + } + } +} + + + +/* mem_numvar_list + + Arguments: + type - the number of type; + num - # of variables allocated (> 0) or deallocated ( < 0) + list - list of types + */ + +#ifndef ANSI_C +void mem_numvar_list(type,num,list) +int type,list,num; +#else +void mem_numvar_list(int type, int num, int list) +#endif +{ + MEM_CONNECT *mlist; + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return; + + mlist = &mem_connect[list]; + if ( type < 0 || type >= mlist->ntypes + || mlist->free_funcs[type] == NULL ) + return; + + mlist->info_sum[type].numvar += num; + + /* check if the number of variables is non-negative */ + if ( num < 0 ) { + + if (mlist->info_sum[type].numvar < 0) + { +#ifndef MEX + fprintf(stderr, + "\n WARNING !! memory info: allocated # of variables is less than 0\n"); + fprintf(stderr,"\t TYPE %s \n\n", mlist->type_names[type]); + if ( !isatty(fileno(stdout)) ) { + fprintf(stdout, + "\n WARNING !! memory info: allocated # of variables is less than 0\n"); + fprintf(stdout,"\t TYPE %s \n\n", mlist->type_names[type]); + } +#else + mexPrintf("\n WARNING !! memory info: allocated # of variables < 0\n"); + mexPrintf(stderr,"\t TYPE %s \n\n", mlist->type_names[type]); +#endif + } + } +} + diff --git a/meminfo.h b/meminfo.h new file mode 100644 index 0000000..9561eff --- /dev/null +++ b/meminfo.h @@ -0,0 +1,164 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* meminfo.h 26/08/93 */ +/* changed 11/12/93 */ + + +#ifndef MEM_INFOH +#define MEM_INFOH + + + +/* for hash table in mem_stat.c */ +/* Note: the hash size should be a prime, or at very least odd */ +#define MEM_HASHSIZE 509 +#define MEM_HASHSIZE_FILE "meminfo.h" + + +/* default: memory information is off */ +/* set it to 1 if you want it all the time */ +#define MEM_SWITCH_ON_DEF 0 + + +/* available standard types */ +#define TYPE_NULL (-1) +#define TYPE_MAT 0 +#define TYPE_BAND 1 +#define TYPE_PERM 2 +#define TYPE_VEC 3 +#define TYPE_IVEC 4 + +#ifdef SPARSE +#define TYPE_ITER 5 +#define TYPE_SPROW 6 +#define TYPE_SPMAT 7 +#endif + +#ifdef COMPLEX +#ifdef SPARSE +#define TYPE_ZVEC 8 +#define TYPE_ZMAT 9 +#else +#define TYPE_ZVEC 5 +#define TYPE_ZMAT 6 +#endif +#endif + +/* structure for memory information */ +typedef struct { + long bytes; /* # of allocated bytes for each type (summary) */ + int numvar; /* # of allocated variables for each type */ +} MEM_ARRAY; + + + +#ifdef ANSI_C + +int mem_info_is_on(void); +int mem_info_on(int sw); + +long mem_info_bytes(int type,int list); +int mem_info_numvar(int type,int list); +void mem_info_file(FILE * fp,int list); + +void mem_bytes_list(int type,int old_size,int new_size, + int list); +void mem_numvar_list(int type, int num, int list); + +#ifndef THREADSAFE +int mem_stat_reg_list(void **var,int type,int list,char *fname,int line); +int mem_stat_mark(int mark); +int mem_stat_free_list(int mark,int list); +int mem_stat_show_mark(void); +void mem_stat_dump(FILE *fp,int list); +int mem_attach_list(int list,int ntypes,char *type_names[], + int (*free_funcs[])(), MEM_ARRAY info_sum[]); +int mem_free_vars(int list); +int mem_is_list_attached(int list); +void mem_dump_list(FILE *fp,int list); +int mem_stat_reg_vars(int list,int type,char *fname,int line,...); +#endif /* THREADSAFE */ +#else +int mem_info_is_on(); +int mem_info_on(); + +long mem_info_bytes(); +int mem_info_numvar(); +void mem_info_file(); + +void mem_bytes_list(); +void mem_numvar_list(); + +#ifndef THREADSAFE +int mem_stat_reg_list(); +int mem_stat_mark(); +int mem_stat_free_list(); +int mem_stat_show_mark(); +void mem_stat_dump(); +int mem_attach_list(); +int mem_free_vars(); +int mem_is_list_attached(); +void mem_dump_list(); +int mem_stat_reg_vars(); +#endif /* THREADSAFE */ + +#endif + +/* macros */ + +#define mem_info() mem_info_file(stdout,0) + +#ifndef THREADSAFE +#define mem_stat_reg(var,type) mem_stat_reg_list((void **)var,type,0,__FILE__,__LINE__) +#define MEM_STAT_REG(var,type) mem_stat_reg_list((void **)&(var),type,0,__FILE__,__LINE__) +#define mem_stat_free(mark) mem_stat_free_list(mark,0) +#else +#define mem_stat_reg(var,type) +#define MEM_STAT_REG(var,type) +#define mem_stat_free(mark) +#endif + +#define mem_bytes(type,old_size,new_size) \ + mem_bytes_list(type,old_size,new_size,0) + +#define mem_numvar(type,num) mem_numvar_list(type,num,0) + + +/* internal type */ + +typedef struct { + char **type_names; /* array of names of types (strings) */ + int (**free_funcs)(); /* array of functions for releasing types */ + unsigned ntypes; /* max number of types */ + MEM_ARRAY *info_sum; /* local array for keeping track of memory */ +} MEM_CONNECT; + +/* max number of lists of types */ +#define MEM_CONNECT_MAX_LISTS 5 + + +#endif diff --git a/memory.c b/memory.c new file mode 100644 index 0000000..89cdc73 --- /dev/null +++ b/memory.c @@ -0,0 +1,1043 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* memory.c 1.3 11/25/87 */ + +#include "matrix.h" + + +static char rcsid[] = "$Id: memory.c,v 1.13 1994/04/05 02:10:37 des Exp $"; + +/* m_get -- gets an mxn matrix (in MAT form) by dynamic memory allocation + -- normally ALL matrices should be obtained this way + -- if either m or n is negative this will raise an error + -- note that 0 x n and m x 0 matrices can be created */ +#ifndef ANSI_C +MAT *m_get(m,n) +int m,n; +#else +MAT *m_get(int m, int n) +#endif +{ + MAT *matrix; + int i; + + if (m < 0 || n < 0) + error(E_NEG,"m_get"); + + if ((matrix=NEW(MAT)) == (MAT *)NULL ) + error(E_MEM,"m_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,sizeof(MAT)); + mem_numvar(TYPE_MAT,1); + } + + matrix->m = m; matrix->n = matrix->max_n = n; + matrix->max_m = m; matrix->max_size = m*n; +#ifndef SEGMENTED + if ((matrix->base = NEW_A(m*n,Real)) == (Real *)NULL ) + { + free(matrix); + error(E_MEM,"m_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,m*n*sizeof(Real)); + } +#else + matrix->base = (Real *)NULL; +#endif + if ((matrix->me = (Real **)calloc(m,sizeof(Real *))) == + (Real **)NULL ) + { free(matrix->base); free(matrix); + error(E_MEM,"m_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,m*sizeof(Real *)); + } + +#ifndef SEGMENTED + /* set up pointers */ + for ( i=0; ime[i] = &(matrix->base[i*n]); +#else + for ( i = 0; i < m; i++ ) + if ( (matrix->me[i]=NEW_A(n,Real)) == (Real *)NULL ) + error(E_MEM,"m_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,n*sizeof(Real)); + } +#endif + + return (matrix); +} + + +/* px_get -- gets a PERM of given 'size' by dynamic memory allocation + -- Note: initialized to the identity permutation + -- the permutation is on the set {0,1,2,...,size-1} */ +#ifndef ANSI_C +PERM *px_get(size) +int size; +#else +PERM *px_get(int size) +#endif +{ + PERM *permute; + int i; + + if (size < 0) + error(E_NEG,"px_get"); + + if ((permute=NEW(PERM)) == (PERM *)NULL ) + error(E_MEM,"px_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_PERM,0,sizeof(PERM)); + mem_numvar(TYPE_PERM,1); + } + + permute->size = permute->max_size = size; + if ((permute->pe = NEW_A(size,unsigned int)) == (unsigned int *)NULL ) + error(E_MEM,"px_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_PERM,0,size*sizeof(unsigned int)); + } + + for ( i=0; ipe[i] = i; + + return (permute); +} + +/* v_get -- gets a VEC of dimension 'size' + -- Note: initialized to zero */ +#ifndef ANSI_C +VEC *v_get(size) +int size; +#else +VEC *v_get(int size) +#endif +{ + VEC *vector; + + if (size < 0) + error(E_NEG,"v_get"); + + if ((vector=NEW(VEC)) == (VEC *)NULL ) + error(E_MEM,"v_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,0,sizeof(VEC)); + mem_numvar(TYPE_VEC,1); + } + + vector->dim = vector->max_dim = size; + if ((vector->ve=NEW_A(size,Real)) == (Real *)NULL ) + { + free(vector); + error(E_MEM,"v_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,0,size*sizeof(Real)); + } + + return (vector); +} + +/* m_free -- returns MAT & asoociated memory back to memory heap */ +#ifndef ANSI_C +int m_free(mat) +MAT *mat; +#else +int m_free(MAT *mat) +#endif +{ +#ifdef SEGMENTED + int i; +#endif + + if ( mat==(MAT *)NULL || (int)(mat->m) < 0 || + (int)(mat->n) < 0 ) + /* don't trust it */ + return (-1); + +#ifndef SEGMENTED + if ( mat->base != (Real *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,mat->max_m*mat->max_n*sizeof(Real),0); + } + free((char *)(mat->base)); + } +#else + for ( i = 0; i < mat->max_m; i++ ) + if ( mat->me[i] != (Real *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,mat->max_n*sizeof(Real),0); + } + free((char *)(mat->me[i])); + } +#endif + if ( mat->me != (Real **)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,mat->max_m*sizeof(Real *),0); + } + free((char *)(mat->me)); + } + + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,sizeof(MAT),0); + mem_numvar(TYPE_MAT,-1); + } + free((char *)mat); + + return (0); +} + + + +/* px_free -- returns PERM & asoociated memory back to memory heap */ +#ifndef ANSI_C +int px_free(px) +PERM *px; +#else +int px_free(PERM *px) +#endif +{ + if ( px==(PERM *)NULL || (int)(px->size) < 0 ) + /* don't trust it */ + return (-1); + + if ( px->pe == (unsigned int *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_PERM,sizeof(PERM),0); + mem_numvar(TYPE_PERM,-1); + } + free((char *)px); + } + else + { + if (mem_info_is_on()) { + mem_bytes(TYPE_PERM,sizeof(PERM)+px->max_size*sizeof(unsigned int),0); + mem_numvar(TYPE_PERM,-1); + } + free((char *)px->pe); + free((char *)px); + } + + return (0); +} + + + +/* v_free -- returns VEC & asoociated memory back to memory heap */ +#ifndef ANSI_C +int v_free(vec) +VEC *vec; +#else +int v_free(VEC *vec) +#endif +{ + if ( vec==(VEC *)NULL || (int)(vec->dim) < 0 ) + /* don't trust it */ + return (-1); + + if ( vec->ve == (Real *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,sizeof(VEC),0); + mem_numvar(TYPE_VEC,-1); + } + free((char *)vec); + } + else + { + if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,sizeof(VEC)+vec->max_dim*sizeof(Real),0); + mem_numvar(TYPE_VEC,-1); + } + free((char *)vec->ve); + free((char *)vec); + } + + return (0); +} + + + +/* m_resize -- returns the matrix A of size new_m x new_n; A is zeroed + -- if A == NULL on entry then the effect is equivalent to m_get() */ +#ifndef ANSI_C +MAT *m_resize(A,new_m,new_n) +MAT *A; +int new_m, new_n; +#else +MAT *m_resize(MAT *A,int new_m, int new_n) +#endif +{ + int i; + int new_max_m, new_max_n, new_size, old_m, old_n; + + if (new_m < 0 || new_n < 0) + error(E_NEG,"m_resize"); + + if ( ! A ) + return m_get(new_m,new_n); + + /* nothing was changed */ + if (new_m == A->m && new_n == A->n) + return A; + + old_m = A->m; old_n = A->n; + if ( new_m > A->max_m ) + { /* re-allocate A->me */ + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,A->max_m*sizeof(Real *), + new_m*sizeof(Real *)); + } + + A->me = RENEW(A->me,new_m,Real *); + if ( ! A->me ) + error(E_MEM,"m_resize"); + } + new_max_m = max(new_m,A->max_m); + new_max_n = max(new_n,A->max_n); + +#ifndef SEGMENTED + new_size = new_max_m*new_max_n; + if ( new_size > A->max_size ) + { /* re-allocate A->base */ + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,A->max_m*A->max_n*sizeof(Real), + new_size*sizeof(Real)); + } + + A->base = RENEW(A->base,new_size,Real); + if ( ! A->base ) + error(E_MEM,"m_resize"); + A->max_size = new_size; + } + + /* now set up A->me[i] */ + for ( i = 0; i < new_m; i++ ) + A->me[i] = &(A->base[i*new_n]); + + /* now shift data in matrix */ + if ( old_n > new_n ) + { + for ( i = 1; i < min(old_m,new_m); i++ ) + MEM_COPY((char *)&(A->base[i*old_n]), + (char *)&(A->base[i*new_n]), + sizeof(Real)*new_n); + } + else if ( old_n < new_n ) + { + for ( i = (int)(min(old_m,new_m))-1; i > 0; i-- ) + { /* copy & then zero extra space */ + MEM_COPY((char *)&(A->base[i*old_n]), + (char *)&(A->base[i*new_n]), + sizeof(Real)*old_n); + __zero__(&(A->base[i*new_n+old_n]),(new_n-old_n)); + } + __zero__(&(A->base[old_n]),(new_n-old_n)); + A->max_n = new_n; + } + /* zero out the new rows.. */ + for ( i = old_m; i < new_m; i++ ) + __zero__(&(A->base[i*new_n]),new_n); +#else + if ( A->max_n < new_n ) + { + Real *tmp; + + for ( i = 0; i < A->max_m; i++ ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,A->max_n*sizeof(Real), + new_max_n*sizeof(Real)); + } + + if ( (tmp = RENEW(A->me[i],new_max_n,Real)) == NULL ) + error(E_MEM,"m_resize"); + else { + A->me[i] = tmp; + } + } + for ( i = A->max_m; i < new_max_m; i++ ) + { + if ( (tmp = NEW_A(new_max_n,Real)) == NULL ) + error(E_MEM,"m_resize"); + else { + A->me[i] = tmp; + + if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real)); + } + } + } + } + else if ( A->max_m < new_m ) + { + for ( i = A->max_m; i < new_m; i++ ) + if ( (A->me[i] = NEW_A(new_max_n,Real)) == NULL ) + error(E_MEM,"m_resize"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real)); + } + + } + + if ( old_n < new_n ) + { + for ( i = 0; i < old_m; i++ ) + __zero__(&(A->me[i][old_n]),new_n-old_n); + } + + /* zero out the new rows.. */ + for ( i = old_m; i < new_m; i++ ) + __zero__(A->me[i],new_n); +#endif + + A->max_m = new_max_m; + A->max_n = new_max_n; + A->max_size = A->max_m*A->max_n; + A->m = new_m; A->n = new_n; + + return A; +} + +/* px_resize -- returns the permutation px with size new_size + -- px is set to the identity permutation */ +#ifndef ANSI_C +PERM *px_resize(px,new_size) +PERM *px; +int new_size; +#else +PERM *px_resize(PERM *px, int new_size) +#endif +{ + int i; + + if (new_size < 0) + error(E_NEG,"px_resize"); + + if ( ! px ) + return px_get(new_size); + + /* nothing is changed */ + if (new_size == px->size) + return px; + + if ( new_size > px->max_size ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_PERM,px->max_size*sizeof(unsigned int), + new_size*sizeof(unsigned int)); + } + px->pe = RENEW(px->pe,new_size,unsigned int); + if ( ! px->pe ) + error(E_MEM,"px_resize"); + px->max_size = new_size; + } + if ( px->size <= new_size ) + /* extend permutation */ + for ( i = px->size; i < new_size; i++ ) + px->pe[i] = i; + else + for ( i = 0; i < new_size; i++ ) + px->pe[i] = i; + + px->size = new_size; + + return px; +} + +/* v_resize -- returns the vector x with dim new_dim + -- x is set to the zero vector */ +#ifndef ANSI_C +VEC *v_resize(x,new_dim) +VEC *x; +int new_dim; +#else +VEC *v_resize(VEC *x, int new_dim) +#endif +{ + + if (new_dim < 0) + error(E_NEG,"v_resize"); + + if ( ! x ) + return v_get(new_dim); + + /* nothing is changed */ + if (new_dim == x->dim) + return x; + + if ( x->max_dim == 0 ) /* assume that it's from sub_vec */ + return v_get(new_dim); + + if ( new_dim > x->max_dim ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,x->max_dim*sizeof(Real), + new_dim*sizeof(Real)); + } + + x->ve = RENEW(x->ve,new_dim,Real); + if ( ! x->ve ) + error(E_MEM,"v_resize"); + x->max_dim = new_dim; + } + + if ( new_dim > x->dim ) + __zero__(&(x->ve[x->dim]),new_dim - x->dim); + x->dim = new_dim; + + return x; +} + + + + +/* Varying number of arguments */ +/* other functions of this type are in sparse.c and zmemory.c */ + + + +#ifdef ANSI_C + + +/* To allocate memory to many arguments. + The function should be called: + v_get_vars(dim,&x,&y,&z,...,NULL); + where + int dim; + VEC *x, *y, *z,...; + The last argument should be NULL ! + dim is the length of vectors x,y,z,... + returned value is equal to the number of allocated variables + Other gec_... functions are similar. +*/ + +int v_get_vars(int dim,...) +{ + va_list ap; + int i=0; + VEC **par; + + va_start(ap, dim); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + *par = v_get(dim); + i++; + } + + va_end(ap); + return i; +} + + +int iv_get_vars(int dim,...) +{ + va_list ap; + int i=0; + IVEC **par; + + va_start(ap, dim); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + *par = iv_get(dim); + i++; + } + + va_end(ap); + return i; +} + +int m_get_vars(int m,int n,...) +{ + va_list ap; + int i=0; + MAT **par; + + va_start(ap, n); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + *par = m_get(m,n); + i++; + } + + va_end(ap); + return i; +} + +int px_get_vars(int dim,...) +{ + va_list ap; + int i=0; + PERM **par; + + va_start(ap, dim); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + *par = px_get(dim); + i++; + } + + va_end(ap); + return i; +} + + + +/* To resize memory for many arguments. + The function should be called: + v_resize_vars(new_dim,&x,&y,&z,...,NULL); + where + int new_dim; + VEC *x, *y, *z,...; + The last argument should be NULL ! + rdim is the resized length of vectors x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. + Other *_resize_list() functions are similar. +*/ + +int v_resize_vars(int new_dim,...) +{ + va_list ap; + int i=0; + VEC **par; + + va_start(ap, new_dim); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + *par = v_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + + + +int iv_resize_vars(int new_dim,...) +{ + va_list ap; + int i=0; + IVEC **par; + + va_start(ap, new_dim); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + *par = iv_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + +int m_resize_vars(int m,int n,...) +{ + va_list ap; + int i=0; + MAT **par; + + va_start(ap, n); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + *par = m_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + + +int px_resize_vars(int new_dim,...) +{ + va_list ap; + int i=0; + PERM **par; + + va_start(ap, new_dim); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + *par = px_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + +/* To deallocate memory for many arguments. + The function should be called: + v_free_vars(&x,&y,&z,...,NULL); + where + VEC *x, *y, *z,...; + The last argument should be NULL ! + There must be at least one not NULL argument. + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. + Other *_free_list() functions are similar. +*/ + + +int v_free_vars(VEC **pv,...) +{ + va_list ap; + int i=1; + VEC **par; + + v_free(*pv); + *pv = VNULL; + va_start(ap, pv); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + v_free(*par); + *par = VNULL; + i++; + } + + va_end(ap); + return i; +} + + +int iv_free_vars(IVEC **ipv,...) +{ + va_list ap; + int i=1; + IVEC **par; + + iv_free(*ipv); + *ipv = IVNULL; + va_start(ap, ipv); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + iv_free(*par); + *par = IVNULL; + i++; + } + + va_end(ap); + return i; +} + + +int px_free_vars(PERM **vpx,...) +{ + va_list ap; + int i=1; + PERM **par; + + px_free(*vpx); + *vpx = PNULL; + va_start(ap, vpx); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + px_free(*par); + *par = PNULL; + i++; + } + + va_end(ap); + return i; +} + +int m_free_vars(MAT **va,...) +{ + va_list ap; + int i=1; + MAT **par; + + m_free(*va); + *va = MNULL; + va_start(ap, va); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + m_free(*par); + *par = MNULL; + i++; + } + + va_end(ap); + return i; +} + + +#elif VARARGS +/* old varargs is used */ + + + +/* To allocate memory to many arguments. + The function should be called: + v_get_vars(dim,&x,&y,&z,...,VNULL); + where + int dim; + VEC *x, *y, *z,...; + The last argument should be VNULL ! + dim is the length of vectors x,y,z,... +*/ + +int v_get_vars(va_alist) va_dcl +{ + va_list ap; + int dim,i=0; + VEC **par; + + va_start(ap); + dim = va_arg(ap,int); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + *par = v_get(dim); + i++; + } + + va_end(ap); + return i; +} + + +int iv_get_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, dim; + IVEC **par; + + va_start(ap); + dim = va_arg(ap,int); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + *par = iv_get(dim); + i++; + } + + va_end(ap); + return i; +} + +int m_get_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, n, m; + MAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + *par = m_get(m,n); + i++; + } + + va_end(ap); + return i; +} + + + +int px_get_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, dim; + PERM **par; + + va_start(ap); + dim = va_arg(ap,int); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + *par = px_get(dim); + i++; + } + + va_end(ap); + return i; +} + + + +/* To resize memory for many arguments. + The function should be called: + v_resize_vars(new_dim,&x,&y,&z,...,NULL); + where + int new_dim; + VEC *x, *y, *z,...; + The last argument should be NULL ! + rdim is the resized length of vectors x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. + Other *_resize_list() functions are similar. +*/ + +int v_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, new_dim; + VEC **par; + + va_start(ap); + new_dim = va_arg(ap,int); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + *par = v_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + + + +int iv_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, new_dim; + IVEC **par; + + va_start(ap); + new_dim = va_arg(ap,int); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + *par = iv_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + +int m_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, m, n; + MAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + *par = m_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + +int px_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, new_dim; + PERM **par; + + va_start(ap); + new_dim = va_arg(ap,int); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + *par = px_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + + +/* To deallocate memory for many arguments. + The function should be called: + v_free_vars(&x,&y,&z,...,NULL); + where + VEC *x, *y, *z,...; + The last argument should be NULL ! + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. + Other *_free_list() functions are similar. +*/ + + +int v_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + VEC **par; + + va_start(ap); + while (par = va_arg(ap,VEC **)) { /* NULL ends the list*/ + v_free(*par); + *par = VNULL; + i++; + } + + va_end(ap); + return i; +} + + + +int iv_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + IVEC **par; + + va_start(ap); + while (par = va_arg(ap,IVEC **)) { /* NULL ends the list*/ + iv_free(*par); + *par = IVNULL; + i++; + } + + va_end(ap); + return i; +} + + +int px_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + PERM **par; + + va_start(ap); + while (par = va_arg(ap,PERM **)) { /* NULL ends the list*/ + px_free(*par); + *par = PNULL; + i++; + } + + va_end(ap); + return i; +} + +int m_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + MAT **par; + + va_start(ap); + while (par = va_arg(ap,MAT **)) { /* NULL ends the list*/ + m_free(*par); + *par = MNULL; + i++; + } + + va_end(ap); + return i; +} + + + +#endif /* VARARGS */ + + diff --git a/memstat.c b/memstat.c new file mode 100644 index 0000000..5304a04 --- /dev/null +++ b/memstat.c @@ -0,0 +1,421 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* mem_stat.c 6/09/93 */ + +/* Deallocation of static arrays */ + + +#include +#include "matrix.h" +#include "meminfo.h" +#ifdef COMPLEX +#include "zmatrix.h" +#endif +#ifdef SPARSE +#include "sparse.h" +#include "iter.h" +#endif + +static char rcsid[] = "$Id: memstat.c,v 1.1 1994/01/13 05:32:44 des Exp $"; + +/* global variable */ + +extern MEM_CONNECT mem_connect[MEM_CONNECT_MAX_LISTS]; + + +/* local type */ + +typedef struct { + void **var; /* for &A, where A is a pointer */ + int type; /* type of A */ + int mark; /* what mark is chosen */ + char *fname; /* source file name where last registered */ + int line; /* line # of file where last registered */ +} MEM_STAT_STRUCT; + + +/* local variables */ + +/* how many marks are used */ +static int mem_stat_mark_many = 0; + +/* current mark */ +static int mem_stat_mark_curr = 0; + + +static MEM_STAT_STRUCT mem_stat_var[MEM_HASHSIZE]; + +/* array of indices (+1) to mem_stat_var */ +static unsigned int mem_hash_idx[MEM_HASHSIZE]; + +/* points to the first unused element in mem_hash_idx */ +static unsigned int mem_hash_idx_end = 0; + + + +/* hashing function */ +#ifndef ANSI_C +static unsigned int mem_hash(ptr) +void **ptr; +#else +static unsigned int mem_hash(void **ptr) +#endif +{ + unsigned long lp = (unsigned long)ptr; + + return (lp % MEM_HASHSIZE); +} + + +/* look for a place in mem_stat_var */ +#ifndef ANSI_C +static int mem_lookup(var) +void **var; +#else +static int mem_lookup(void **var) +#endif +{ + int k, j; + + k = mem_hash(var); + + if (mem_stat_var[k].var == var) { + return -1; + } + else if (mem_stat_var[k].var == NULL) { + return k; + } + else { /* look for an empty place */ + j = k; + while (mem_stat_var[j].var != var && j < MEM_HASHSIZE + && mem_stat_var[j].var != NULL) + j++; + + if (mem_stat_var[j].var == NULL) return j; + else if (mem_stat_var[j].var == var) return -1; + else { /* if (j == MEM_HASHSIZE) */ + j = 0; + while (mem_stat_var[j].var != var && j < k + && mem_stat_var[j].var != NULL) + j++; + if (mem_stat_var[j].var == NULL) return j; + else if (mem_stat_var[j].var == var) return -1; + else { /* if (j == k) */ + fprintf(stderr, + "\n WARNING !!! static memory: mem_stat_var is too small\n"); + fprintf(stderr, + " Increase MEM_HASHSIZE in file: %s (currently = %d)\n\n", + MEM_HASHSIZE_FILE, MEM_HASHSIZE); + if ( !isatty(fileno(stdout)) ) { + fprintf(stdout, + "\n WARNING !!! static memory: mem_stat_var is too small\n"); + fprintf(stdout, + " Increase MEM_HASHSIZE in file: %s (currently = %d)\n\n", + MEM_HASHSIZE_FILE, MEM_HASHSIZE); + } + error(E_MEM,"mem_lookup"); + } + } + } + + return -1; +} + + +/* register static variables; + Input arguments: + var - variable to be registered, + type - type of this variable; + list - list of types + fname - source file name where last registered + line - line number of source file + + returned value < 0 --> error, + returned value == 0 --> not registered, + returned value >= 0 --> registered with this mark; +*/ +#ifndef ANSI_C +int mem_stat_reg_list(var,type,list,fname,line) +void **var; +int type,list; +char *fname; +int line; +#else +int mem_stat_reg_list(void **var, int type, int list, + char *fname, int line) +#endif +{ + int n; + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS ) + return -1; + + if (mem_stat_mark_curr == 0) return 0; /* not registered */ + if (var == NULL) return -1; /* error */ + + if ( type < 0 || type >= mem_connect[list].ntypes || + mem_connect[list].free_funcs[type] == NULL ) + { + warning(WARN_WRONG_TYPE,"mem_stat_reg_list"); + return -1; + } + + if ((n = mem_lookup(var)) >= 0) { + mem_stat_var[n].var = var; + mem_stat_var[n].mark = mem_stat_mark_curr; + mem_stat_var[n].type = type; + mem_stat_var[n].fname = fname; + mem_stat_var[n].line = line; + /* save n+1, not n */ + mem_hash_idx[mem_hash_idx_end++] = n+1; + } + + return mem_stat_mark_curr; +} + + +/* set a mark; + Input argument: + mark - positive number denoting a mark; + returned: + mark if mark > 0, + 0 if mark == 0, + -1 if mark is negative. +*/ +#ifndef ANSI_C +int mem_stat_mark(mark) +int mark; +#else +int mem_stat_mark(int mark) +#endif +{ + if (mark < 0) { + mem_stat_mark_curr = 0; + return -1; /* error */ + } + else if (mark == 0) { + mem_stat_mark_curr = 0; + return 0; + } + + mem_stat_mark_curr = mark; + mem_stat_mark_many++; + + return mark; +} + + + +/* deallocate static variables; + Input argument: + mark - a positive number denoting the mark; + + Returned: + -1 if mark < 0 (error); + 0 if mark == 0; +*/ +#ifndef ANSI_C +int mem_stat_free_list(mark,list) +int mark,list; +#else +int mem_stat_free_list(int mark, int list) +#endif +{ + unsigned int i,j; + int (*free_fn)(); + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS + || mem_connect[list].free_funcs == NULL ) + return -1; + + if (mark < 0) { + mem_stat_mark_curr = 0; + return -1; + } + else if (mark == 0) { + mem_stat_mark_curr = 0; + return 0; + } + + if (mem_stat_mark_many <= 0) { + warning(WARN_NO_MARK,"mem_stat_free"); + return -1; + } + +#ifdef DEBUG + printf("mem_stat_free: Freeing variables registered for mark %d\n", mark); +#endif /* DEBUG */ + /* deallocate the marked variables */ + for (i=0; i < mem_hash_idx_end; i++) { + j = mem_hash_idx[i]; + if (j == 0) continue; + else { + j--; + if (mem_stat_var[j].mark == mark) { + free_fn = mem_connect[list].free_funcs[mem_stat_var[j].type]; +#ifdef DEBUG + printf("# Freeing variable(s) registered in file \"%s\", line %d\n", + mem_stat_var[j].fname, mem_stat_var[j].line); +#endif /* DEBUG */ + if ( free_fn != NULL ) + (*free_fn)(*mem_stat_var[j].var); + else + warning(WARN_WRONG_TYPE,"mem_stat_free"); + + *(mem_stat_var[j].var) = NULL; + mem_stat_var[j].var = NULL; + mem_stat_var[j].mark = 0; + mem_stat_var[j].fname = NULL; + mem_stat_var[j].line = 0; + mem_hash_idx[i] = 0; + } + } + } + + while (mem_hash_idx_end > 0 && mem_hash_idx[mem_hash_idx_end-1] == 0) + mem_hash_idx_end--; + + mem_stat_mark_curr = 0; + mem_stat_mark_many--; + return 0; +} + + +/* only for diagnostic purposes */ +#ifndef ANSI_C +void mem_stat_dump(fp,list) +FILE *fp; +int list; +#else +void mem_stat_dump(FILE *fp, int list) +#endif +{ + unsigned int i,j,k=1; + + if ( list < 0 || list >= MEM_CONNECT_MAX_LISTS + || mem_connect[list].free_funcs == NULL ) + return; + + fprintf(fp," Array mem_stat_var (list no. %d):\n",list); + for (i=0; i < mem_hash_idx_end; i++) { + j = mem_hash_idx[i]; + if (j == 0) continue; + else { + j--; + fprintf(fp," %d. var = 0x%p, type = %s, mark = %d\n", + k,mem_stat_var[j].var, + mem_stat_var[j].type < mem_connect[list].ntypes && + mem_connect[list].free_funcs[mem_stat_var[j].type] != NULL ? + mem_connect[list].type_names[(int)mem_stat_var[j].type] : + "???", + mem_stat_var[j].mark); + k++; + } + } + + fprintf(fp,"\n"); +} + + +/* query function about the current mark */ +#ifdef ANSI_C +int mem_stat_show_mark(void) +#else +int mem_stat_show_mark() +#endif +{ + return mem_stat_mark_curr; +} + + +/* Varying number of arguments */ + + +#ifdef ANSI_C + +/* To allocate memory to many arguments. + The function should be called: + mem_stat_vars(list,type,&v1,&v2,&v3,...,VNULL); + where + int list,type; + void **v1, **v2, **v3,...; + The last argument should be VNULL ! + type is the type of variables v1,v2,v3,... + (of course they must be of the same type) +*/ + +int mem_stat_reg_vars(int list,int type,char *fname,int line, ...) +{ + va_list ap; + int i=0; + void **par; + + /* va_start(ap, type); */ + va_start(ap,line); /* Changed for Linux 7th Oct, 2003 */ + while (par = va_arg(ap,void **)) { /* NULL ends the list*/ + mem_stat_reg_list(par,type,list,fname,line); + i++; + } + + va_end(ap); + return i; +} + +#elif VARARGS +/* old varargs is used */ + +/* To allocate memory to many arguments. + The function should be called: + mem_stat_vars(list,type,&v1,&v2,&v3,...,VNULL); + where + int list,type; + void **v1, **v2, **v3,...; + The last argument should be VNULL ! + type is the type of variables v1,v2,v3,... + (of course they must be of the same type) +*/ + +int mem_stat_reg_vars(va_alist) va_dcl +{ + va_list ap; + int type,list,i=0; + void **par; + + va_start(ap); + list = va_arg(ap,int); + type = va_arg(ap,int); + while (par = va_arg(ap,void **)) { /* NULL ends the list*/ + mem_stat_reg_list(par,type,list); + i++; + } + + va_end(ap); + return i; +} + + +#endif diff --git a/memtort.c b/memtort.c new file mode 100644 index 0000000..8a22046 --- /dev/null +++ b/memtort.c @@ -0,0 +1,760 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Tests for mem_info.c functions + */ + +static char rcsid[] = "$Id: $"; + +#include +#include +#include "matrix2.h" +#include "sparse2.h" +#include "zmatrix2.h" + + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg) + + +/* new types list */ + +extern MEM_CONNECT mem_connect[MEM_CONNECT_MAX_LISTS]; + +/* the number of a new list */ +#define FOO_LIST 1 + +/* numbers of types */ +#define TYPE_FOO_1 1 +#define TYPE_FOO_2 2 + +typedef struct { + int dim; + int fix_dim; + Real (*a)[10]; +} FOO_1; + +typedef struct { + int dim; + int fix_dim; + Real (*a)[2]; +} FOO_2; + + + +FOO_1 *foo_1_get(dim) +int dim; +{ + FOO_1 *f; + + if ((f = (FOO_1 *)malloc(sizeof(FOO_1))) == NULL) + error(E_MEM,"foo_1_get"); + else if (mem_info_is_on()) { + mem_bytes_list(TYPE_FOO_1,0,sizeof(FOO_1),FOO_LIST); + mem_numvar_list(TYPE_FOO_1,1,FOO_LIST); + } + + f->dim = dim; + f->fix_dim = 10; + if ((f->a = (Real (*)[10])malloc(dim*sizeof(Real [10]))) == NULL) + error(E_MEM,"foo_1_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_FOO_1,0,dim*sizeof(Real [10]),FOO_LIST); + + return f; +} + + +FOO_2 *foo_2_get(dim) +int dim; +{ + FOO_2 *f; + + if ((f = (FOO_2 *)malloc(sizeof(FOO_2))) == NULL) + error(E_MEM,"foo_2_get"); + else if (mem_info_is_on()) { + mem_bytes_list(TYPE_FOO_2,0,sizeof(FOO_2),FOO_LIST); + mem_numvar_list(TYPE_FOO_2,1,FOO_LIST); + } + + f->dim = dim; + f->fix_dim = 2; + if ((f->a = (Real (*)[2])malloc(dim*sizeof(Real [2]))) == NULL) + error(E_MEM,"foo_2_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_FOO_2,0,dim*sizeof(Real [2]),FOO_LIST); + + return f; +} + + + +int foo_1_free(f) +FOO_1 *f; +{ + if ( f != NULL) { + if (mem_info_is_on()) { + mem_bytes_list(TYPE_FOO_1,sizeof(FOO_1)+ + f->dim*sizeof(Real [10]),0,FOO_LIST); + mem_numvar_list(TYPE_FOO_1,-1,FOO_LIST); + } + + free(f->a); + free(f); + } + return 0; +} + +int foo_2_free(f) +FOO_2 *f; +{ + if ( f != NULL) { + if (mem_info_is_on()) { + mem_bytes_list(TYPE_FOO_2,sizeof(FOO_2)+ + f->dim*sizeof(Real [2]),0,FOO_LIST); + mem_numvar_list(TYPE_FOO_2,-1,FOO_LIST); + } + + free(f->a); + free(f); + } + return 0; +} + + + + +char *foo_type_name[] = { + "nothing", + "FOO_1", + "FOO_2" +}; + + +#define FOO_NUM_TYPES (sizeof(foo_type_name)/sizeof(*foo_type_name)) + + +int (*foo_free_func[FOO_NUM_TYPES])() = { + NULL, + foo_1_free, + foo_2_free + }; + + + +static MEM_ARRAY foo_info_sum[FOO_NUM_TYPES]; + + + + /* px_rand -- generates sort-of random permutation */ +PERM *px_rand(pi) +PERM *pi; +{ + int i, j, k; + + if ( ! pi ) + error(E_NULL,"px_rand"); + + for ( i = 0; i < 3*pi->size; i++ ) + { + j = (rand() >> 8) % pi->size; + k = (rand() >> 8) % pi->size; + px_transp(pi,j,k); + } + + return pi; +} + +#ifdef SPARSE +SPMAT *gen_non_symm(m,n) +int m, n; +{ + SPMAT *A; + static PERM *px = PNULL; + int i, j, k, k_max; + Real s1; + + A = sp_get(m,n,8); + px = px_resize(px,n); + MEM_STAT_REG(px,TYPE_PERM); + for ( i = 0; i < A->m; i++ ) + { + k_max = 1 + ((rand() >> 8) % 10); + for ( k = 0; k < k_max; k++ ) + { + j = (rand() >> 8) % A->n; + s1 = rand()/((double)MAX_RAND); + sp_set_val(A,i,j,s1); + } + } + /* to make it likely that A is nonsingular, use pivot... */ + for ( i = 0; i < 2*A->n; i++ ) + { + j = (rand() >> 8) % A->n; + k = (rand() >> 8) % A->n; + px_transp(px,j,k); + } + for ( i = 0; i < A->n; i++ ) + sp_set_val(A,i,px->pe[i],1.0); + + + return A; +} +#endif + +void stat_test1(par) +int par; +{ + static MAT *AT = MNULL; + static VEC *xt1 = VNULL, *yt1 = VNULL; + static VEC *xt2 = VNULL, *yt2 = VNULL; + static VEC *xt3 = VNULL, *yt3 = VNULL; + static VEC *xt4 = VNULL, *yt4 = VNULL; + + AT = m_resize(AT,10,10); + xt1 = v_resize(xt1,10); + yt1 = v_resize(yt1,10); + xt2 = v_resize(xt2,10); + yt2 = v_resize(yt2,10); + xt3 = v_resize(xt3,10); + yt3 = v_resize(yt3,10); + xt4 = v_resize(xt4,10); + yt4 = v_resize(yt4,10); + + MEM_STAT_REG(AT,TYPE_MAT); + +#ifdef ANSI_C + mem_stat_reg_vars(0,TYPE_VEC,__FILE__,__LINE__,&xt1,&xt2,&xt3,&xt4,&yt1, + &yt2,&yt3,&yt4,NULL); +#else +#ifdef VARARGS + mem_stat_reg_vars(0,TYPE_VEC,__FILE__,__LINE__,&xt1,&xt2,&xt3,&xt4,&yt1, + &yt2,&yt3,&yt4,NULL); +#else + MEM_STAT_REG(xt1,TYPE_VEC); + MEM_STAT_REG(yt1,TYPE_VEC); + MEM_STAT_REG(xt2,TYPE_VEC); + MEM_STAT_REG(yt2,TYPE_VEC); + MEM_STAT_REG(xt3,TYPE_VEC); + MEM_STAT_REG(yt3,TYPE_VEC); + MEM_STAT_REG(xt4,TYPE_VEC); + MEM_STAT_REG(yt4,TYPE_VEC); +#endif +#endif + + v_rand(xt1); + m_rand(AT); + mv_mlt(AT,xt1,yt1); + +} + + +void stat_test2(par) +int par; +{ + static PERM *px = PNULL; + static IVEC *ixt = IVNULL, *iyt = IVNULL; + + px = px_resize(px,10); + ixt = iv_resize(ixt,10); + iyt = iv_resize(iyt,10); + + MEM_STAT_REG(px,TYPE_PERM); + MEM_STAT_REG(ixt,TYPE_IVEC); + MEM_STAT_REG(iyt,TYPE_IVEC); + + px_rand(px); + px_inv(px,px); +} + +#ifdef SPARSE +void stat_test3(par) +int par; +{ + static SPMAT *AT = (SPMAT *)NULL; + static VEC *xt = VNULL, *yt = VNULL; + static SPROW *r = (SPROW *) NULL; + + if (AT == (SPMAT *)NULL) + AT = gen_non_symm(100,100); + else + AT = sp_resize(AT,100,100); + xt = v_resize(xt,100); + yt = v_resize(yt,100); + if (r == NULL) r = sprow_get(100); + + MEM_STAT_REG(AT,TYPE_SPMAT); + MEM_STAT_REG(xt,TYPE_VEC); + MEM_STAT_REG(yt,TYPE_VEC); + MEM_STAT_REG(r,TYPE_SPROW); + + v_rand(xt); + sp_mv_mlt(AT,xt,yt); + +} +#endif + +#ifdef COMPLEX +void stat_test4(par) +int par; +{ + static ZMAT *AT = ZMNULL; + static ZVEC *xt = ZVNULL, *yt = ZVNULL; + + AT = zm_resize(AT,10,10); + xt = zv_resize(xt,10); + yt = zv_resize(yt,10); + + MEM_STAT_REG(AT,TYPE_ZMAT); + MEM_STAT_REG(xt,TYPE_ZVEC); + MEM_STAT_REG(yt,TYPE_ZVEC); + + zv_rand(xt); + zm_rand(AT); + zmv_mlt(AT,xt,yt); + +} +#endif + + +void main(argc, argv) +int argc; +char *argv[]; +{ + VEC *x = VNULL, *y = VNULL, *z = VNULL; + PERM *pi1 = PNULL, *pi2 = PNULL, *pi3 = PNULL; + MAT *A = MNULL, *B = MNULL, *C = MNULL; +#ifdef SPARSE + SPMAT *sA, *sB; + SPROW *r; +#endif + IVEC *ix = IVNULL, *iy = IVNULL, *iz = IVNULL; + int m,n,i,j,deg,k; + Real s1,s2; +#ifdef COMPLEX + ZVEC *zx = ZVNULL, *zy = ZVNULL, *zz = ZVNULL; + ZMAT *zA = ZMNULL, *zB = ZMNULL, *zC = ZMNULL; + complex ONE; +#endif + /* variables for testing attaching new lists of types */ + FOO_1 *foo_1; + FOO_2 *foo_2; + + + mem_info_on(TRUE); + +#if defined(ANSI_C) || defined(VARARGS) + + notice("vector initialize, copy & resize"); + + n = v_get_vars(15,&x,&y,&z,(VEC **)NULL); + if (n != 3) { + errmesg("v_get_vars"); + printf(" n = %d (should be 3)\n",n); + } + + v_rand(x); + v_rand(y); + z = v_copy(x,z); + if ( v_norm2(v_sub(x,z,z)) >= MACHEPS ) + errmesg("v_get_vars"); + v_copy(x,y); + n = v_resize_vars(10,&x,&y,&z,NULL); + if ( n != 3 || v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("VEC copy/resize"); + + n = v_resize_vars(20,&x,&y,&z,NULL); + if ( n != 3 || v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("VEC resize"); + + n = v_free_vars(&x,&y,&z,NULL); + if (n != 3) + errmesg("v_free_vars"); + + /* IVEC */ + notice("int vector initialise, copy & resize"); + n = iv_get_vars(15,&ix,&iy,&iz,NULL); + + if (n != 3) { + errmesg("iv_get_vars"); + printf(" n = %d (should be 3)\n",n); + } + for (i=0; i < ix->dim; i++) { + ix->ive[i] = 2*i-1; + iy->ive[i] = 3*i+2; + } + iz = iv_add(ix,iy,iz); + for (i=0; i < ix->dim; i++) + if ( iz->ive[i] != 5*i+1) + errmesg("iv_get_vars"); + + n = iv_resize_vars(10,&ix,&iy,&iz,NULL); + if ( n != 3) errmesg("IVEC copy/resize"); + + iv_add(ix,iy,iz); + for (i=0; i < ix->dim; i++) + if (iz->ive[i] != 5*i+1) + errmesg("IVEC copy/resize"); + + n = iv_resize_vars(20,&ix,&iy,&iz,NULL); + if ( n != 3 ) errmesg("IVEC resize"); + + iv_add(ix,iy,iz); + for (i=0; i < 10; i++) + if (iz->ive[i] != 5*i+1) + errmesg("IVEC copy/resize"); + + n = iv_free_vars(&ix,&iy,&iz,NULL); + if (n != 3) + errmesg("iv_free_vars"); + + /* MAT */ + notice("matrix initialise, copy & resize"); + n = m_get_vars(10,10,&A,&B,&C,NULL); + if (n != 3) { + errmesg("m_get_vars"); + printf(" n = %d (should be 3)\n",n); + } + + m_rand(A); + m_rand(B); + C = m_copy(A,C); + if ( m_norm_inf(m_sub(A,C,C)) >= MACHEPS ) + errmesg("MAT copy"); + m_copy(A,B); + n = m_resize_vars(5,5,&A,&B,&C,NULL); + if ( n != 3 || m_norm_inf(m_sub(A,B,C)) >= MACHEPS ) + errmesg("MAT copy/resize"); + + n = m_resize_vars(20,20,&A,&B,NULL); + if ( m_norm_inf(m_sub(A,B,C)) >= MACHEPS ) + errmesg("MAT resize"); + + k = m_free_vars(&A,&B,&C,NULL); + if ( k != 3 ) + errmesg("MAT free"); + + /* PERM */ + notice("permutation initialise, inverting & permuting vectors"); + n = px_get_vars(15,&pi1,&pi2,&pi3,NULL); + if (n != 3) { + errmesg("px_get_vars"); + printf(" n = %d (should be 3)\n",n); + } + + v_get_vars(15,&x,&y,&z,NULL); + + px_rand(pi1); + v_rand(x); + px_vec(pi1,x,z); + y = v_resize(y,x->dim); + pxinv_vec(pi1,z,y); + if ( v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("PERMute vector"); + pi2 = px_inv(pi1,pi2); + pi3 = px_mlt(pi1,pi2,pi3); + for ( i = 0; i < pi3->size; i++ ) + if ( pi3->pe[i] != i ) + errmesg("PERM inverse/multiply"); + + px_resize_vars(20,&pi1,&pi2,&pi3,NULL); + v_resize_vars(20,&x,&y,&z,NULL); + + px_rand(pi1); + v_rand(x); + px_vec(pi1,x,z); + pxinv_vec(pi1,z,y); + if ( v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("PERMute vector"); + pi2 = px_inv(pi1,pi2); + pi3 = px_mlt(pi1,pi2,pi3); + for ( i = 0; i < pi3->size; i++ ) + if ( pi3->pe[i] != i ) + errmesg("PERM inverse/multiply"); + + n = px_free_vars(&pi1,&pi2,&pi3,NULL); + if ( n != 3 ) + errmesg("PERM px_free_vars"); + +#ifdef SPARSE + /* set up two random sparse matrices */ + m = 120; + n = 100; + deg = 5; + notice("allocating sparse matrices"); + k = sp_get_vars(m,n,deg,&sA,&sB,NULL); + if (k != 2) { + errmesg("sp_get_vars"); + printf(" n = %d (should be 2)\n",k); + } + + notice("setting and getting matrix entries"); + for ( k = 0; k < m*deg; k++ ) + { + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(sA,i,j,rand()/((Real)MAX_RAND)); + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(sB,i,j,rand()/((Real)MAX_RAND)); + } + for ( k = 0; k < 10; k++ ) + { + s1 = rand()/((Real)MAX_RAND); + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(sA,i,j,s1); + s2 = sp_get_val(sA,i,j); + if ( fabs(s1 - s2) >= MACHEPS ) { + printf(" s1 = %g, s2 = %g, |s1 - s2| = %g\n", + s1,s2,fabs(s1-s2)); + break; + } + } + if ( k < 10 ) + errmesg("sp_set_val()/sp_get_val()"); + + /* check column access paths */ + notice("resizing and access paths"); + k = sp_resize_vars(sA->m+10,sA->n+10,&sA,&sB,NULL); + if (k != 2) { + errmesg("sp_get_vars"); + printf(" n = %d (should be 2)\n",k); + } + + for ( k = 0 ; k < 20; k++ ) + { + i = sA->m - 1 - ((rand() >> 8) % 10); + j = sA->n - 1 - ((rand() >> 8) % 10); + s1 = rand()/((Real)MAX_RAND); + sp_set_val(sA,i,j,s1); + if ( fabs(s1 - sp_get_val(sA,i,j)) >= MACHEPS ) + break; + } + if ( k < 20 ) + errmesg("sp_resize()"); + sp_col_access(sA); + if ( ! chk_col_access(sA) ) + { + errmesg("sp_col_access()"); + } + sp_diag_access(sA); + for ( i = 0; i < sA->m; i++ ) + { + r = &(sA->row[i]); + if ( r->diag != sprow_idx(r,i) ) + break; + } + if ( i < sA->m ) + { + errmesg("sp_diag_access()"); + } + + k = sp_free_vars(&sA,&sB,NULL); + if (k != 2) + errmesg("sp_free_vars"); +#endif /* SPARSE */ + + +#ifdef COMPLEX + /* complex stuff */ + + ONE = zmake(1.0,0.0); + printf("# ONE = "); z_output(ONE); + printf("# Check: MACHEPS = %g\n",MACHEPS); + /* allocate, initialise, copy and resize operations */ + /* ZVEC */ + notice("vector initialise, copy & resize"); + zv_get_vars(12,&zx,&zy,&zz,NULL); + + zv_rand(zx); + zv_rand(zy); + zz = zv_copy(zx,zz); + if ( zv_norm2(zv_sub(zx,zz,zz)) >= MACHEPS ) + errmesg("ZVEC copy"); + zv_copy(zx,zy); + + zv_resize_vars(10,&zx,&zy,NULL); + if ( zv_norm2(zv_sub(zx,zy,zz)) >= MACHEPS ) + errmesg("ZVEC copy/resize"); + + zv_resize_vars(20,&zx,&zy,NULL); + if ( zv_norm2(zv_sub(zx,zy,zz)) >= MACHEPS ) + errmesg("VZEC resize"); + zv_free_vars(&zx,&zy,&zz,NULL); + + + /* ZMAT */ + notice("matrix initialise, copy & resize"); + zm_get_vars(8,5,&zA,&zB,&zC,NULL); + + zm_rand(zA); + zm_rand(zB); + zC = zm_copy(zA,zC); + if ( zm_norm_inf(zm_sub(zA,zC,zC)) >= MACHEPS ) + errmesg("ZMAT copy"); + + zm_copy(zA,zB); + zm_resize_vars(3,5,&zA,&zB,&zC,NULL); + + if ( zm_norm_inf(zm_sub(zA,zB,zC)) >= MACHEPS ) + errmesg("ZMAT copy/resize"); + zm_resize_vars(20,20,&zA,&zB,&zC,NULL); + + if ( zm_norm_inf(zm_sub(zA,zB,zC)) >= MACHEPS ) + errmesg("ZMAT resize"); + + zm_free_vars(&zA,&zB,&zC,NULL); +#endif /* COMPLEX */ + +#endif /* if defined(ANSI_C) || defined(VARARGS) */ + + printf("# test of mem_info_bytes and mem_info_numvar\n"); + printf(" TYPE VEC: %ld bytes allocated, %d variables allocated\n", + mem_info_bytes(TYPE_VEC,0),mem_info_numvar(TYPE_VEC,0)); + + notice("static memory test"); + mem_info_on(TRUE); + mem_stat_mark(1); + for (i=0; i < 100; i++) + stat_test1(i); + mem_stat_free(1); + + mem_stat_mark(1); + for (i=0; i < 100; i++) { + stat_test1(i); +#ifdef COMPLEX + stat_test4(i); +#endif + } + + mem_stat_mark(2); + for (i=0; i < 100; i++) + stat_test2(i); + + mem_stat_mark(3); +#ifdef SPARSE + for (i=0; i < 100; i++) + stat_test3(i); +#endif + + mem_info(); + mem_dump_list(stdout,0); + + mem_stat_free(1); + mem_stat_free(3); + mem_stat_mark(4); + + for (i=0; i < 100; i++) { + stat_test1(i); +#ifdef COMPLEX + stat_test4(i); +#endif + } + + mem_stat_dump(stdout,0); + if (mem_stat_show_mark() != 4) { + errmesg("not 4 in mem_stat_show_mark()"); + } + + mem_stat_free(2); + mem_stat_free(4); + + if (mem_stat_show_mark() != 0) { + errmesg("not 0 in mem_stat_show_mark()"); + } + + /* add new list of types */ + + mem_attach_list(FOO_LIST,FOO_NUM_TYPES,foo_type_name, + foo_free_func,foo_info_sum); + if (!mem_is_list_attached(FOO_LIST)) + errmesg("list FOO_LIST is not attached"); + + mem_dump_list(stdout,FOO_LIST); + foo_1 = foo_1_get(6); + foo_2 = foo_2_get(3); + for (i=0; i < foo_1->dim; i++) + for (j=0; j < foo_1->fix_dim; j++) + foo_1->a[i][j] = i+j; + for (i=0; i < foo_2->dim; i++) + for (j=0; j < foo_2->fix_dim; j++) + foo_2->a[i][j] = i+j; + printf(" foo_1->a[%d][%d] = %g\n",5,9,foo_1->a[5][9]); + printf(" foo_2->a[%d][%d] = %g\n",2,1,foo_2->a[2][1]); + + mem_stat_mark(5); + mem_stat_reg_list((void **)&foo_1,TYPE_FOO_1,FOO_LIST,__FILE__,__LINE__); + mem_stat_reg_list((void **)&foo_2,TYPE_FOO_2,FOO_LIST,__FILE__,__LINE__); + mem_stat_dump(stdout,FOO_LIST); + mem_info_file(stdout,FOO_LIST); + mem_stat_free_list(5,FOO_LIST); + mem_stat_dump(stdout,FOO_LIST); + if ( foo_1 != NULL ) + errmesg(" foo_1 is not released"); + if ( foo_2 != NULL ) + errmesg(" foo_2 is not released"); + mem_dump_list(stdout,FOO_LIST); + mem_info_file(stdout,FOO_LIST); + + mem_free_vars(FOO_LIST); + if ( mem_is_list_attached(FOO_LIST) ) + errmesg("list FOO_LIST is not detached"); + + mem_info(); + +#if REAL == FLOAT + printf("# SINGLE PRECISION was used\n"); +#elif REAL == DOUBLE + printf("# DOUBLE PRECISION was used\n"); +#endif + +#define ANSI_OR_VAR + +#ifndef ANSI_C +#ifndef VARARGS +#undef ANSI_OR_VAR +#endif +#endif + +#ifdef ANSI_OR_VAR + + printf("# you should get: \n"); +#if (REAL == FLOAT) + printf("# type VEC: 276 bytes allocated, 3 variables allocated\n"); +#elif (REAL == DOUBLE) + printf("# type VEC: 516 bytes allocated, 3 variables allocated\n"); +#endif + printf("# and other types are zeros\n"); + +#endif /*#if defined(ANSI_C) || defined(VARAGS) */ + + printf("# Finished memory torture test\n"); + + dmalloc_shutdown(); + return; +} diff --git a/mfunc.c b/mfunc.c new file mode 100644 index 0000000..89fc7de --- /dev/null +++ b/mfunc.c @@ -0,0 +1,434 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains routines for computing functions of matrices + especially polynomials and exponential functions + Copyright (C) Teresa Leyk and David Stewart, 1993 + */ + +#include +#include +#include "matrix.h" +#include "matrix2.h" + +static char rcsid[] = "$Id: mfunc.c,v 1.2 1994/11/01 05:57:56 des Exp $"; + + + +/* _m_pow -- computes integer powers of a square matrix A, A^p + -- uses tmp as temporary workspace */ +#ifndef ANSI_C +MAT *_m_pow(A, p, tmp, out) +MAT *A, *tmp, *out; +int p; +#else +MAT *_m_pow(const MAT *A, int p, MAT *tmp, MAT *out) +#endif +{ + int it_cnt, k, max_bit; + + /* + File containing routines for evaluating matrix functions + esp. the exponential function + */ + +#define Z(k) (((k) & 1) ? tmp : out) + + if ( ! A ) + error(E_NULL,"_m_pow"); + if ( A->m != A->n ) + error(E_SQUARE,"_m_pow"); + if ( p < 0 ) + error(E_NEG,"_m_pow"); + out = m_resize(out,A->m,A->n); + tmp = m_resize(tmp,A->m,A->n); + + if ( p == 0 ) + m_ident(out); + else if ( p > 0 ) + { + it_cnt = 1; + for ( max_bit = 0; ; max_bit++ ) + if ( (p >> (max_bit+1)) == 0 ) + break; + tmp = m_copy(A,tmp); + + for ( k = 0; k < max_bit; k++ ) + { + m_mlt(Z(it_cnt),Z(it_cnt),Z(it_cnt+1)); + it_cnt++; + if ( p & (1 << (max_bit-1)) ) + { + m_mlt(A,Z(it_cnt),Z(it_cnt+1)); + /* m_copy(Z(it_cnt),out); */ + it_cnt++; + } + p <<= 1; + } + if (it_cnt & 1) + out = m_copy(Z(it_cnt),out); + } + + return out; + +#undef Z +} + +/* m_pow -- computes integer powers of a square matrix A, A^p */ +#ifndef ANSI_C +MAT *m_pow(A, p, out) +MAT *A, *out; +int p; +#else +MAT *m_pow(const MAT *A, int p, MAT *out) +#endif +{ + STATIC MAT *wkspace=MNULL, *tmp=MNULL; + + if ( ! A ) + error(E_NULL,"m_pow"); + if ( A->m != A->n ) + error(E_SQUARE,"m_pow"); + + wkspace = m_resize(wkspace,A->m,A->n); + MEM_STAT_REG(wkspace,TYPE_MAT); + if ( p < 0 ) + { + tmp = m_resize(tmp,A->m,A->n); + MEM_STAT_REG(tmp,TYPE_MAT); + tracecatch(m_inverse(A,tmp),"m_pow"); + out = _m_pow(tmp, -p, wkspace, out); + } + else + out = _m_pow(A, p, wkspace, out); + +#ifdef THREADSAFE + M_FREE(wkspace); M_FREE(tmp); +#endif + + return out; +} + +/**************************************************/ + +/* _m_exp -- compute matrix exponential of A and save it in out + -- uses Pade approximation followed by repeated squaring + -- eps is the tolerance used for the Pade approximation + -- A is not changed + -- q_out - degree of the Pade approximation (q_out,q_out) + -- j_out - the power of 2 for scaling the matrix A + such that ||A/2^j_out|| <= 0.5 +*/ +#ifndef ANSI_C +MAT *_m_exp(A,eps,out,q_out,j_out) +MAT *A,*out; +double eps; +int *q_out, *j_out; +#else +MAT *_m_exp(MAT *A, double eps, MAT *out, int *q_out, int *j_out) +#endif +{ + STATIC MAT *D = MNULL, *Apow = MNULL, *N = MNULL, *Y = MNULL; + STATIC VEC *c1 = VNULL, *tmp = VNULL; + VEC y0, y1; /* additional structures */ + STATIC PERM *pivot = PNULL; + int j, k, l, q, r, s, j2max, t; + double inf_norm, eqq, power2, c, sign; + + if ( ! A ) + error(E_SIZES,"_m_exp"); + if ( A->m != A->n ) + error(E_SIZES,"_m_exp"); + if ( A == out ) + error(E_INSITU,"_m_exp"); + if ( eps < 0.0 ) + error(E_RANGE,"_m_exp"); + else if (eps == 0.0) + eps = MACHEPS; + + N = m_resize(N,A->m,A->n); + D = m_resize(D,A->m,A->n); + Apow = m_resize(Apow,A->m,A->n); + out = m_resize(out,A->m,A->n); + + MEM_STAT_REG(N,TYPE_MAT); + MEM_STAT_REG(D,TYPE_MAT); + MEM_STAT_REG(Apow,TYPE_MAT); + + /* normalise A to have ||A||_inf <= 1 */ + inf_norm = m_norm_inf(A); + if (inf_norm <= 0.0) { + m_ident(out); + *q_out = -1; + *j_out = 0; + return out; + } + else { + j2max = floor(1+log(inf_norm)/log(2.0)); + j2max = max(0, j2max); + } + + power2 = 1.0; + for ( k = 1; k <= j2max; k++ ) + power2 *= 2; + power2 = 1.0/power2; + if ( j2max > 0 ) + sm_mlt(power2,A,A); + + /* compute order for polynomial approximation */ + eqq = 1.0/6.0; + for ( q = 1; eqq > eps; q++ ) + eqq /= 16.0*(2.0*q+1.0)*(2.0*q+3.0); + + /* construct vector of coefficients */ + c1 = v_resize(c1,q+1); + MEM_STAT_REG(c1,TYPE_VEC); + c1->ve[0] = 1.0; + for ( k = 1; k <= q; k++ ) + c1->ve[k] = c1->ve[k-1]*(q-k+1)/((2*q-k+1)*(double)k); + + tmp = v_resize(tmp,A->n); + MEM_STAT_REG(tmp,TYPE_VEC); + + s = (int)floor(sqrt((double)q/2.0)); + if ( s <= 0 ) s = 1; + _m_pow(A,s,out,Apow); + r = q/s; + + Y = m_resize(Y,s,A->n); + MEM_STAT_REG(Y,TYPE_MAT); + /* y0 and y1 are pointers to rows of Y, N and D */ + y0.dim = y0.max_dim = A->n; + y1.dim = y1.max_dim = A->n; + + m_zero(Y); + m_zero(N); + m_zero(D); + + for( j = 0; j < A->n; j++ ) + { + if (j > 0) + Y->me[0][j-1] = 0.0; + y0.ve = Y->me[0]; + y0.ve[j] = 1.0; + for ( k = 0; k < s-1; k++ ) + { + y1.ve = Y->me[k+1]; + mv_mlt(A,&y0,&y1); + y0.ve = y1.ve; + } + + y0.ve = N->me[j]; + y1.ve = D->me[j]; + t = s*r; + for ( l = 0; l <= q-t; l++ ) + { + c = c1->ve[t+l]; + sign = ((t+l) & 1) ? -1.0 : 1.0; + __mltadd__(y0.ve,Y->me[l],c, Y->n); + __mltadd__(y1.ve,Y->me[l],c*sign,Y->n); + } + + for (k=1; k <= r; k++) + { + v_copy(mv_mlt(Apow,&y0,tmp),&y0); + v_copy(mv_mlt(Apow,&y1,tmp),&y1); + t = s*(r-k); + for (l=0; l < s; l++) + { + c = c1->ve[t+l]; + sign = ((t+l) & 1) ? -1.0 : 1.0; + __mltadd__(y0.ve,Y->me[l],c, Y->n); + __mltadd__(y1.ve,Y->me[l],c*sign,Y->n); + } + } + } + + pivot = px_resize(pivot,A->m); + MEM_STAT_REG(pivot,TYPE_PERM); + + /* note that N and D are transposed, + therefore we use LUTsolve; + out is saved row-wise, and must be transposed + after this */ + + LUfactor(D,pivot); + for (k=0; k < A->n; k++) + { + y0.ve = N->me[k]; + y1.ve = out->me[k]; + LUTsolve(D,pivot,&y0,&y1); + } + m_transp(out,out); + + + /* Use recursive squaring to turn the normalised exponential to the + true exponential */ + +#define Z(k) ((k) & 1 ? Apow : out) + + for( k = 1; k <= j2max; k++) + m_mlt(Z(k-1),Z(k-1),Z(k)); + + if (Z(k) == out) + m_copy(Apow,out); + + /* output parameters */ + *j_out = j2max; + *q_out = q; + + /* restore the matrix A */ + sm_mlt(1.0/power2,A,A); + +#ifdef THREADSAFE + M_FREE(D); M_FREE(Apow); M_FREE(N); M_FREE(Y); + V_FREE(c1); V_FREE(tmp); + PX_FREE(pivot); +#endif + + return out; + +#undef Z +} + + +/* simple interface for _m_exp */ +#ifndef ANSI_C +MAT *m_exp(A,eps,out) +MAT *A,*out; +double eps; +#else +MAT *m_exp(MAT *A, double eps, MAT *out) +#endif +{ + int q_out, j_out; + + return _m_exp(A,eps,out,&q_out,&j_out); +} + + +/*--------------------------------*/ + +/* m_poly -- computes sum_i a[i].A^i, where i=0,1,...dim(a); + -- uses C. Van Loan's fast and memory efficient method */ +#ifndef ANSI_C +MAT *m_poly(A,a,out) +MAT *A,*out; +VEC *a; +#else +MAT *m_poly(const MAT *A, const VEC *a, MAT *out) +#endif +{ + STATIC MAT *Apow = MNULL, *Y = MNULL; + STATIC VEC *tmp = VNULL; + VEC y0, y1; /* additional vectors */ + int j, k, l, q, r, s, t; + + if ( ! A || ! a ) + error(E_NULL,"m_poly"); + if ( A->m != A->n ) + error(E_SIZES,"m_poly"); + if ( A == out ) + error(E_INSITU,"m_poly"); + + out = m_resize(out,A->m,A->n); + Apow = m_resize(Apow,A->m,A->n); + MEM_STAT_REG(Apow,TYPE_MAT); + tmp = v_resize(tmp,A->n); + MEM_STAT_REG(tmp,TYPE_VEC); + + q = a->dim - 1; + if ( q == 0 ) { + m_zero(out); + for (j=0; j < out->n; j++) + out->me[j][j] = a->ve[0]; + return out; + } + else if ( q == 1) { + sm_mlt(a->ve[1],A,out); + for (j=0; j < out->n; j++) + out->me[j][j] += a->ve[0]; + return out; + } + + s = (int)floor(sqrt((double)q/2.0)); + if ( s <= 0 ) s = 1; + _m_pow(A,s,out,Apow); + r = q/s; + + Y = m_resize(Y,s,A->n); + MEM_STAT_REG(Y,TYPE_MAT); + /* pointers to rows of Y */ + y0.dim = y0.max_dim = A->n; + y1.dim = y1.max_dim = A->n; + + m_zero(Y); + m_zero(out); + +#define Z(k) ((k) & 1 ? tmp : &y0) +#define ZZ(k) ((k) & 1 ? tmp->ve : y0.ve) + + for( j = 0; j < A->n; j++) + { + if( j > 0 ) + Y->me[0][j-1] = 0.0; + Y->me[0][j] = 1.0; + + y0.ve = Y->me[0]; + for (k = 0; k < s-1; k++) + { + y1.ve = Y->me[k+1]; + mv_mlt(A,&y0,&y1); + y0.ve = y1.ve; + } + + y0.ve = out->me[j]; + + t = s*r; + for ( l = 0; l <= q-t; l++ ) + __mltadd__(y0.ve,Y->me[l],a->ve[t+l],Y->n); + + for (k=1; k <= r; k++) + { + mv_mlt(Apow,Z(k-1),Z(k)); + t = s*(r-k); + for (l=0; l < s; l++) + __mltadd__(ZZ(k),Y->me[l],a->ve[t+l],Y->n); + } + if (Z(k) == &y0) v_copy(tmp,&y0); + } + + m_transp(out,out); + +#ifdef THREADSAFE + M_FREE(Apow); M_FREE(Y); V_FREE(tmp); +#endif + + return out; +} + + diff --git a/mfuntort.c b/mfuntort.c new file mode 100644 index 0000000..fd8ec9b --- /dev/null +++ b/mfuntort.c @@ -0,0 +1,181 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* mfuntort.c, 10/11/93 */ + +static char rcsid[] = "$Id: mfuntort.c,v 1.2 1994/01/14 01:08:06 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + +#define DIM 10 + +void main() +{ + + MAT *A, *B, *C, *OUTA, *OUTB, *TMP; + MAT *exp_A_expected, *exp_A; + VEC *x, *b; + double c, eps = 1e-10; + int i, j, q_out, j_out; + + mem_info_on(TRUE); + + A = m_get(DIM,DIM); + B = m_get(DIM,DIM); + C = m_get(DIM,DIM); + OUTA = m_get(DIM,DIM); + OUTB = m_get(DIM,DIM); + TMP = m_get(DIM,DIM); + x = v_get(DIM); + b = v_get(6); + + notice("exponent of a matrix"); + + m_ident(A); + mem_stat_mark(1); + _m_exp(A,eps,OUTA,&q_out,&j_out); + printf("# q_out = %d, j_out = %d\n",q_out,j_out); + + m_exp(A,eps,OUTA); + sm_mlt(exp(1.0),A,A); + m_sub(OUTA,A,TMP); + printf("# ||exp(I) - e*I|| = %g\n",m_norm_inf(TMP)); + + m_rand(A); + m_transp(A,TMP); + m_add(A,TMP,A); + B = m_copy(A,B); + + m_exp(A,eps,OUTA); + + symmeig(B,OUTB,x); + m_zero(TMP); + for (i=0; i < x->dim; i++) + TMP->me[i][i] = exp(x->ve[i]); + m_mlt(OUTB,TMP,C); + mmtr_mlt(C,OUTB,TMP); + m_sub(TMP,OUTA,TMP); + printf("# ||exp(A) - Q*exp(lambda)*Q^T|| = %g\n",m_norm_inf(TMP)); + + notice("polynomial of a matrix"); + m_rand(A); + m_transp(A,TMP); + m_add(A,TMP,A); + B = m_copy(A,B); + v_rand(b); + + m_poly(A,b,OUTA); + + symmeig(B,OUTB,x); + m_zero(TMP); + for (i=0; i < x->dim; i++) { + c = b->ve[b->dim-1]; + for (j=b->dim-2; j >= 0; j--) + c = c*x->ve[i] + b->ve[j]; + TMP->me[i][i] = c; + } + m_mlt(OUTB,TMP,C); + mmtr_mlt(C,OUTB,TMP); + m_sub(TMP,OUTA,TMP); + printf("# ||poly(A) - Q*poly(lambda)*Q^T|| = %g\n",m_norm_inf(TMP)); + mem_stat_free(1); + + + /* Brook Milligan's test */ + + M_FREE(A); + M_FREE(B); + M_FREE(C); + + notice("exponent of a nonsymmetric matrix"); + A = m_get (2, 2); + A -> me [0][0] = 1.0; + A -> me [0][1] = 1.0; + A -> me [1][0] = 4.0; + A -> me [1][1] = 1.0; + + exp_A_expected = m_get(2, 2); + exp_A_expected -> me [0][0] = exp (3.0) / 2.0 + exp (-1.0) / 2.0; + exp_A_expected -> me [0][1] = exp (3.0) / 4.0 - exp (-1.0) / 4.0; + exp_A_expected -> me [1][0] = exp (3.0) - exp (-1.0); + exp_A_expected -> me [1][1] = exp (3.0) / 2.0 + exp (-1.0) / 2.0; + + printf ("A:\n"); + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + printf (" %15.8e", A -> me [i][j]); + printf ("\n"); + } + + printf ("\nexp(A) (expected):\n"); + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + printf (" %15.8e", exp_A_expected -> me [i][j]); + printf ("\n"); + } + + mem_stat_mark(3); + exp_A = m_exp (A, 1e-16,NULL); + mem_stat_free(3); + + printf ("\nexp(A):\n"); + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + printf (" %15.8e", exp_A -> me [i][j]); + printf ("\n"); + } + printf ("\nexp(A) - exp(A) (expected):\n"); + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + printf (" %15.8e", exp_A -> me [i][j] - exp_A_expected -> me [i][j]); + printf ("\n"); + } + + M_FREE(A); + M_FREE(B); + M_FREE(C); + M_FREE(exp_A); + M_FREE(exp_A_expected); + M_FREE(OUTA); + M_FREE(OUTB); + M_FREE(TMP); + V_FREE(b); + V_FREE(x); + + mem_info(); +} + diff --git a/norm.c b/norm.c new file mode 100644 index 0000000..60cc03b --- /dev/null +++ b/norm.c @@ -0,0 +1,230 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + A collection of functions for computing norms: scaled and unscaled +*/ +static char rcsid[] = "$Id: norm.c,v 1.6 1994/01/13 05:34:35 des Exp $"; + +#include +#include +#include "matrix.h" + + +/* _v_norm1 -- computes (scaled) 1-norms of vectors */ +#ifndef ANSI_C +double _v_norm1(x,scale) +VEC *x, *scale; +#else +double _v_norm1(const VEC *x, const VEC *scale) +#endif +{ + int i, dim; + Real s, sum; + + if ( x == (VEC *)NULL ) + error(E_NULL,"_v_norm1"); + dim = x->dim; + + sum = 0.0; + if ( scale == (VEC *)NULL ) + for ( i = 0; i < dim; i++ ) + sum += fabs(x->ve[i]); + else if ( scale->dim < dim ) + error(E_SIZES,"_v_norm1"); + else + for ( i = 0; i < dim; i++ ) + { s = scale->ve[i]; + sum += ( s== 0.0 ) ? fabs(x->ve[i]) : fabs(x->ve[i]/s); + } + + return sum; +} + +/* square -- returns x^2 */ +#ifndef ANSI_C +double square(x) +double x; +#else +double square(double x) +#endif +{ return x*x; } + +/* cube -- returns x^3 */ +#ifndef ANSI_C +double cube(x) +double x; +#else +double cube(double x) +#endif +{ return x*x*x; } + +/* _v_norm2 -- computes (scaled) 2-norm (Euclidean norm) of vectors */ +#ifndef ANSI_C +double _v_norm2(x,scale) +VEC *x, *scale; +#else +double _v_norm2(const VEC *x, const VEC *scale) +#endif +{ + int i, dim; + Real s, sum; + + if ( x == (VEC *)NULL ) + error(E_NULL,"_v_norm2"); + dim = x->dim; + + sum = 0.0; + if ( scale == (VEC *)NULL ) + for ( i = 0; i < dim; i++ ) + sum += square(x->ve[i]); + else if ( scale->dim < dim ) + error(E_SIZES,"_v_norm2"); + else + for ( i = 0; i < dim; i++ ) + { s = scale->ve[i]; + sum += ( s== 0.0 ) ? square(x->ve[i]) : + square(x->ve[i]/s); + } + + return sqrt(sum); +} + +#define max(a,b) ((a) > (b) ? (a) : (b)) + +/* _v_norm_inf -- computes (scaled) infinity-norm (supremum norm) of vectors */ +#ifndef ANSI_C +double _v_norm_inf(x,scale) +VEC *x, *scale; +#else +double _v_norm_inf(const VEC *x, const VEC *scale) +#endif +{ + int i, dim; + Real s, maxval, tmp; + + if ( x == (VEC *)NULL ) + error(E_NULL,"_v_norm_inf"); + dim = x->dim; + + maxval = 0.0; + if ( scale == (VEC *)NULL ) + for ( i = 0; i < dim; i++ ) + { tmp = fabs(x->ve[i]); + maxval = max(maxval,tmp); + } + else if ( scale->dim < dim ) + error(E_SIZES,"_v_norm_inf"); + else + for ( i = 0; i < dim; i++ ) + { s = scale->ve[i]; + tmp = ( s== 0.0 ) ? fabs(x->ve[i]) : fabs(x->ve[i]/s); + maxval = max(maxval,tmp); + } + + return maxval; +} + +/* m_norm1 -- compute matrix 1-norm -- unscaled */ +#ifndef ANSI_C +double m_norm1(A) +MAT *A; +#else +double m_norm1(const MAT *A) +#endif +{ + int i, j, m, n; + Real maxval, sum; + + if ( A == (MAT *)NULL ) + error(E_NULL,"m_norm1"); + + m = A->m; n = A->n; + maxval = 0.0; + + for ( j = 0; j < n; j++ ) + { + sum = 0.0; + for ( i = 0; i < m; i ++ ) + sum += fabs(A->me[i][j]); + maxval = max(maxval,sum); + } + + return maxval; +} + +/* m_norm_inf -- compute matrix infinity-norm -- unscaled */ +#ifndef ANSI_C +double m_norm_inf(A) +MAT *A; +#else +double m_norm_inf(const MAT *A) +#endif +{ + int i, j, m, n; + Real maxval, sum; + + if ( A == (MAT *)NULL ) + error(E_NULL,"m_norm_inf"); + + m = A->m; n = A->n; + maxval = 0.0; + + for ( i = 0; i < m; i++ ) + { + sum = 0.0; + for ( j = 0; j < n; j ++ ) + sum += fabs(A->me[i][j]); + maxval = max(maxval,sum); + } + + return maxval; +} + +/* m_norm_frob -- compute matrix frobenius-norm -- unscaled */ +#ifndef ANSI_C +double m_norm_frob(A) +MAT *A; +#else +double m_norm_frob(const MAT *A) +#endif +{ + int i, j, m, n; + Real sum; + + if ( A == (MAT *)NULL ) + error(E_NULL,"m_norm_frob"); + + m = A->m; n = A->n; + sum = 0.0; + + for ( i = 0; i < m; i++ ) + for ( j = 0; j < n; j ++ ) + sum += square(A->me[i][j]); + + return sqrt(sum); +} + diff --git a/oldnames.h b/oldnames.h new file mode 100644 index 0000000..333d087 --- /dev/null +++ b/oldnames.h @@ -0,0 +1,150 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* macros for names used in versions 1.0 and 1.1 */ +/* 8/11/93 */ + + +#ifndef OLDNAMESH +#define OLDNAMESH + + +/* type IVEC */ + +#define get_ivec iv_get +#define freeivec IV_FREE +#define cp_ivec iv_copy +#define fout_ivec iv_foutput +#define out_ivec iv_output +#define fin_ivec iv_finput +#define in_ivec iv_input +#define dump_ivec iv_dump + + +/* type ZVEC */ + +#define get_zvec zv_get +#define freezvec ZV_FREE +#define cp_zvec zv_copy +#define fout_zvec zv_foutput +#define out_zvec zv_output +#define fin_zvec zv_finput +#define in_zvec zv_input +#define zero_zvec zv_zero +#define rand_zvec zv_rand +#define dump_zvec zv_dump + +/* type ZMAT */ + +#define get_zmat zm_get +#define freezmat ZM_FREE +#define cp_zmat zm_copy +#define fout_zmat zm_foutput +#define out_zmat zm_output +#define fin_zmat zm_finput +#define in_zmat zm_input +#define zero_zmat zm_zero +#define rand_zmat zm_rand +#define dump_zmat zm_dump + +/* types SPMAT */ + +#define sp_mat SPMAT +#define sp_get_mat sp_get +#define sp_free_mat sp_free +#define sp_cp_mat sp_copy +#define sp_cp_mat2 sp_copy2 +#define sp_fout_mat sp_foutput +#define sp_fout_mat2 sp_foutput2 +#define sp_out_mat sp_output +#define sp_out_mat2 sp_output2 +#define sp_fin_mat sp_finput +#define sp_in_mat sp_input +#define sp_zero_mat sp_zero +#define sp_dump_mat sp_dump + + +/* type SPROW */ + +#define sp_row SPROW +#define sp_get_idx sprow_idx +#define row_xpd sprow_xpd +#define sp_get_row sprow_get +#define row_set_val sprow_set_val +#define fout_row sprow_foutput +#define _row_mltadd sprow_mltadd +#define sp_row_copy sprow_copy +#define sp_row_merge sprow_merge +#define sp_row_ip sprow_ip +#define sp_row_sqr sprow_sqr + + +/* type MAT */ + +#define get_mat m_get +#define freemat M_FREE +#define cp_mat m_copy +#define fout_mat m_foutput +#define out_mat m_output +#define fin_mat m_finput +#define in_mat m_input +#define zero_mat m_zero +#define id_mat m_ident +#define rand_mat m_rand +#define ones_mat m_ones +#define dump_mat m_dump + +/* type VEC */ + +#define get_vec v_get +#define freevec V_FREE +#define cp_vec v_copy +#define fout_vec v_foutput +#define out_vec v_output +#define fin_vec v_finput +#define in_vec v_input +#define zero_vec v_zero +#define rand_vec v_rand +#define ones_vec v_ones +#define dump_vec v_dump + + +/* type PERM */ + +#define get_perm px_get +#define freeperm PX_FREE +#define cp_perm px_copy +#define fout_perm px_foutput +#define out_perm px_output +#define fin_perm px_finput +#define in_perm px_input +#define id_perm px_ident +#define px_id px_ident +#define trans_px px_transp +#define sign_px px_sign +#define dump_perm px_dump + +#endif diff --git a/otherio.c b/otherio.c new file mode 100644 index 0000000..5762080 --- /dev/null +++ b/otherio.c @@ -0,0 +1,180 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File for doing assorted I/O operations not invlolving + MAT/VEC/PERM objects +*/ +static char rcsid[] = "$Id: otherio.c,v 1.2 1994/01/13 05:34:52 des Exp $"; + +#include +#include +#include "matrix.h" + + + +/* scratch area -- enough for a single line */ +static char scratch[MAXLINE+1]; + +/* default value for fy_or_n */ +static int y_n_dflt = TRUE; + +/* fy_or_n -- yes-or-no to question is string s + -- question written to stderr, input from fp + -- if fp is NOT a tty then return y_n_dflt */ +#ifndef ANSI_C +int fy_or_n(fp,s) +FILE *fp; +char *s; +#else +int fy_or_n(FILE *fp, const char *s) +#endif +{ + char *cp; + + if ( ! isatty(fileno(fp)) ) + return y_n_dflt; + + for ( ; ; ) + { + fprintf(stderr,"%s (y/n) ? ",s); + if ( fgets(scratch,MAXLINE,fp)==NULL ) + error(E_INPUT,"fy_or_n"); + cp = scratch; + while ( isspace(*cp) ) + cp++; + if ( *cp == 'y' || *cp == 'Y' ) + return TRUE; + if ( *cp == 'n' || *cp == 'N' ) + return FALSE; + fprintf(stderr,"Please reply with 'y' or 'Y' for yes "); + fprintf(stderr,"and 'n' or 'N' for no.\n"); + } +} + +/* yn_dflt -- sets the value of y_n_dflt to val */ +#ifndef ANSI_C +int yn_dflt(val) +int val; +#else +int yn_dflt(int val) +#endif +{ return y_n_dflt = val; } + +/* fin_int -- return integer read from file/stream fp + -- prompt s on stderr if fp is a tty + -- check that x lies between low and high: re-prompt if + fp is a tty, error exit otherwise + -- ignore check if low > high */ +#ifndef ANSI_C +int fin_int(fp,s,low,high) +FILE *fp; +char *s; +int low, high; +#else +int fin_int(FILE *fp, const char *s, int low, int high) +#endif +{ + int retcode, x; + + if ( ! isatty(fileno(fp)) ) + { + skipjunk(fp); + if ( (retcode=fscanf(fp,"%d",&x)) == EOF ) + error(E_INPUT,"fin_int"); + if ( retcode <= 0 ) + error(E_FORMAT,"fin_int"); + if ( low <= high && ( x < low || x > high ) ) + error(E_BOUNDS,"fin_int"); + return x; + } + + for ( ; ; ) + { + fprintf(stderr,"%s: ",s); + if ( fgets(scratch,MAXLINE,stdin)==NULL ) + error(E_INPUT,"fin_int"); + retcode = sscanf(scratch,"%d",&x); + if ( ( retcode==1 && low > high ) || + ( x >= low && x <= high ) ) + return x; + fprintf(stderr,"Please type an integer in range [%d,%d].\n", + low,high); + } +} + + +/* fin_double -- return double read from file/stream fp + -- prompt s on stderr if fp is a tty + -- check that x lies between low and high: re-prompt if + fp is a tty, error exit otherwise + -- ignore check if low > high */ +#ifndef ANSI_C +double fin_double(fp,s,low,high) +FILE *fp; +char *s; +double low, high; +#else +double fin_double(FILE *fp, const char *s, double low, double high) +#endif +{ + Real retcode, x; + + if ( ! isatty(fileno(fp)) ) + { + skipjunk(fp); +#if REAL == DOUBLE + if ( (retcode=fscanf(fp,"%lf",&x)) == EOF ) +#elif REAL == FLOAT + if ( (retcode=fscanf(fp,"%f",&x)) == EOF ) +#endif + error(E_INPUT,"fin_double"); + if ( retcode <= 0 ) + error(E_FORMAT,"fin_double"); + if ( low <= high && ( x < low || x > high ) ) + error(E_BOUNDS,"fin_double"); + return (double)x; + } + + for ( ; ; ) + { + fprintf(stderr,"%s: ",s); + if ( fgets(scratch,MAXLINE,stdin)==NULL ) + error(E_INPUT,"fin_double"); +#if REAL == DOUBLE + retcode = sscanf(scratch,"%lf",&x); +#elif REAL == FLOAT + retcode = sscanf(scratch,"%f",&x); +#endif + if ( ( retcode==1 && low > high ) || + ( x >= low && x <= high ) ) + return (double)x; + fprintf(stderr,"Please type an double in range [%g,%g].\n", + low,high); + } +} + + diff --git a/pxop.c b/pxop.c new file mode 100644 index 0000000..38cb3ec --- /dev/null +++ b/pxop.c @@ -0,0 +1,393 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* pxop.c 1.5 12/03/87 */ + + +#include +#include "matrix.h" + +static char rcsid[] = "$Id: pxop.c,v 1.6 1995/06/08 14:57:11 des Exp $"; + +/********************************************************************** +Note: A permutation is often interpreted as a matrix + (i.e. a permutation matrix). + A permutation px represents a permutation matrix P where + P[i][j] == 1 if and only if px->pe[i] == j +**********************************************************************/ + + +/* px_inv -- invert permutation -- in situ + -- taken from ACM Collected Algorithms #250 */ +#ifndef ANSI_C +PERM *px_inv(px,out) +PERM *px, *out; +#else +PERM *px_inv(const PERM *px, PERM *out) +#endif +{ + int i, j, k, n, *p; + + out = px_copy(px, out); + n = out->size; + p = (int *)(out->pe); + for ( n--; n>=0; n-- ) + { + i = p[n]; + if ( i < 0 ) p[n] = -1 - i; + else if ( i != n ) + { + k = n; + while (TRUE) + { + if ( i < 0 || i >= out->size ) + error(E_BOUNDS,"px_inv"); + j = p[i]; p[i] = -1 - k; + if ( j == n ) + { p[n] = i; break; } + k = i; i = j; + } + } + } + return out; +} + +/* px_mlt -- permutation multiplication (composition) */ +#ifndef ANSI_C +PERM *px_mlt(px1,px2,out) +PERM *px1,*px2,*out; +#else +PERM *px_mlt(const PERM *px1, const PERM *px2, PERM *out) +#endif +{ + unsigned int i,size; + + if ( px1==(PERM *)NULL || px2==(PERM *)NULL ) + error(E_NULL,"px_mlt"); + if ( px1->size != px2->size ) + error(E_SIZES,"px_mlt"); + if ( px1 == out || px2 == out ) + error(E_INSITU,"px_mlt"); + if ( out==(PERM *)NULL || out->size < px1->size ) + out = px_resize(out,px1->size); + + size = px1->size; + for ( i=0; ipe[i] >= size ) + error(E_BOUNDS,"px_mlt"); + else + out->pe[i] = px1->pe[px2->pe[i]]; + + return out; +} + +/* px_vec -- permute vector */ +#ifndef ANSI_C +VEC *px_vec(px,vector,out) +PERM *px; +VEC *vector,*out; +#else +VEC *px_vec(PERM *px, const VEC *vector, VEC *out) +#endif +{ + unsigned int old_i, i, size, start; + Real tmp; + + if ( px==PNULL || vector==VNULL ) + error(E_NULL,"px_vec"); + if ( px->size > vector->dim ) + error(E_SIZES,"px_vec"); + if ( out==VNULL || out->dim < vector->dim ) + out = v_resize(out,vector->dim); + + size = px->size; + if ( size == 0 ) + return v_copy(vector,out); + if ( out != vector ) + { + for ( i=0; ipe[i] >= size ) + error(E_BOUNDS,"px_vec"); + else + out->ve[i] = vector->ve[px->pe[i]]; + } + else + { /* in situ algorithm */ + start = 0; + while ( start < size ) + { + old_i = start; + i = px->pe[old_i]; + if ( i >= size ) + { + start++; + continue; + } + tmp = vector->ve[start]; + while ( TRUE ) + { + vector->ve[old_i] = vector->ve[i]; + px->pe[old_i] = i+size; + old_i = i; + i = px->pe[old_i]; + if ( i >= size ) + break; + if ( i == start ) + { + vector->ve[old_i] = tmp; + px->pe[old_i] = i+size; + break; + } + } + start++; + } + + for ( i = 0; i < size; i++ ) + if ( px->pe[i] < size ) + error(E_BOUNDS,"px_vec"); + else + px->pe[i] = px->pe[i]-size; + } + + return out; +} + +/* pxinv_vec -- apply the inverse of px to x, returning the result in out */ +#ifndef ANSI_C +VEC *pxinv_vec(px,x,out) +PERM *px; +VEC *x, *out; +#else +VEC *pxinv_vec(PERM *px, const VEC *x, VEC *out) +#endif +{ + unsigned int i, size; + + if ( ! px || ! x ) + error(E_NULL,"pxinv_vec"); + if ( px->size > x->dim ) + error(E_SIZES,"pxinv_vec"); + /* if ( x == out ) + error(E_INSITU,"pxinv_vec"); */ + if ( ! out || out->dim < x->dim ) + out = v_resize(out,x->dim); + + size = px->size; + if ( size == 0 ) + return v_copy(x,out); + if ( out != x ) + { + for ( i=0; ipe[i] >= size ) + error(E_BOUNDS,"pxinv_vec"); + else + out->ve[px->pe[i]] = x->ve[i]; + } + else + { /* in situ algorithm --- cheat's way out */ + px_inv(px,px); + px_vec(px,x,out); + px_inv(px,px); + } + + return out; +} + + + +/* px_transp -- transpose elements of permutation + -- Really multiplying a permutation by a transposition */ +#ifndef ANSI_C +PERM *px_transp(px,i1,i2) +PERM *px; /* permutation to transpose */ +unsigned int i1,i2; /* elements to transpose */ +#else +PERM *px_transp(PERM *px, unsigned int i1, unsigned int i2) +#endif +{ + unsigned int temp; + + if ( px==(PERM *)NULL ) + error(E_NULL,"px_transp"); + + if ( i1 < px->size && i2 < px->size ) + { + temp = px->pe[i1]; + px->pe[i1] = px->pe[i2]; + px->pe[i2] = temp; + } + + return px; +} + +/* myqsort -- a cheap implementation of Quicksort on integers + -- returns number of swaps */ +#ifndef ANSI_C +static int myqsort(a,num) +int *a, num; +#else +static int myqsort(int *a, int num) +#endif +{ + int i, j, tmp, v; + int numswaps; + + numswaps = 0; + if ( num <= 1 ) + return 0; + + i = 0; j = num; v = a[0]; + for ( ; ; ) + { + while ( a[++i] < v ) + ; + while ( a[--j] > v ) + ; + if ( i >= j ) break; + + tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + numswaps++; + } + + tmp = a[0]; + a[0] = a[j]; + a[j] = tmp; + if ( j != 0 ) + numswaps++; + + numswaps += myqsort(&a[0],j); + numswaps += myqsort(&a[j+1],num-(j+1)); + + return numswaps; +} + + +/* px_sign -- compute the ``sign'' of a permutation = +/-1 where + px is the product of an even/odd # transpositions */ +#ifndef ANSI_C +int px_sign(px) +PERM *px; +#else +int px_sign(const PERM *px) +#endif +{ + int numtransp; + PERM *px2; + + if ( px==(PERM *)NULL ) + error(E_NULL,"px_sign"); + px2 = px_copy(px,PNULL); + numtransp = myqsort((int *)px2->pe,px2->size); + px_free(px2); + + return ( numtransp % 2 ) ? -1 : 1; +} + + +/* px_cols -- permute columns of matrix A; out = A.px' + -- May NOT be in situ */ +#ifndef ANSI_C +MAT *px_cols(px,A,out) +PERM *px; +MAT *A, *out; +#else +MAT *px_cols(const PERM *px, const MAT *A, MAT *out) +#endif +{ + int i, j, m, n, px_j; + Real **A_me, **out_me; +#ifdef ANSI_C + MAT *m_get(int, int); +#else + extern MAT *m_get(); +#endif + + if ( ! A || ! px ) + error(E_NULL,"px_cols"); + if ( px->size != A->n ) + error(E_SIZES,"px_cols"); + if ( A == out ) + error(E_INSITU,"px_cols"); + m = A->m; n = A->n; + if ( ! out || out->m != m || out->n != n ) + out = m_get(m,n); + A_me = A->me; out_me = out->me; + + for ( j = 0; j < n; j++ ) + { + px_j = px->pe[j]; + if ( px_j >= n ) + error(E_BOUNDS,"px_cols"); + for ( i = 0; i < m; i++ ) + out_me[i][px_j] = A_me[i][j]; + } + + return out; +} + +/* px_rows -- permute columns of matrix A; out = px.A + -- May NOT be in situ */ +#ifndef ANSI_C +MAT *px_rows(px,A,out) +PERM *px; +MAT *A, *out; +#else +MAT *px_rows(const PERM *px, const MAT *A, MAT *out) +#endif +{ + int i, j, m, n, px_i; + Real **A_me, **out_me; +#ifdef ANSI_C + MAT *m_get(int, int); +#else + extern MAT *m_get(); +#endif + + if ( ! A || ! px ) + error(E_NULL,"px_rows"); + if ( px->size != A->m ) + error(E_SIZES,"px_rows"); + if ( A == out ) + error(E_INSITU,"px_rows"); + m = A->m; n = A->n; + if ( ! out || out->m != m || out->n != n ) + out = m_get(m,n); + A_me = A->me; out_me = out->me; + + for ( i = 0; i < m; i++ ) + { + px_i = px->pe[i]; + if ( px_i >= m ) + error(E_BOUNDS,"px_rows"); + for ( j = 0; j < n; j++ ) + out_me[i][j] = A_me[px_i][j]; + } + + return out; +} + diff --git a/qrfactor.c b/qrfactor.c new file mode 100644 index 0000000..90c36c7 --- /dev/null +++ b/qrfactor.c @@ -0,0 +1,583 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains the routines needed to perform QR factorisation + of matrices, as well as Householder transformations. + The internal "factored form" of a matrix A is not quite standard. + The diagonal of A is replaced by the diagonal of R -- not by the 1st non-zero + entries of the Householder vectors. The 1st non-zero entries are held in + the diag parameter of QRfactor(). The reason for this non-standard + representation is that it enables direct use of the Usolve() function + rather than requiring that a seperate function be written just for this case. + See, e.g., QRsolve() below for more details. + +*/ + + +static char rcsid[] = "$Id: qrfactor.c,v 1.5 1994/01/13 05:35:07 des Exp $"; + +#include +#include +#include "matrix2.h" + + + + + +#define sign(x) ((x) > 0.0 ? 1 : ((x) < 0.0 ? -1 : 0 )) + +extern VEC *Usolve(); /* See matrix2.h */ + +/* Note: The usual representation of a Householder transformation is taken + to be: + P = I - beta.u.uT + where beta = 2/(uT.u) and u is called the Householder vector + */ + +/* QRfactor -- forms the QR factorisation of A -- factorisation stored in + compact form as described above ( not quite standard format ) */ +#ifndef ANSI_C +MAT *QRfactor(A,diag) +MAT *A; +VEC *diag; +#else +MAT *QRfactor(MAT *A, VEC *diag) +#endif +{ + unsigned int k,limit; + Real beta; + STATIC VEC *hh=VNULL, *w=VNULL; + + if ( ! A || ! diag ) + error(E_NULL,"QRfactor"); + limit = min(A->m,A->n); + if ( diag->dim < limit ) + error(E_SIZES,"QRfactor"); + + hh = v_resize(hh,A->m); + w = v_resize(w, A->n); + MEM_STAT_REG(hh,TYPE_VEC); + MEM_STAT_REG(w, TYPE_VEC); + + for ( k=0; kve[k],hh,&A->me[k][k]); */ + hhvec(hh,k,&beta,hh,&A->me[k][k]); + diag->ve[k] = hh->ve[k]; + + /* apply H/holder vector to remaining columns */ + /* hhtrcols(A,k,k+1,hh,beta->ve[k]); */ + _hhtrcols(A,k,k+1,hh,beta,w); + } + +#ifdef THREADSAFE + V_FREE(hh); V_FREE(w); +#endif + + return (A); +} + +/* QRCPfactor -- forms the QR factorisation of A with column pivoting + -- factorisation stored in compact form as described above + ( not quite standard format ) */ +#ifndef ANSI_C +MAT *QRCPfactor(A,diag,px) +MAT *A; +VEC *diag; +PERM *px; +#else +MAT *QRCPfactor(MAT *A, VEC *diag, PERM *px) +#endif +{ + unsigned int i, i_max, j, k, limit; + STATIC VEC *gamma=VNULL, *tmp1=VNULL, *tmp2=VNULL, *w=VNULL; + Real beta, maxgamma, sum, tmp; + + if ( ! A || ! diag || ! px ) + error(E_NULL,"QRCPfactor"); + limit = min(A->m,A->n); + if ( diag->dim < limit || px->size != A->n ) + error(E_SIZES,"QRCPfactor"); + + tmp1 = v_resize(tmp1,A->m); + tmp2 = v_resize(tmp2,A->m); + gamma = v_resize(gamma,A->n); + w = v_resize(w, A->n); + MEM_STAT_REG(tmp1,TYPE_VEC); + MEM_STAT_REG(tmp2,TYPE_VEC); + MEM_STAT_REG(gamma,TYPE_VEC); + MEM_STAT_REG(w, TYPE_VEC); + + /* initialise gamma and px */ + for ( j=0; jn; j++ ) + { + px->pe[j] = j; + sum = 0.0; + for ( i=0; im; i++ ) + sum += square(A->me[i][j]); + gamma->ve[j] = sum; + } + + for ( k=0; kve[k]; + for ( i=k+1; in; i++ ) + /* Loop invariant:maxgamma=gamma[i_max] + >=gamma[l];l=k,...,i-1 */ + if ( gamma->ve[i] > maxgamma ) + { maxgamma = gamma->ve[i]; i_max = i; } + + /* swap columns if necessary */ + if ( i_max != k ) + { + /* swap gamma values */ + tmp = gamma->ve[k]; + gamma->ve[k] = gamma->ve[i_max]; + gamma->ve[i_max] = tmp; + + /* update column permutation */ + px_transp(px,k,i_max); + + /* swap columns of A */ + for ( i=0; im; i++ ) + { + tmp = A->me[i][k]; + A->me[i][k] = A->me[i][i_max]; + A->me[i][i_max] = tmp; + } + } + + /* get H/holder vector for the k-th column */ + get_col(A,k,tmp1); + /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */ + hhvec(tmp1,k,&beta,tmp1,&A->me[k][k]); + diag->ve[k] = tmp1->ve[k]; + + /* apply H/holder vector to remaining columns */ + /* hhtrcols(A,k,k+1,tmp1,beta->ve[k]); */ + _hhtrcols(A,k,k+1,tmp1,beta,w); + + /* update gamma values */ + for ( j=k+1; jn; j++ ) + gamma->ve[j] -= square(A->me[k][j]); + } + +#ifdef THREADSAFE + V_FREE(gamma); V_FREE(tmp1); V_FREE(tmp2); V_FREE(w); +#endif + + return (A); +} + +/* Qsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact + form a la QRfactor() -- may be in-situ */ +#ifndef ANSI_C +VEC *_Qsolve(QR,diag,b,x,tmp) +MAT *QR; +VEC *diag, *b, *x, *tmp; +#else +VEC *_Qsolve(const MAT *QR, const VEC *diag, const VEC *b, + VEC *x, VEC *tmp) +#endif +{ + unsigned int dynamic; + int k, limit; + Real beta, r_ii, tmp_val; + + limit = min(QR->m,QR->n); + dynamic = FALSE; + if ( ! QR || ! diag || ! b ) + error(E_NULL,"_Qsolve"); + if ( diag->dim < limit || b->dim != QR->m ) + error(E_SIZES,"_Qsolve"); + x = v_resize(x,QR->m); + if ( tmp == VNULL ) + dynamic = TRUE; + tmp = v_resize(tmp,QR->m); + + /* apply H/holder transforms in normal order */ + x = v_copy(b,x); + for ( k = 0 ; k < limit ; k++ ) + { + get_col(QR,k,tmp); + r_ii = fabs(tmp->ve[k]); + tmp->ve[k] = diag->ve[k]; + tmp_val = (r_ii*fabs(diag->ve[k])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + /* hhtrvec(tmp,beta->ve[k],k,x,x); */ + hhtrvec(tmp,beta,k,x,x); + } + + if ( dynamic ) + V_FREE(tmp); + + return (x); +} + +/* makeQ -- constructs orthogonal matrix from Householder vectors stored in + compact QR form */ +#ifndef ANSI_C +MAT *makeQ(QR,diag,Qout) +MAT *QR,*Qout; +VEC *diag; +#else +MAT *makeQ(const MAT *QR,const VEC *diag, MAT *Qout) +#endif +{ + STATIC VEC *tmp1=VNULL,*tmp2=VNULL; + unsigned int i, limit; + Real beta, r_ii, tmp_val; + int j; + + limit = min(QR->m,QR->n); + if ( ! QR || ! diag ) + error(E_NULL,"makeQ"); + if ( diag->dim < limit ) + error(E_SIZES,"makeQ"); + if ( Qout==(MAT *)NULL || Qout->m < QR->m || Qout->n < QR->m ) + Qout = m_get(QR->m,QR->m); + + tmp1 = v_resize(tmp1,QR->m); /* contains basis vec & columns of Q */ + tmp2 = v_resize(tmp2,QR->m); /* contains H/holder vectors */ + MEM_STAT_REG(tmp1,TYPE_VEC); + MEM_STAT_REG(tmp2,TYPE_VEC); + + for ( i=0; im ; i++ ) + { /* get i-th column of Q */ + /* set up tmp1 as i-th basis vector */ + for ( j=0; jm ; j++ ) + tmp1->ve[j] = 0.0; + tmp1->ve[i] = 1.0; + + /* apply H/h transforms in reverse order */ + for ( j=limit-1; j>=0; j-- ) + { + get_col(QR,j,tmp2); + r_ii = fabs(tmp2->ve[j]); + tmp2->ve[j] = diag->ve[j]; + tmp_val = (r_ii*fabs(diag->ve[j])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + /* hhtrvec(tmp2,beta->ve[j],j,tmp1,tmp1); */ + hhtrvec(tmp2,beta,j,tmp1,tmp1); + } + + /* insert into Q */ + set_col(Qout,i,tmp1); + } + +#ifdef THREADSAFE + V_FREE(tmp1); V_FREE(tmp2); +#endif + + return (Qout); +} + +/* makeR -- constructs upper triangular matrix from QR (compact form) + -- may be in-situ (all it does is zero the lower 1/2) */ +#ifndef ANSI_C +MAT *makeR(QR,Rout) +MAT *QR,*Rout; +#else +MAT *makeR(const MAT *QR, MAT *Rout) +#endif +{ + unsigned int i,j; + + if ( QR==MNULL ) + error(E_NULL,"makeR"); + Rout = m_copy(QR,Rout); + + for ( i=1; im; i++ ) + for ( j=0; jn && jme[i][j] = 0.0; + + return (Rout); +} + +/* QRsolve -- solves the system Q.R.x=b where Q & R are stored in compact form + -- returns x, which is created if necessary */ +#ifndef ANSI_C +VEC *QRsolve(QR,diag,b,x) +MAT *QR; +VEC *diag /* , *beta */ , *b, *x; +#else +VEC *QRsolve(const MAT *QR, const VEC *diag, const VEC *b, VEC *x) +#endif +{ + int limit; + STATIC VEC *tmp = VNULL; + + if ( ! QR || ! diag || ! b ) + error(E_NULL,"QRsolve"); + limit = min(QR->m,QR->n); + if ( diag->dim < limit || b->dim != QR->m ) + error(E_SIZES,"QRsolve"); + tmp = v_resize(tmp,limit); + MEM_STAT_REG(tmp,TYPE_VEC); + + x = v_resize(x,QR->n); + _Qsolve(QR,diag,b,x,tmp); + x = Usolve(QR,x,x,0.0); + v_resize(x,QR->n); + +#ifdef THREADSAFE + V_FREE(tmp); +#endif + + return x; +} + +/* QRCPsolve -- solves A.x = b where A is factored by QRCPfactor() + -- assumes that A is in the compact factored form */ +#ifndef ANSI_C +VEC *QRCPsolve(QR,diag,pivot,b,x) +MAT *QR; +VEC *diag; +PERM *pivot; +VEC *b, *x; +#else +VEC *QRCPsolve(const MAT *QR, const VEC *diag, PERM *pivot, + const VEC *b, VEC *x) +#endif +{ + STATIC VEC *tmp=VNULL; + + if ( ! QR || ! diag || ! pivot || ! b ) + error(E_NULL,"QRCPsolve"); + if ( (QR->m > diag->dim &&QR->n > diag->dim) || QR->n != pivot->size ) + error(E_SIZES,"QRCPsolve"); + + tmp = QRsolve(QR,diag,b,tmp); + MEM_STAT_REG(tmp,TYPE_VEC); + x = pxinv_vec(pivot,tmp,x); + +#ifdef THREADSAFE + V_FREE(tmp); +#endif + + return x; +} + +/* Umlt -- compute out = upper_triang(U).x + -- may be in situ */ +#ifndef ANSI_C +static VEC *Umlt(U,x,out) +MAT *U; +VEC *x, *out; +#else +static VEC *Umlt(const MAT *U, const VEC *x, VEC *out) +#endif +{ + int i, limit; + + if ( U == MNULL || x == VNULL ) + error(E_NULL,"Umlt"); + limit = min(U->m,U->n); + if ( limit != x->dim ) + error(E_SIZES,"Umlt"); + if ( out == VNULL || out->dim < limit ) + out = v_resize(out,limit); + + for ( i = 0; i < limit; i++ ) + out->ve[i] = __ip__(&(x->ve[i]),&(U->me[i][i]),limit - i); + return out; +} + +/* UTmlt -- returns out = upper_triang(U)^T.x */ +#ifndef ANSI_C +static VEC *UTmlt(U,x,out) +MAT *U; +VEC *x, *out; +#else +static VEC *UTmlt(const MAT *U, const VEC *x, VEC *out) +#endif +{ + Real sum; + int i, j, limit; + + if ( U == MNULL || x == VNULL ) + error(E_NULL,"UTmlt"); + limit = min(U->m,U->n); + if ( out == VNULL || out->dim < limit ) + out = v_resize(out,limit); + + for ( i = limit-1; i >= 0; i-- ) + { + sum = 0.0; + for ( j = 0; j <= i; j++ ) + sum += U->me[j][i]*x->ve[j]; + out->ve[i] = sum; + } + return out; +} + +/* QRTsolve -- solve A^T.sc = c where the QR factors of A are stored in + compact form + -- returns sc + -- original due to Mike Osborne modified Wed 09th Dec 1992 */ +#ifndef ANSI_C +VEC *QRTsolve(A,diag,c,sc) +MAT *A; +VEC *diag, *c, *sc; +#else +VEC *QRTsolve(const MAT *A, const VEC *diag, const VEC *c, VEC *sc) +#endif +{ + int i, j, k, n, p; + Real beta, r_ii, s, tmp_val; + + if ( ! A || ! diag || ! c ) + error(E_NULL,"QRTsolve"); + if ( diag->dim < min(A->m,A->n) ) + error(E_SIZES,"QRTsolve"); + sc = v_resize(sc,A->m); + n = sc->dim; + p = c->dim; + if ( n == p ) + k = p-2; + else + k = p-1; + v_zero(sc); + sc->ve[0] = c->ve[0]/A->me[0][0]; + if ( n == 1) + return sc; + if ( p > 1) + { + for ( i = 1; i < p; i++ ) + { + s = 0.0; + for ( j = 0; j < i; j++ ) + s += A->me[j][i]*sc->ve[j]; + if ( A->me[i][i] == 0.0 ) + error(E_SING,"QRTsolve"); + sc->ve[i]=(c->ve[i]-s)/A->me[i][i]; + } + } + for (i = k; i >= 0; i--) + { + s = diag->ve[i]*sc->ve[i]; + for ( j = i+1; j < n; j++ ) + s += A->me[j][i]*sc->ve[j]; + r_ii = fabs(A->me[i][i]); + tmp_val = (r_ii*fabs(diag->ve[i])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + tmp_val = beta*s; + sc->ve[i] -= tmp_val*diag->ve[i]; + for ( j = i+1; j < n; j++ ) + sc->ve[j] -= tmp_val*A->me[j][i]; + } + + return sc; +} + +/* QRcondest -- returns an estimate of the 2-norm condition number of the + matrix factorised by QRfactor() or QRCPfactor() + -- note that as Q does not affect the 2-norm condition number, + it is not necessary to pass the diag, beta (or pivot) vectors + -- generates a lower bound on the true condition number + -- if the matrix is exactly singular, HUGE_VAL is returned + -- note that QRcondest() is likely to be more reliable for + matrices factored using QRCPfactor() */ +#ifndef ANSI_C +double QRcondest(QR) +MAT *QR; +#else +double QRcondest(const MAT *QR) +#endif +{ + STATIC VEC *y=VNULL; + Real norm1, norm2, sum, tmp1, tmp2; + int i, j, limit; + + if ( QR == MNULL ) + error(E_NULL,"QRcondest"); + + limit = min(QR->m,QR->n); + for ( i = 0; i < limit; i++ ) + if ( QR->me[i][i] == 0.0 ) + return HUGE_VAL; + + y = v_resize(y,limit); + MEM_STAT_REG(y,TYPE_VEC); + /* use the trick for getting a unit vector y with ||R.y||_inf small + from the LU condition estimator */ + for ( i = 0; i < limit; i++ ) + { + sum = 0.0; + for ( j = 0; j < i; j++ ) + sum -= QR->me[j][i]*y->ve[j]; + sum -= (sum < 0.0) ? 1.0 : -1.0; + y->ve[i] = sum / QR->me[i][i]; + } + UTmlt(QR,y,y); + + /* now apply inverse power method to R^T.R */ + for ( i = 0; i < 3; i++ ) + { + tmp1 = v_norm2(y); + sv_mlt(1/tmp1,y,y); + UTsolve(QR,y,y,0.0); + tmp2 = v_norm2(y); + sv_mlt(1/v_norm2(y),y,y); + Usolve(QR,y,y,0.0); + } + /* now compute approximation for ||R^{-1}||_2 */ + norm1 = sqrt(tmp1)*sqrt(tmp2); + + /* now use complementary approach to compute approximation to ||R||_2 */ + for ( i = limit-1; i >= 0; i-- ) + { + sum = 0.0; + for ( j = i+1; j < limit; j++ ) + sum += QR->me[i][j]*y->ve[j]; + y->ve[i] = (sum >= 0.0) ? 1.0 : -1.0; + y->ve[i] = (QR->me[i][i] >= 0.0) ? y->ve[i] : - y->ve[i]; + } + + /* now apply power method to R^T.R */ + for ( i = 0; i < 3; i++ ) + { + tmp1 = v_norm2(y); + sv_mlt(1/tmp1,y,y); + Umlt(QR,y,y); + tmp2 = v_norm2(y); + sv_mlt(1/tmp2,y,y); + UTmlt(QR,y,y); + } + norm2 = sqrt(tmp1)*sqrt(tmp2); + + /* printf("QRcondest: norm1 = %g, norm2 = %g\n",norm1,norm2); */ + +#ifdef THREADSAFE + V_FREE(y); +#endif + + return norm1*norm2; +} diff --git a/rk4.dat b/rk4.dat new file mode 100644 index 0000000..ac656c3 --- /dev/null +++ b/rk4.dat @@ -0,0 +1,12 @@ +# No. of a problem +1 +# Initial time +0 +# Final time +1 +# Solution is x(t) = (cos(t),-sin(t)) +# x(0) = +Vector: dim: 2 +1 0 +# Step size +0.1 diff --git a/schur.c b/schur.c new file mode 100644 index 0000000..416f338 --- /dev/null +++ b/schur.c @@ -0,0 +1,692 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File containing routines for computing the Schur decomposition + of a real non-symmetric matrix + See also: hessen.c +*/ + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +static char rcsid[] = "$Id: schur.c,v 1.7 1994/03/17 05:36:53 des Exp $"; + + + +#ifndef ANSI_C +static void hhldr3(x,y,z,nu1,beta,newval) +double x, y, z; +Real *nu1, *beta, *newval; +#else +static void hhldr3(double x, double y, double z, + Real *nu1, Real *beta, Real *newval) +#endif +{ + Real alpha; + + if ( x >= 0.0 ) + alpha = sqrt(x*x+y*y+z*z); + else + alpha = -sqrt(x*x+y*y+z*z); + *nu1 = x + alpha; + *beta = 1.0/(alpha*(*nu1)); + *newval = alpha; +} + +#ifndef ANSI_C +static void hhldr3cols(A,k,j0,beta,nu1,nu2,nu3) +MAT *A; +int k, j0; +double beta, nu1, nu2, nu3; +#else +static void hhldr3cols(MAT *A, int k, int j0, double beta, + double nu1, double nu2, double nu3) +#endif +{ + Real **A_me, ip, prod; + int j, n; + + if ( k < 0 || k+3 > A->m || j0 < 0 ) + error(E_BOUNDS,"hhldr3cols"); + A_me = A->me; n = A->n; + + /* printf("hhldr3cols:(l.%d) j0 = %d, k = %d, A at 0x%lx, m = %d, n = %d\n", + __LINE__, j0, k, (long)A, A->m, A->n); */ + /* printf("hhldr3cols: A (dumped) =\n"); m_dump(stdout,A); */ + + for ( j = j0; j < n; j++ ) + { + /***** + ip = nu1*A_me[k][j] + nu2*A_me[k+1][j] + nu3*A_me[k+2][j]; + prod = ip*beta; + A_me[k][j] -= prod*nu1; + A_me[k+1][j] -= prod*nu2; + A_me[k+2][j] -= prod*nu3; + *****/ + /* printf("hhldr3cols: j = %d\n", j); */ + + ip = nu1*m_entry(A,k,j)+nu2*m_entry(A,k+1,j)+nu3*m_entry(A,k+2,j); + prod = ip*beta; + /***** + m_set_val(A,k ,j,m_entry(A,k ,j) - prod*nu1); + m_set_val(A,k+1,j,m_entry(A,k+1,j) - prod*nu2); + m_set_val(A,k+2,j,m_entry(A,k+2,j) - prod*nu3); + *****/ + m_add_val(A,k ,j,-prod*nu1); + m_add_val(A,k+1,j,-prod*nu2); + m_add_val(A,k+2,j,-prod*nu3); + + } + /* printf("hhldr3cols:(l.%d) j0 = %d, k = %d, m = %d, n = %d\n", + __LINE__, j0, k, A->m, A->n); */ + /* putc('\n',stdout); */ +} + +#ifndef ANSI_C +static void hhldr3rows(A,k,i0,beta,nu1,nu2,nu3) +MAT *A; +int k, i0; +double beta, nu1, nu2, nu3; +#else +static void hhldr3rows(MAT *A, int k, int i0, double beta, + double nu1, double nu2, double nu3) +#endif +{ + Real **A_me, ip, prod; + int i, m; + + /* printf("hhldr3rows:(l.%d) A at 0x%lx\n", __LINE__, (long)A); */ + /* printf("hhldr3rows: k = %d\n", k); */ + if ( k < 0 || k+3 > A->n ) + error(E_BOUNDS,"hhldr3rows"); + A_me = A->me; m = A->m; + i0 = min(i0,m-1); + + for ( i = 0; i <= i0; i++ ) + { + /**** + ip = nu1*A_me[i][k] + nu2*A_me[i][k+1] + nu3*A_me[i][k+2]; + prod = ip*beta; + A_me[i][k] -= prod*nu1; + A_me[i][k+1] -= prod*nu2; + A_me[i][k+2] -= prod*nu3; + ****/ + + ip = nu1*m_entry(A,i,k)+nu2*m_entry(A,i,k+1)+nu3*m_entry(A,i,k+2); + prod = ip*beta; + m_add_val(A,i,k , - prod*nu1); + m_add_val(A,i,k+1, - prod*nu2); + m_add_val(A,i,k+2, - prod*nu3); + + } +} + +/* schur -- computes the Schur decomposition of the matrix A in situ + -- optionally, gives Q matrix such that Q^T.A.Q is upper triangular + -- returns upper triangular Schur matrix */ +#ifndef ANSI_C +MAT *schur(A,Q) +MAT *A, *Q; +#else +MAT *schur(MAT *A, MAT *Q) +#endif +{ + int i, j, iter, k, k_min, k_max, k_tmp, n, split; + Real beta2, c, discrim, dummy, nu1, s, t, tmp, x, y, z; + Real **A_me; + Real sqrt_macheps; + STATIC VEC *diag=VNULL, *beta=VNULL; + + if ( ! A ) + error(E_NULL,"schur"); + if ( A->m != A->n || ( Q && Q->m != Q->n ) ) + error(E_SQUARE,"schur"); + if ( Q != MNULL && Q->m != A->m ) + error(E_SIZES,"schur"); + n = A->n; + diag = v_resize(diag,A->n); + beta = v_resize(beta,A->n); + MEM_STAT_REG(diag,TYPE_VEC); + MEM_STAT_REG(beta,TYPE_VEC); + /* compute Hessenberg form */ + Hfactor(A,diag,beta); + + /* save Q if necessary */ + if ( Q ) + Q = makeHQ(A,diag,beta,Q); + makeH(A,A); + + sqrt_macheps = sqrt(MACHEPS); + + k_min = 0; A_me = A->me; + + while ( k_min < n ) + { + Real a00, a01, a10, a11; + double scale, t, numer, denom; + + /* find k_max to suit: + submatrix k_min..k_max should be irreducible */ + k_max = n-1; + for ( k = k_min; k < k_max; k++ ) + /* if ( A_me[k+1][k] == 0.0 ) */ + if ( m_entry(A,k+1,k) == 0.0 ) + { k_max = k; break; } + + if ( k_max <= k_min ) + { + k_min = k_max + 1; + continue; /* outer loop */ + } + + /* check to see if we have a 2 x 2 block + with complex eigenvalues */ + if ( k_max == k_min + 1 ) + { + /* tmp = A_me[k_min][k_min] - A_me[k_max][k_max]; */ + a00 = m_entry(A,k_min,k_min); + a01 = m_entry(A,k_min,k_max); + a10 = m_entry(A,k_max,k_min); + a11 = m_entry(A,k_max,k_max); + tmp = a00 - a11; + /* discrim = tmp*tmp + + 4*A_me[k_min][k_max]*A_me[k_max][k_min]; */ + discrim = tmp*tmp + 4*a01*a10; + if ( discrim < 0.0 ) + { /* yes -- e-vals are complex + -- put 2 x 2 block in form [a b; c a]; + then eigenvalues have real part a & imag part sqrt(|bc|) */ + numer = - tmp; + denom = ( a01+a10 >= 0.0 ) ? + (a01+a10) + sqrt((a01+a10)*(a01+a10)+tmp*tmp) : + (a01+a10) - sqrt((a01+a10)*(a01+a10)+tmp*tmp); + if ( denom != 0.0 ) + { /* t = s/c = numer/denom */ + t = numer/denom; + scale = c = 1.0/sqrt(1+t*t); + s = c*t; + } + else + { + c = 1.0; + s = 0.0; + } + rot_cols(A,k_min,k_max,c,s,A); + rot_rows(A,k_min,k_max,c,s,A); + if ( Q != MNULL ) + rot_cols(Q,k_min,k_max,c,s,Q); + k_min = k_max + 1; + continue; + } + else /* discrim >= 0; i.e. block has two real eigenvalues */ + { /* no -- e-vals are not complex; + split 2 x 2 block and continue */ + /* s/c = numer/denom */ + numer = ( tmp >= 0.0 ) ? + - tmp - sqrt(discrim) : - tmp + sqrt(discrim); + denom = 2*a01; + if ( fabs(numer) < fabs(denom) ) + { /* t = s/c = numer/denom */ + t = numer/denom; + scale = c = 1.0/sqrt(1+t*t); + s = c*t; + } + else if ( numer != 0.0 ) + { /* t = c/s = denom/numer */ + t = denom/numer; + scale = 1.0/sqrt(1+t*t); + c = fabs(t)*scale; + s = ( t >= 0.0 ) ? scale : -scale; + } + else /* numer == denom == 0 */ + { + c = 0.0; + s = 1.0; + } + rot_cols(A,k_min,k_max,c,s,A); + rot_rows(A,k_min,k_max,c,s,A); + /* A->me[k_max][k_min] = 0.0; */ + if ( Q != MNULL ) + rot_cols(Q,k_min,k_max,c,s,Q); + k_min = k_max + 1; /* go to next block */ + continue; + } + } + + /* now have r x r block with r >= 2: + apply Francis QR step until block splits */ + split = FALSE; iter = 0; + while ( ! split ) + { + iter++; + + /* set up Wilkinson/Francis complex shift */ + k_tmp = k_max - 1; + + a00 = m_entry(A,k_tmp,k_tmp); + a01 = m_entry(A,k_tmp,k_max); + a10 = m_entry(A,k_max,k_tmp); + a11 = m_entry(A,k_max,k_max); + + /* treat degenerate cases differently + -- if there are still no splits after five iterations + and the bottom 2 x 2 looks degenerate, force it to + split */ +#ifdef DEBUG + printf("# schur: bottom 2 x 2 = [%lg, %lg; %lg, %lg]\n", + a00, a01, a10, a11); +#endif + if ( iter >= 5 && + fabs(a00-a11) < sqrt_macheps*(fabs(a00)+fabs(a11)) && + (fabs(a01) < sqrt_macheps*(fabs(a00)+fabs(a11)) || + fabs(a10) < sqrt_macheps*(fabs(a00)+fabs(a11))) ) + { + if ( fabs(a01) < sqrt_macheps*(fabs(a00)+fabs(a11)) ) + m_set_val(A,k_tmp,k_max,0.0); + if ( fabs(a10) < sqrt_macheps*(fabs(a00)+fabs(a11)) ) + { + m_set_val(A,k_max,k_tmp,0.0); + split = TRUE; + continue; + } + } + + s = a00 + a11; + t = a00*a11 - a01*a10; + + /* break loop if a 2 x 2 complex block */ + if ( k_max == k_min + 1 && s*s < 4.0*t ) + { + split = TRUE; + continue; + } + + /* perturb shift if convergence is slow */ + if ( (iter % 10) == 0 ) + { s += iter*0.02; t += iter*0.02; + } + + /* set up Householder transformations */ + k_tmp = k_min + 1; + /******************** + x = A_me[k_min][k_min]*A_me[k_min][k_min] + + A_me[k_min][k_tmp]*A_me[k_tmp][k_min] - + s*A_me[k_min][k_min] + t; + y = A_me[k_tmp][k_min]* + (A_me[k_min][k_min]+A_me[k_tmp][k_tmp]-s); + if ( k_min + 2 <= k_max ) + z = A_me[k_tmp][k_min]*A_me[k_min+2][k_tmp]; + else + z = 0.0; + ********************/ + + a00 = m_entry(A,k_min,k_min); + a01 = m_entry(A,k_min,k_tmp); + a10 = m_entry(A,k_tmp,k_min); + a11 = m_entry(A,k_tmp,k_tmp); + + /******************** + a00 = A->me[k_min][k_min]; + a01 = A->me[k_min][k_tmp]; + a10 = A->me[k_tmp][k_min]; + a11 = A->me[k_tmp][k_tmp]; + ********************/ + x = a00*a00 + a01*a10 - s*a00 + t; + y = a10*(a00+a11-s); + if ( k_min + 2 <= k_max ) + z = a10* /* m_entry(A,k_min+2,k_tmp) */ A->me[k_min+2][k_tmp]; + else + z = 0.0; + + for ( k = k_min; k <= k_max-1; k++ ) + { + if ( k < k_max - 1 ) + { + hhldr3(x,y,z,&nu1,&beta2,&dummy); + tracecatch(hhldr3cols(A,k,max(k-1,0), beta2,nu1,y,z),"schur"); + tracecatch(hhldr3rows(A,k,min(n-1,k+3),beta2,nu1,y,z),"schur"); + if ( Q != MNULL ) + hhldr3rows(Q,k,n-1,beta2,nu1,y,z); + } + else + { + givens(x,y,&c,&s); + rot_cols(A,k,k+1,c,s,A); + rot_rows(A,k,k+1,c,s,A); + if ( Q ) + rot_cols(Q,k,k+1,c,s,Q); + } + /* if ( k >= 2 ) + m_set_val(A,k,k-2,0.0); */ + /* x = A_me[k+1][k]; */ + x = m_entry(A,k+1,k); + if ( k <= k_max - 2 ) + /* y = A_me[k+2][k];*/ + y = m_entry(A,k+2,k); + else + y = 0.0; + if ( k <= k_max - 3 ) + /* z = A_me[k+3][k]; */ + z = m_entry(A,k+3,k); + else + z = 0.0; + } + /* if ( k_min > 0 ) + m_set_val(A,k_min,k_min-1,0.0); + if ( k_max < n - 1 ) + m_set_val(A,k_max+1,k_max,0.0); */ + for ( k = k_min; k <= k_max-2; k++ ) + { + /* zero appropriate sub-diagonals */ + m_set_val(A,k+2,k,0.0); + if ( k < k_max-2 ) + m_set_val(A,k+3,k,0.0); + } + + /* test to see if matrix should split */ + for ( k = k_min; k < k_max; k++ ) + if ( fabs(A_me[k+1][k]) < MACHEPS* + (fabs(A_me[k][k])+fabs(A_me[k+1][k+1])) ) + { A_me[k+1][k] = 0.0; split = TRUE; } + } + } + + /* polish up A by zeroing strictly lower triangular elements + and small sub-diagonal elements */ + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < i-1; j++ ) + A_me[i][j] = 0.0; + for ( i = 0; i < A->m - 1; i++ ) + if ( fabs(A_me[i+1][i]) < MACHEPS* + (fabs(A_me[i][i])+fabs(A_me[i+1][i+1])) ) + A_me[i+1][i] = 0.0; + +#ifdef THREADSAFE + V_FREE(diag); V_FREE(beta); +#endif + + return A; +} + +/* schur_vals -- compute real & imaginary parts of eigenvalues + -- assumes T contains a block upper triangular matrix + as produced by schur() + -- real parts stored in real_pt, imaginary parts in imag_pt */ +#ifndef ANSI_C +void schur_evals(T,real_pt,imag_pt) +MAT *T; +VEC *real_pt, *imag_pt; +#else +void schur_evals(MAT *T, VEC *real_pt, VEC *imag_pt) +#endif +{ + int i, n; + Real discrim, **T_me; + Real diff, sum, tmp; + + if ( ! T || ! real_pt || ! imag_pt ) + error(E_NULL,"schur_evals"); + if ( T->m != T->n ) + error(E_SQUARE,"schur_evals"); + n = T->n; T_me = T->me; + real_pt = v_resize(real_pt,(unsigned int)n); + imag_pt = v_resize(imag_pt,(unsigned int)n); + + i = 0; + while ( i < n ) + { + if ( i < n-1 && T_me[i+1][i] != 0.0 ) + { /* should be a complex eigenvalue */ + sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]); + diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]); + discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i]; + if ( discrim < 0.0 ) + { /* yes -- complex e-vals */ + real_pt->ve[i] = real_pt->ve[i+1] = sum; + imag_pt->ve[i] = sqrt(-discrim); + imag_pt->ve[i+1] = - imag_pt->ve[i]; + } + else + { /* no -- actually both real */ + tmp = sqrt(discrim); + real_pt->ve[i] = sum + tmp; + real_pt->ve[i+1] = sum - tmp; + imag_pt->ve[i] = imag_pt->ve[i+1] = 0.0; + } + i += 2; + } + else + { /* real eigenvalue */ + real_pt->ve[i] = T_me[i][i]; + imag_pt->ve[i] = 0.0; + i++; + } + } +} + +/* schur_vecs -- returns eigenvectors computed from the real Schur + decomposition of a matrix + -- T is the block upper triangular Schur matrix + -- Q is the orthognal matrix where A = Q.T.Q^T + -- if Q is null, the eigenvectors of T are returned + -- X_re is the real part of the matrix of eigenvectors, + and X_im is the imaginary part of the matrix. + -- X_re is returned */ +#ifndef ANSI_C +MAT *schur_vecs(T,Q,X_re,X_im) +MAT *T, *Q, *X_re, *X_im; +#else +MAT *schur_vecs(MAT *T, MAT *Q, MAT *X_re, MAT *X_im) +#endif +{ + int i, j, limit; + Real t11_re, t11_im, t12, t21, t22_re, t22_im; + Real l_re, l_im, det_re, det_im, invdet_re, invdet_im, + val1_re, val1_im, val2_re, val2_im, + tmp_val1_re, tmp_val1_im, tmp_val2_re, tmp_val2_im, **T_me; + Real sum, diff, discrim, magdet, norm, scale; + STATIC VEC *tmp1_re=VNULL, *tmp1_im=VNULL, + *tmp2_re=VNULL, *tmp2_im=VNULL; + + if ( ! T || ! X_re ) + error(E_NULL,"schur_vecs"); + if ( T->m != T->n || X_re->m != X_re->n || + ( Q != MNULL && Q->m != Q->n ) || + ( X_im != MNULL && X_im->m != X_im->n ) ) + error(E_SQUARE,"schur_vecs"); + if ( T->m != X_re->m || + ( Q != MNULL && T->m != Q->m ) || + ( X_im != MNULL && T->m != X_im->m ) ) + error(E_SIZES,"schur_vecs"); + + tmp1_re = v_resize(tmp1_re,T->m); + tmp1_im = v_resize(tmp1_im,T->m); + tmp2_re = v_resize(tmp2_re,T->m); + tmp2_im = v_resize(tmp2_im,T->m); + MEM_STAT_REG(tmp1_re,TYPE_VEC); + MEM_STAT_REG(tmp1_im,TYPE_VEC); + MEM_STAT_REG(tmp2_re,TYPE_VEC); + MEM_STAT_REG(tmp2_im,TYPE_VEC); + + T_me = T->me; + i = 0; + while ( i < T->m ) + { + if ( i+1 < T->m && T->me[i+1][i] != 0.0 ) + { /* complex eigenvalue */ + sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]); + diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]); + discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i]; + l_re = l_im = 0.0; + if ( discrim < 0.0 ) + { /* yes -- complex e-vals */ + l_re = sum; + l_im = sqrt(-discrim); + } + else /* not correct Real Schur form */ + error(E_RANGE,"schur_vecs"); + } + else + { + l_re = T_me[i][i]; + l_im = 0.0; + } + + v_zero(tmp1_im); + v_rand(tmp1_re); + sv_mlt(MACHEPS,tmp1_re,tmp1_re); + + /* solve (T-l.I)x = tmp1 */ + limit = ( l_im != 0.0 ) ? i+1 : i; + /* printf("limit = %d\n",limit); */ + for ( j = limit+1; j < T->m; j++ ) + tmp1_re->ve[j] = 0.0; + j = limit; + while ( j >= 0 ) + { + if ( j > 0 && T->me[j][j-1] != 0.0 ) + { /* 2 x 2 diagonal block */ + /* printf("checkpoint A\n"); */ + val1_re = tmp1_re->ve[j-1] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j-1][j+1]),limit-j); + /* printf("checkpoint B\n"); */ + val1_im = tmp1_im->ve[j-1] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j-1][j+1]),limit-j); + /* printf("checkpoint C\n"); */ + val2_re = tmp1_re->ve[j] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint D\n"); */ + val2_im = tmp1_im->ve[j] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint E\n"); */ + + t11_re = T_me[j-1][j-1] - l_re; + t11_im = - l_im; + t22_re = T_me[j][j] - l_re; + t22_im = - l_im; + t12 = T_me[j-1][j]; + t21 = T_me[j][j-1]; + + scale = fabs(T_me[j-1][j-1]) + fabs(T_me[j][j]) + + fabs(t12) + fabs(t21) + fabs(l_re) + fabs(l_im); + + det_re = t11_re*t22_re - t11_im*t22_im - t12*t21; + det_im = t11_re*t22_im + t11_im*t22_re; + magdet = det_re*det_re+det_im*det_im; + if ( sqrt(magdet) < MACHEPS*scale ) + { + det_re = MACHEPS*scale; + magdet = det_re*det_re+det_im*det_im; + } + invdet_re = det_re/magdet; + invdet_im = - det_im/magdet; + tmp_val1_re = t22_re*val1_re-t22_im*val1_im-t12*val2_re; + tmp_val1_im = t22_im*val1_re+t22_re*val1_im-t12*val2_im; + tmp_val2_re = t11_re*val2_re-t11_im*val2_im-t21*val1_re; + tmp_val2_im = t11_im*val2_re+t11_re*val2_im-t21*val1_im; + tmp1_re->ve[j-1] = invdet_re*tmp_val1_re - + invdet_im*tmp_val1_im; + tmp1_im->ve[j-1] = invdet_im*tmp_val1_re + + invdet_re*tmp_val1_im; + tmp1_re->ve[j] = invdet_re*tmp_val2_re - + invdet_im*tmp_val2_im; + tmp1_im->ve[j] = invdet_im*tmp_val2_re + + invdet_re*tmp_val2_im; + j -= 2; + } + else + { + t11_re = T_me[j][j] - l_re; + t11_im = - l_im; + magdet = t11_re*t11_re + t11_im*t11_im; + scale = fabs(T_me[j][j]) + fabs(l_re); + if ( sqrt(magdet) < MACHEPS*scale ) + { + t11_re = MACHEPS*scale; + magdet = t11_re*t11_re + t11_im*t11_im; + } + invdet_re = t11_re/magdet; + invdet_im = - t11_im/magdet; + /* printf("checkpoint F\n"); */ + val1_re = tmp1_re->ve[j] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint G\n"); */ + val1_im = tmp1_im->ve[j] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint H\n"); */ + tmp1_re->ve[j] = invdet_re*val1_re - invdet_im*val1_im; + tmp1_im->ve[j] = invdet_im*val1_re + invdet_re*val1_im; + j -= 1; + } + } + + norm = v_norm_inf(tmp1_re) + v_norm_inf(tmp1_im); + sv_mlt(1/norm,tmp1_re,tmp1_re); + if ( l_im != 0.0 ) + sv_mlt(1/norm,tmp1_im,tmp1_im); + mv_mlt(Q,tmp1_re,tmp2_re); + if ( l_im != 0.0 ) + mv_mlt(Q,tmp1_im,tmp2_im); + if ( l_im != 0.0 ) + norm = sqrt(in_prod(tmp2_re,tmp2_re)+in_prod(tmp2_im,tmp2_im)); + else + norm = v_norm2(tmp2_re); + sv_mlt(1/norm,tmp2_re,tmp2_re); + if ( l_im != 0.0 ) + sv_mlt(1/norm,tmp2_im,tmp2_im); + + if ( l_im != 0.0 ) + { + if ( ! X_im ) + error(E_NULL,"schur_vecs"); + set_col(X_re,i,tmp2_re); + set_col(X_im,i,tmp2_im); + sv_mlt(-1.0,tmp2_im,tmp2_im); + set_col(X_re,i+1,tmp2_re); + set_col(X_im,i+1,tmp2_im); + i += 2; + } + else + { + set_col(X_re,i,tmp2_re); + if ( X_im != MNULL ) + set_col(X_im,i,tmp1_im); /* zero vector */ + i += 1; + } + } + +#ifdef THREADSAFE + V_FREE(tmp1_re); V_FREE(tmp1_im); + V_FREE(tmp2_re); V_FREE(tmp2_im); +#endif + + return X_re; +} + diff --git a/solve.c b/solve.c new file mode 100644 index 0000000..4b07818 --- /dev/null +++ b/solve.c @@ -0,0 +1,308 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. +*/ + +/* solve.c 1.2 11/25/87 */ +static char rcsid[] = "$Id: solve.c,v 1.3 1994/01/13 05:29:57 des Exp $"; + +#include +#include +#include "matrix2.h" + + + + + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* Usolve -- back substitution with optional over-riding diagonal + -- can be in-situ but doesn't need to be */ +#ifndef ANSI_C +VEC *Usolve(matrix,b,out,diag) +MAT *matrix; +VEC *b, *out; +double diag; +#else +VEC *Usolve(const MAT *matrix, const VEC *b, VEC *out, double diag) +#endif +{ + unsigned int dim /* , j */; + int i, i_lim; + Real **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny; + + if ( matrix==MNULL || b==VNULL ) + error(E_NULL,"Usolve"); + dim = min(matrix->m,matrix->n); + if ( b->dim < dim ) + error(E_SIZES,"Usolve"); + if ( out==VNULL || out->dim < dim ) + out = v_resize(out,matrix->n); + mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; + + tiny = 10.0/HUGE_VAL; + + for ( i=dim-1; i>=0; i-- ) + if ( b_ent[i] != 0.0 ) + break; + else + out_ent[i] = 0.0; + i_lim = i; + + for ( ; i>=0; i-- ) + { + sum = b_ent[i]; + mat_row = &(mat_ent[i][i+1]); + out_col = &(out_ent[i+1]); + sum -= __ip__(mat_row,out_col,i_lim-i); + /****************************************************** + for ( j=i+1; j<=i_lim; j++ ) + sum -= mat_ent[i][j]*out_ent[j]; + sum -= (*mat_row++)*(*out_col++); + ******************************************************/ + if ( diag==0.0 ) + { + if ( fabs(mat_ent[i][i]) <= tiny*fabs(sum) ) + error(E_SING,"Usolve"); + else + out_ent[i] = sum/mat_ent[i][i]; + } + else + out_ent[i] = sum/diag; + } + + return (out); +} + +/* Lsolve -- forward elimination with (optional) default diagonal value */ +#ifndef ANSI_C +VEC *Lsolve(matrix,b,out,diag) +MAT *matrix; +VEC *b,*out; +double diag; +#else +VEC *Lsolve(const MAT *matrix, const VEC *b, VEC *out, double diag) +#endif +{ + unsigned int dim, i, i_lim /* , j */; + Real **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny; + + if ( matrix==(MAT *)NULL || b==(VEC *)NULL ) + error(E_NULL,"Lsolve"); + dim = min(matrix->m,matrix->n); + if ( b->dim < dim ) + error(E_SIZES,"Lsolve"); + if ( out==(VEC *)NULL || out->dim < dim ) + out = v_resize(out,matrix->n); + mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; + + for ( i=0; im,U->n); + if ( b->dim < dim ) + error(E_SIZES,"UTsolve"); + out = v_resize(out,U->n); + U_me = U->me; b_ve = b->ve; out_ve = out->ve; + + tiny = 10.0/HUGE_VAL; + + for ( i=0; idim); + MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]),(dim-i_lim)*sizeof(Real)); + } + + if ( diag == 0.0 ) + { + for ( ; im,A->n); + if ( b->dim < dim ) + error(E_SIZES,"Dsolve"); + x = v_resize(x,A->n); + + tiny = 10.0/HUGE_VAL; + + dim = b->dim; + for ( i=0; ime[i][i]) <= tiny*fabs(b->ve[i]) ) + error(E_SING,"Dsolve"); + else + x->ve[i] = b->ve[i]/A->me[i][i]; + + return (x); +} + +/* LTsolve -- back substitution with optional over-riding diagonal + using the LOWER triangular part of matrix + -- can be in-situ but doesn't need to be */ +#ifndef ANSI_C +VEC *LTsolve(L,b,out,diag) +MAT *L; +VEC *b, *out; +double diag; +#else +VEC *LTsolve(const MAT *L, const VEC *b, VEC *out, double diag) +#endif +{ + unsigned int dim; + int i, i_lim; + Real **L_me, *b_ve, *out_ve, tmp, invdiag, tiny; + + if ( ! L || ! b ) + error(E_NULL,"LTsolve"); + dim = min(L->m,L->n); + if ( b->dim < dim ) + error(E_SIZES,"LTsolve"); + out = v_resize(out,L->n); + L_me = L->me; b_ve = b->ve; out_ve = out->ve; + + tiny = 10.0/HUGE_VAL; + + for ( i=dim-1; i>=0; i-- ) + if ( b_ve[i] != 0.0 ) + break; + i_lim = i; + + if ( b != out ) + { + __zero__(out_ve,out->dim); + MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(Real)); + } + + if ( diag == 0.0 ) + { + for ( ; i>=0; i-- ) + { + tmp = L_me[i][i]; + if ( fabs(tmp) <= tiny*fabs(out_ve[i]) ) + error(E_SING,"LTsolve"); + out_ve[i] /= tmp; + __mltadd__(out_ve,L_me[i],-out_ve[i],i); + } + } + else + { + invdiag = 1.0/diag; + for ( ; i>=0; i-- ) + { + out_ve[i] *= invdiag; + __mltadd__(out_ve,L_me[i],-out_ve[i],i); + } + } + + return (out); +} diff --git a/sparse.c b/sparse.c new file mode 100644 index 0000000..4cda289 --- /dev/null +++ b/sparse.c @@ -0,0 +1,1162 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + Sparse matrix package + See also: sparse.h, matrix.h + */ + +#include +#include +#include +#include "sparse.h" + + +static char rcsid[] = "$Id: sparse.c,v 1.10 1994/03/08 05:46:07 des Exp $"; + +#define MINROWLEN 10 + + + +/* sp_get_val -- returns the (i,j) entry of the sparse matrix A */ +#ifndef ANSI_C +double sp_get_val(A,i,j) +SPMAT *A; +int i, j; +#else +double sp_get_val(const SPMAT *A, int i, int j) +#endif +{ + SPROW *r; + int idx; + + if ( A == SMNULL ) + error(E_NULL,"sp_get_val"); + if ( i < 0 || i >= A->m || j < 0 || j >= A->n ) + error(E_SIZES,"sp_get_val"); + + r = A->row+i; + idx = sprow_idx(r,j); + if ( idx < 0 ) + return 0.0; + /* else */ + return r->elt[idx].val; +} + +/* sp_set_val -- sets the (i,j) entry of the sparse matrix A */ +#ifndef ANSI_C +double sp_set_val(A,i,j,val) +SPMAT *A; +int i, j; +double val; +#else +double sp_set_val(SPMAT *A, int i, int j, double val) +#endif +{ + SPROW *r; + int idx, idx2, new_len; + + if ( A == SMNULL ) + error(E_NULL,"sp_set_val"); + if ( i < 0 || i >= A->m || j < 0 || j >= A->n ) + error(E_SIZES,"sp_set_val"); + + r = A->row+i; + idx = sprow_idx(r,j); + /* printf("sp_set_val: idx = %d\n",idx); */ + if ( idx >= 0 ) + { r->elt[idx].val = val; return val; } + /* else */ if ( idx < -1 ) + { + /* Note: this destroys the column & diag access paths */ + A->flag_col = A->flag_diag = FALSE; + /* shift & insert new value */ + idx = -(idx+2); /* this is the intended insertion index */ + if ( r->len >= r->maxlen ) + { + r->len = r->maxlen; + new_len = max(2*r->maxlen+1,5); + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->row[i].maxlen*sizeof(row_elt), + new_len*sizeof(row_elt)); + } + + r->elt = RENEW(r->elt,new_len,row_elt); + if ( ! r->elt ) /* can't allocate */ + error(E_MEM,"sp_set_val"); + r->maxlen = 2*r->maxlen+1; + } + for ( idx2 = r->len-1; idx2 >= idx; idx2-- ) + MEM_COPY((char *)(&(r->elt[idx2])), + (char *)(&(r->elt[idx2+1])),sizeof(row_elt)); + /************************************************************ + if ( idx < r->len ) + MEM_COPY((char *)(&(r->elt[idx])),(char *)(&(r->elt[idx+1])), + (r->len-idx)*sizeof(row_elt)); + ************************************************************/ + r->len++; + r->elt[idx].col = j; + return r->elt[idx].val = val; + } + /* else -- idx == -1, error in index/matrix! */ + return 0.0; +} + +/* sp_mv_mlt -- sparse matrix/dense vector multiply + -- result is in out, which is returned unless out==NULL on entry + -- if out==NULL on entry then the result vector is created */ +#ifndef ANSI_C +VEC *sp_mv_mlt(A,x,out) +SPMAT *A; +VEC *x, *out; +#else +VEC *sp_mv_mlt(const SPMAT *A, const VEC *x, VEC *out) +#endif +{ + int i, j_idx, m, n, max_idx; + Real sum, *x_ve; + SPROW *r; + row_elt *elts; + + if ( ! A || ! x ) + error(E_NULL,"sp_mv_mlt"); + if ( x->dim != A->n ) + error(E_SIZES,"sp_mv_mlt"); + if ( ! out || out->dim < A->m ) + out = v_resize(out,A->m); + if ( out == x ) + error(E_INSITU,"sp_mv_mlt"); + m = A->m; n = A->n; + x_ve = x->ve; + + for ( i = 0; i < m; i++ ) + { + sum = 0.0; + r = &(A->row[i]); + max_idx = r->len; + elts = r->elt; + for ( j_idx = 0; j_idx < max_idx; j_idx++, elts++ ) + sum += elts->val*x_ve[elts->col]; + out->ve[i] = sum; + } + return out; +} + +/* sp_vm_mlt -- sparse matrix/dense vector multiply from left + -- result is in out, which is returned unless out==NULL on entry + -- if out==NULL on entry then result vector is created & returned */ +#ifndef ANSI_C +VEC *sp_vm_mlt(A,x,out) +SPMAT *A; +VEC *x, *out; +#else +VEC *sp_vm_mlt(const SPMAT *A, const VEC *x, VEC *out) +#endif +{ + int i, j_idx, m, n, max_idx; + Real tmp, *x_ve, *out_ve; + SPROW *r; + row_elt *elts; + + if ( ! A || ! x ) + error(E_NULL,"sp_vm_mlt"); + if ( x->dim != A->m ) + error(E_SIZES,"sp_vm_mlt"); + if ( ! out || out->dim < A->n ) + out = v_resize(out,A->n); + if ( out == x ) + error(E_INSITU,"sp_vm_mlt"); + + m = A->m; n = A->n; + v_zero(out); + x_ve = x->ve; out_ve = out->ve; + + for ( i = 0; i < m; i++ ) + { + r = A->row+i; + max_idx = r->len; + elts = r->elt; + tmp = x_ve[i]; + for ( j_idx = 0; j_idx < max_idx; j_idx++, elts++ ) + out_ve[elts->col] += elts->val*tmp; + } + + return out; +} + + +/* sp_get -- get sparse matrix + -- len is number of elements available for each row without + allocating further memory */ +#ifndef ANSI_C +SPMAT *sp_get(m,n,maxlen) +int m, n, maxlen; +#else +SPMAT *sp_get(int m, int n, int maxlen) +#endif +{ + SPMAT *A; + SPROW *rows; + int i; + + if ( m < 0 || n < 0 ) + error(E_NEG,"sp_get"); + + maxlen = max(maxlen,1); + + A = NEW(SPMAT); + if ( ! A ) /* can't allocate */ + error(E_MEM,"sp_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,sizeof(SPMAT)); + mem_numvar(TYPE_SPMAT,1); + } + /* fprintf(stderr,"Have SPMAT structure\n"); */ + + A->row = rows = NEW_A(m,SPROW); + if ( ! A->row ) /* can't allocate */ + error(E_MEM,"sp_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,m*sizeof(SPROW)); + } + /* fprintf(stderr,"Have row structure array\n"); */ + + A->start_row = NEW_A(n,int); + A->start_idx = NEW_A(n,int); + if ( ! A->start_row || ! A->start_idx ) /* can't allocate */ + error(E_MEM,"sp_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,2*n*sizeof(int)); + } + for ( i = 0; i < n; i++ ) + A->start_row[i] = A->start_idx[i] = -1; + /* fprintf(stderr,"Have start_row array\n"); */ + + A->m = A->max_m = m; + A->n = A->max_n = n; + + for ( i = 0; i < m; i++, rows++ ) + { + rows->elt = NEW_A(maxlen,row_elt); + if ( ! rows->elt ) + error(E_MEM,"sp_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,maxlen*sizeof(row_elt)); + } + /* fprintf(stderr,"Have row %d element array\n",i); */ + rows->len = 0; + rows->maxlen = maxlen; + rows->diag = -1; + } + + return A; +} + + +/* sp_free -- frees up the memory for a sparse matrix */ +#ifndef ANSI_C +int sp_free(A) +SPMAT *A; +#else +int sp_free(SPMAT *A) +#endif +{ + SPROW *r; + int i; + + if ( ! A ) + return -1; + if ( A->start_row != (int *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->max_n*sizeof(int),0); + } + free((char *)(A->start_row)); + } + if ( A->start_idx != (int *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->max_n*sizeof(int),0); + } + + free((char *)(A->start_idx)); + } + if ( ! A->row ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,sizeof(SPMAT),0); + mem_numvar(TYPE_SPMAT,-1); + } + + free((char *)A); + return 0; + } + for ( i = 0; i < A->m; i++ ) + { + r = &(A->row[i]); + if ( r->elt != (row_elt *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->row[i].maxlen*sizeof(row_elt),0); + } + free((char *)(r->elt)); + } + } + + if (mem_info_is_on()) { + if (A->row) + mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW),0); + mem_bytes(TYPE_SPMAT,sizeof(SPMAT),0); + mem_numvar(TYPE_SPMAT,-1); + } + + free((char *)(A->row)); + free((char *)A); + + return 0; +} + + +/* sp_copy -- constructs a copy of a given matrix + -- note that the max_len fields (etc) are no larger in the copy + than necessary + -- result is returned */ +#ifndef ANSI_C +SPMAT *sp_copy(A) +SPMAT *A; +#else +SPMAT *sp_copy(const SPMAT *A) +#endif +{ + SPMAT *out; + SPROW *row1, *row2; + int i; + + if ( A == SMNULL ) + error(E_NULL,"sp_copy"); + if ( ! (out=NEW(SPMAT)) ) + error(E_MEM,"sp_copy"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,sizeof(SPMAT)); + mem_numvar(TYPE_SPMAT,1); + } + out->m = out->max_m = A->m; out->n = out->max_n = A->n; + + /* set up rows */ + if ( ! (out->row=NEW_A(A->m,SPROW)) ) + error(E_MEM,"sp_copy"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,A->m*sizeof(SPROW)); + } + for ( i = 0; i < A->m; i++ ) + { + row1 = &(A->row[i]); + row2 = &(out->row[i]); + if ( ! (row2->elt=NEW_A(max(row1->len,3),row_elt)) ) + error(E_MEM,"sp_copy"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,max(row1->len,3)*sizeof(row_elt)); + } + row2->len = row1->len; + row2->maxlen = max(row1->len,3); + row2->diag = row1->diag; + MEM_COPY((char *)(row1->elt),(char *)(row2->elt), + row1->len*sizeof(row_elt)); + } + + /* set up start arrays -- for column access */ + if ( ! (out->start_idx=NEW_A(A->n,int)) || + ! (out->start_row=NEW_A(A->n,int)) ) + error(E_MEM,"sp_copy"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,2*A->n*sizeof(int)); + } + MEM_COPY((char *)(A->start_idx),(char *)(out->start_idx), + A->n*sizeof(int)); + MEM_COPY((char *)(A->start_row),(char *)(out->start_row), + A->n*sizeof(int)); + + return out; +} + +/* sp_col_access -- set column access path; i.e. nxt_row, nxt_idx fields + -- returns A */ +#ifndef ANSI_C +SPMAT *sp_col_access(A) +SPMAT *A; +#else +SPMAT *sp_col_access(SPMAT *A) +#endif +{ + int i, j, j_idx, len, m, n; + SPROW *row; + row_elt *r_elt; + int *start_row, *start_idx; + + if ( A == SMNULL ) + error(E_NULL,"sp_col_access"); + + m = A->m; n = A->n; + + /* initialise start_row and start_idx */ + start_row = A->start_row; start_idx = A->start_idx; + for ( j = 0; j < n; j++ ) + { *start_row++ = -1; *start_idx++ = -1; } + + start_row = A->start_row; start_idx = A->start_idx; + + /* now work UP the rows, setting nxt_row, nxt_idx fields */ + for ( i = m-1; i >= 0; i-- ) + { + row = &(A->row[i]); + r_elt = row->elt; + len = row->len; + for ( j_idx = 0; j_idx < len; j_idx++, r_elt++ ) + { + j = r_elt->col; + r_elt->nxt_row = start_row[j]; + r_elt->nxt_idx = start_idx[j]; + start_row[j] = i; + start_idx[j] = j_idx; + } + } + + A->flag_col = TRUE; + return A; +} + +/* sp_diag_access -- set diagonal access path(s) */ +#ifndef ANSI_C +SPMAT *sp_diag_access(A) +SPMAT *A; +#else +SPMAT *sp_diag_access(SPMAT *A) +#endif +{ + int i, m; + SPROW *row; + + if ( A == SMNULL ) + error(E_NULL,"sp_diag_access"); + + m = A->m; + + row = A->row; + for ( i = 0; i < m; i++, row++ ) + row->diag = sprow_idx(row,i); + + A->flag_diag = TRUE; + + return A; +} + +/* sp_m2dense -- convert a sparse matrix to a dense one */ +#ifndef ANSI_C +MAT *sp_m2dense(A,out) +SPMAT *A; +MAT *out; +#else +MAT *sp_m2dense(const SPMAT *A, MAT *out) +#endif +{ + int i, j_idx; + SPROW *row; + row_elt *elt; + + if ( ! A ) + error(E_NULL,"sp_m2dense"); + if ( ! out || out->m < A->m || out->n < A->n ) + out = m_get(A->m,A->n); + + m_zero(out); + for ( i = 0; i < A->m; i++ ) + { + row = &(A->row[i]); + elt = row->elt; + for ( j_idx = 0; j_idx < row->len; j_idx++, elt++ ) + out->me[i][elt->col] = elt->val; + } + + return out; +} + + +/* C = A+B, can be in situ */ +#ifndef ANSI_C +SPMAT *sp_add(A,B,C) +SPMAT *A, *B, *C; +#else +SPMAT *sp_add(const SPMAT *A, const SPMAT *B, SPMAT *C) +#endif +{ + int i, in_situ; + SPROW *rc; + STATIC SPROW *tmp = NULL; + + if ( ! A || ! B ) + error(E_NULL,"sp_add"); + if ( A->m != B->m || A->n != B->n ) + error(E_SIZES,"sp_add"); + if (C == A || C == B) + in_situ = TRUE; + else in_situ = FALSE; + + if ( ! C ) + C = sp_get(A->m,A->n,5); + else { + if ( C->m != A->m || C->n != A->n ) + error(E_SIZES,"sp_add"); + if (!in_situ) sp_zero(C); + } + + if (tmp == (SPROW *)NULL && in_situ) { + tmp = sprow_get(MINROWLEN); + MEM_STAT_REG(tmp,TYPE_SPROW); + } + + if (in_situ) + for (i=0; i < A->m; i++) { + rc = &(C->row[i]); + sprow_add(&(A->row[i]),&(B->row[i]),0,tmp,TYPE_SPROW); + sprow_resize(rc,tmp->len,TYPE_SPMAT); + MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt)); + rc->len = tmp->len; + } + else + for (i=0; i < A->m; i++) { + sprow_add(&(A->row[i]),&(B->row[i]),0,&(C->row[i]),TYPE_SPMAT); + } + + C->flag_col = C->flag_diag = FALSE; + +#ifdef THREADSAFE + sprow_free(tmp); +#endif + + return C; +} + +/* C = A-B, cannot be in situ */ +#ifndef ANSI_C +SPMAT *sp_sub(A,B,C) +SPMAT *A, *B, *C; +#else +SPMAT *sp_sub(const SPMAT *A, const SPMAT *B, SPMAT *C) +#endif +{ + int i, in_situ; + SPROW *rc; + STATIC SPROW *tmp = NULL; + + if ( ! A || ! B ) + error(E_NULL,"sp_sub"); + if ( A->m != B->m || A->n != B->n ) + error(E_SIZES,"sp_sub"); + if (C == A || C == B) + in_situ = TRUE; + else in_situ = FALSE; + + if ( ! C ) + C = sp_get(A->m,A->n,5); + else { + if ( C->m != A->m || C->n != A->n ) + error(E_SIZES,"sp_sub"); + if (!in_situ) sp_zero(C); + } + + if (tmp == (SPROW *)NULL && in_situ) { + tmp = sprow_get(MINROWLEN); + MEM_STAT_REG(tmp,TYPE_SPROW); + } + + if (in_situ) + for (i=0; i < A->m; i++) { + rc = &(C->row[i]); + sprow_sub(&(A->row[i]),&(B->row[i]),0,tmp,TYPE_SPROW); + sprow_resize(rc,tmp->len,TYPE_SPMAT); + MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt)); + rc->len = tmp->len; + } + else + for (i=0; i < A->m; i++) { + sprow_sub(&(A->row[i]),&(B->row[i]),0,&(C->row[i]),TYPE_SPMAT); + } + + C->flag_col = C->flag_diag = FALSE; + +#ifdef THREADSAFE + sprow_free(tmp); +#endif + + return C; +} + +/* C = A+alpha*B, cannot be in situ */ +#ifndef ANSI_C +SPMAT *sp_mltadd(A,B,alpha,C) +SPMAT *A, *B, *C; +double alpha; +#else +SPMAT *sp_mltadd(const SPMAT *A, const SPMAT *B, double alpha, SPMAT *C) +#endif +{ + int i, in_situ; + SPROW *rc; + STATIC SPROW *tmp = NULL; + + if ( ! A || ! B ) + error(E_NULL,"sp_mltadd"); + if ( A->m != B->m || A->n != B->n ) + error(E_SIZES,"sp_mltadd"); + if (C == A || C == B) + in_situ = TRUE; + else in_situ = FALSE; + + if ( ! C ) + C = sp_get(A->m,A->n,5); + else { + if ( C->m != A->m || C->n != A->n ) + error(E_SIZES,"sp_mltadd"); + if (!in_situ) sp_zero(C); + } + + if (tmp == (SPROW *)NULL && in_situ) { + tmp = sprow_get(MINROWLEN); + MEM_STAT_REG(tmp,TYPE_SPROW); + } + + if (in_situ) + for (i=0; i < A->m; i++) { + rc = &(C->row[i]); + sprow_mltadd(&(A->row[i]),&(B->row[i]),alpha,0,tmp,TYPE_SPROW); + sprow_resize(rc,tmp->len,TYPE_SPMAT); + MEM_COPY(tmp->elt,rc->elt,tmp->len*sizeof(row_elt)); + rc->len = tmp->len; + } + else + for (i=0; i < A->m; i++) { + sprow_mltadd(&(A->row[i]),&(B->row[i]),alpha,0, + &(C->row[i]),TYPE_SPMAT); + } + + C->flag_col = C->flag_diag = FALSE; + +#ifdef THREADSAFE + sprow_free(tmp); +#endif + + return C; +} + + + +/* B = alpha*A, can be in situ */ +#ifndef ANSI_C +SPMAT *sp_smlt(A,alpha,B) +SPMAT *A, *B; +double alpha; +#else +SPMAT *sp_smlt(const SPMAT *A, double alpha, SPMAT *B) +#endif +{ + int i; + + if ( ! A ) + error(E_NULL,"sp_smlt"); + if ( ! B ) + B = sp_get(A->m,A->n,5); + else + if ( A->m != B->m || A->n != B->n ) + error(E_SIZES,"sp_smlt"); + + for (i=0; i < A->m; i++) { + sprow_smlt(&(A->row[i]),alpha,0,&(B->row[i]),TYPE_SPMAT); + } + return B; +} + + + +/* sp_zero -- zero all the (represented) elements of a sparse matrix */ +#ifndef ANSI_C +SPMAT *sp_zero(A) +SPMAT *A; +#else +SPMAT *sp_zero(SPMAT *A) +#endif +{ + int i, idx, len; + row_elt *elt; + + if ( ! A ) + error(E_NULL,"sp_zero"); + + for ( i = 0; i < A->m; i++ ) + { + elt = A->row[i].elt; + len = A->row[i].len; + for ( idx = 0; idx < len; idx++ ) + (*elt++).val = 0.0; + } + + return A; +} + +/* sp_copy2 -- copy sparse matrix (type 2) + -- keeps structure of the OUT matrix */ +#ifndef ANSI_C +SPMAT *sp_copy2(A,OUT) +SPMAT *A, *OUT; +#else +SPMAT *sp_copy2(const SPMAT *A, SPMAT *OUT) +#endif +{ + int i /* , idx, len1, len2 */; + SPROW *r1, *r2; + STATIC SPROW *scratch = (SPROW *)NULL; + /* row_elt *e1, *e2; */ + + if ( ! A ) + error(E_NULL,"sp_copy2"); + if ( ! OUT ) + OUT = sp_get(A->m,A->n,10); + if ( ! scratch ) { + scratch = sprow_xpd(scratch,MINROWLEN,TYPE_SPROW); + MEM_STAT_REG(scratch,TYPE_SPROW); + } + + if ( OUT->m < A->m ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW), + A->m*sizeof(SPROW)); + } + + OUT->row = RENEW(OUT->row,A->m,SPROW); + if ( ! OUT->row ) + error(E_MEM,"sp_copy2"); + + for ( i = OUT->m; i < A->m; i++ ) + { + OUT->row[i].elt = NEW_A(MINROWLEN,row_elt); + if ( ! OUT->row[i].elt ) + error(E_MEM,"sp_copy2"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,MINROWLEN*sizeof(row_elt)); + } + + OUT->row[i].maxlen = MINROWLEN; + OUT->row[i].len = 0; + } + OUT->m = A->m; + } + + OUT->flag_col = OUT->flag_diag = FALSE; + /* sp_zero(OUT); */ + + for ( i = 0; i < A->m; i++ ) + { + r1 = &(A->row[i]); r2 = &(OUT->row[i]); + sprow_copy(r1,r2,scratch,TYPE_SPROW); + if ( r2->maxlen < scratch->len ) + sprow_xpd(r2,scratch->len,TYPE_SPMAT); + MEM_COPY((char *)(scratch->elt),(char *)(r2->elt), + scratch->len*sizeof(row_elt)); + r2->len = scratch->len; + /******************************************************* + e1 = r1->elt; e2 = r2->elt; + len1 = r1->len; len2 = r2->len; + for ( idx = 0; idx < len2; idx++, e2++ ) + e2->val = 0.0; + for ( idx = 0; idx < len1; idx++, e1++ ) + sprow_set_val(r2,e1->col,e1->val); + *******************************************************/ + } + + sp_col_access(OUT); + +#ifdef THREADSAFE + sprow_free(scratch); +#endif + + return OUT; +} + +/* sp_resize -- resize a sparse matrix + -- don't destroying any contents if possible + -- returns resized matrix */ +#ifndef ANSI_C +SPMAT *sp_resize(A,m,n) +SPMAT *A; +int m, n; +#else +SPMAT *sp_resize(SPMAT *A, int m, int n) +#endif +{ + int i, len; + SPROW *r; + + if (m < 0 || n < 0) + error(E_NEG,"sp_resize"); + + if ( ! A ) + return sp_get(m,n,10); + + if (m == A->m && n == A->n) + return A; + + if ( m <= A->max_m ) + { + for ( i = A->m; i < m; i++ ) + A->row[i].len = 0; + A->m = m; + } + else + { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,A->max_m*sizeof(SPROW), + m*sizeof(SPROW)); + } + + A->row = RENEW(A->row,(unsigned)m,SPROW); + if ( ! A->row ) + error(E_MEM,"sp_resize"); + for ( i = A->m; i < m; i++ ) + { + if ( ! (A->row[i].elt = NEW_A(MINROWLEN,row_elt)) ) + error(E_MEM,"sp_resize"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT,0,MINROWLEN*sizeof(row_elt)); + } + A->row[i].len = 0; A->row[i].maxlen = MINROWLEN; + } + A->m = A->max_m = m; + } + + /* update number of rows */ + A->n = n; + + /* do we need to increase the size of start_idx[] and start_row[] ? */ + if ( n > A->max_n ) + { /* only have to update the start_idx & start_row arrays */ + if (mem_info_is_on()) + { + mem_bytes(TYPE_SPMAT,2*A->max_n*sizeof(int), + 2*n*sizeof(int)); + } + + A->start_row = RENEW(A->start_row,(unsigned)n,int); + A->start_idx = RENEW(A->start_idx,(unsigned)n,int); + if ( ! A->start_row || ! A->start_idx ) + error(E_MEM,"sp_resize"); + A->max_n = n; /* ...and update max_n */ + + return A; + } + + if ( n <= A->n ) + /* make sure that all rows are truncated just before column n */ + for ( i = 0; i < A->m; i++ ) + { + r = &(A->row[i]); + len = sprow_idx(r,n); + if ( len < 0 ) + len = -(len+2); + if ( len < 0 ) + error(E_MEM,"sp_resize"); + r->len = len; + } + + return A; +} + + +/* sp_compact -- removes zeros and near-zeros from a sparse matrix */ +#ifndef ANSI_C +SPMAT *sp_compact(A,tol) +SPMAT *A; +double tol; +#else +SPMAT *sp_compact(SPMAT *A, double tol) +#endif +{ + int i, idx1, idx2; + SPROW *r; + row_elt *elt1, *elt2; + + if ( ! A ) + error(E_NULL,"sp_compact"); + if ( tol < 0.0 ) + error(E_RANGE,"sp_compact"); + + A->flag_col = A->flag_diag = FALSE; + + for ( i = 0; i < A->m; i++ ) + { + r = &(A->row[i]); + elt1 = elt2 = r->elt; + idx1 = idx2 = 0; + while ( idx1 < r->len ) + { + /* printf("# sp_compact: idx1 = %d, idx2 = %d\n",idx1,idx2); */ + if ( fabs(elt1->val) <= tol ) + { idx1++; elt1++; continue; } + if ( elt1 != elt2 ) + MEM_COPY(elt1,elt2,sizeof(row_elt)); + idx1++; elt1++; + idx2++; elt2++; + } + r->len = idx2; + } + + return A; +} + +/* sp_mlt (C) Copyright David Stewart and Fabrizio Novalis */ +/* sp_mlt -- computes out = A*B and returns out */ +SPMAT *sp_mlt(const SPMAT *A, const SPMAT *B, SPMAT *out) +{ + int i, j, k, idx, cp; + SPROW *rA, *rB, *rout, *rtemp; + double valA; + + if ( ! A || ! B ) + error(E_NULL,"sp_mlt"); + if ( A->n != B->m ) + error(E_SIZES,"sp_mlt"); + out = sp_resize(out,A->m,B->n); + sp_zero(out); + rtemp = sprow_get(B->n); + for ( i = 0; i < A->m; i++ ) /* per ogni riga */ + { + rtemp = sprow_resize(rtemp,0,TYPE_SPROW); + rA = &(A->row[i]); + rout = &(out->row[i]); + for ( idx = 0; idx < rA->len; idx++ ) /* per ogni elemento != 0 + della riga corrente */ + { + j = rA->elt[idx].col; + valA = rA->elt[idx].val; + rB = &(B->row[j]); + sprow_mltadd(rtemp,rB,valA,0,rout,TYPE_SPMAT); + + for ( cp = 0; cp < rout->len; cp++ ) + { + rtemp->elt[cp].col = rout->elt[cp].col; + rtemp->elt[cp].val = rout->elt[cp].val; + } + rtemp->len=rout->len; + } + } + return out; +} + +/* varying number of arguments */ + +#ifdef ANSI_C + +/* To allocate memory to many arguments. + The function should be called: + sp_get_vars(m,n,deg,&x,&y,&z,...,NULL); + where + int m,n,deg; + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + m x n is the dimension of matrices x,y,z,... + returned value is equal to the number of allocated variables +*/ + +int sp_get_vars(int m,int n,int deg,...) +{ + va_list ap; + int i=0; + SPMAT **par; + + va_start(ap, deg); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + *par = sp_get(m,n,deg); + i++; + } + + va_end(ap); + return i; +} + + +/* To resize memory for many arguments. + The function should be called: + sp_resize_vars(m,n,&x,&y,&z,...,NULL); + where + int m,n; + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + m X n is the resized dimension of matrices x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. +*/ + +int sp_resize_vars(int m,int n,...) +{ + va_list ap; + int i=0; + SPMAT **par; + + va_start(ap, n); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + *par = sp_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + +/* To deallocate memory for many arguments. + The function should be called: + sp_free_vars(&x,&y,&z,...,NULL); + where + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + There must be at least one not NULL argument. + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. +*/ + +int sp_free_vars(SPMAT **va,...) +{ + va_list ap; + int i=1; + SPMAT **par; + + sp_free(*va); + *va = (SPMAT *) NULL; + va_start(ap, va); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + sp_free(*par); + *par = (SPMAT *)NULL; + i++; + } + + va_end(ap); + return i; +} + + +#elif VARARGS + +/* To allocate memory to many arguments. + The function should be called: + sp_get_vars(m,n,deg,&x,&y,&z,...,NULL); + where + int m,n,deg; + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + m x n is the dimension of matrices x,y,z,... + returned value is equal to the number of allocated variables +*/ + +int sp_get_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, m, n, deg; + SPMAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + deg = va_arg(ap,int); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + *par = sp_get(m,n,deg); + i++; + } + + va_end(ap); + return i; +} + + +/* To resize memory for many arguments. + The function should be called: + sp_resize_vars(m,n,&x,&y,&z,...,NULL); + where + int m,n; + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + m X n is the resized dimension of matrices x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. +*/ + +int sp_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, m, n; + SPMAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + *par = sp_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + + + +/* To deallocate memory for many arguments. + The function should be called: + sp_free_vars(&x,&y,&z,...,NULL); + where + SPMAT *x, *y, *z,...; + The last argument should be NULL ! + There must be at least one not NULL argument. + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. +*/ + +int sp_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + SPMAT **par; + + va_start(ap); + while (par = va_arg(ap,SPMAT **)) { /* NULL ends the list*/ + sp_free(*par); + *par = (SPMAT *)NULL; + i++; + } + + va_end(ap); + return i; +} + + + +#endif + diff --git a/sparse.h b/sparse.h new file mode 100644 index 0000000..0777fff --- /dev/null +++ b/sparse.h @@ -0,0 +1,221 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Header for sparse matrix stuff. + Basic sparse routines to be held in sparse.c +*/ + +/* RCS id: $Id: sparse.h,v 1.2 1994/01/13 05:33:36 des Exp $ */ + +#ifndef SPARSEH + +#define SPARSEH + + +#include "matrix.h" + + +/* basic sparse types */ + +typedef struct row_elt { + int col, nxt_row, nxt_idx; + Real val; + } row_elt; + +typedef struct SPROW { + int len, maxlen, diag; + row_elt *elt; /* elt[maxlen] */ + } SPROW; + +typedef struct SPMAT { + int m, n, max_m, max_n; + char flag_col, flag_diag; + SPROW *row; /* row[max_m] */ + int *start_row; /* start_row[max_n] */ + int *start_idx; /* start_idx[max_n] */ + } SPMAT; + +/* Note that the first allocated entry in column j is start_row[j]; + This starts the chain down the columns using the nxt_row and nxt_idx + fields of each entry in each row. */ + +typedef struct pair { int pos; Real val; } pair; + +typedef struct SPVEC { + int dim, max_dim; + pair *elt; /* elt[max_dim] */ + } SPVEC; + +#define SMNULL ((SPMAT*)NULL) +#define SVNULL ((SPVEC*)NULL) + +/* Macro for speedup */ +#define sprow_idx2(r,c,hint) \ + ( ( (hint) >= 0 && (hint) < (r)->len && \ + (r)->elt[hint].col == (c)) ? (hint) : sprow_idx((r),(c)) ) + + + +/* memory functions */ + +#ifdef ANSI_C +int sp_get_vars(int m,int n,int deg,...); +int sp_resize_vars(int m,int n,...); +int sp_free_vars(SPMAT **,...); +#elif VARARGS +int sp_get_vars(); +int sp_resize_vars(); +int sp_free_vars(); + +#endif /* ANSI_C */ + +/* Sparse Matrix Operations and Utilities */ +#ifndef ANSI_C +extern SPMAT *sp_get(), *sp_copy(), *sp_copy2(), + *sp_zero(), *sp_resize(), *sp_compact(); +extern double sp_get_val(), sp_set_val(); +extern VEC *sp_mv_mlt(), *sp_vm_mlt(); +extern int sp_free(); + +/* Access path operations */ +extern SPMAT *sp_col_access(); +extern SPMAT *sp_diag_access(); +extern int chk_col_access(); + +/* Input/output operations */ +extern SPMAT *sp_finput(); +extern void sp_foutput(), sp_foutput2(); + +/* algebraic operations */ +extern SPMAT *sp_smlt(), *sp_add(), *sp_sub(), *sp_mltadd(); + + +/* sparse row operations */ +extern SPROW *sprow_get(), *sprow_xpd(), *sprow_merge(), *sprow_mltadd(), + *sprow_resize(), *sprow_copy(); +extern SPROW *sprow_add(), *sprow_sub(), *sprow_smlt(); +extern double sprow_set_val(); +extern void sprow_foutput(); +extern int sprow_idx(), sprow_free(); + +/* dump */ +extern void sp_dump(), sprow_dump(); +extern MAT *sp_m2dense(); + +#else +SPMAT *sp_get(int,int,int), *sp_copy(const SPMAT *), + *sp_copy2(const SPMAT *,SPMAT *), + *sp_zero(SPMAT *), *sp_resize(SPMAT *,int,int), + *sp_compact(SPMAT *,double); +double sp_get_val(const SPMAT *,int,int), sp_set_val(SPMAT *,int,int,double); +VEC *sp_mv_mlt(const SPMAT *, const VEC *, VEC *), + *sp_vm_mlt(const SPMAT *, const VEC *, VEC *); +int sp_free(SPMAT *); + +/* Access path operations */ +SPMAT *sp_col_access(SPMAT *); +SPMAT *sp_diag_access(SPMAT *); +int chk_col_access(const SPMAT *); + +/* Input/output operations */ +SPMAT *sp_finput(FILE *); +void sp_foutput(FILE *, const SPMAT *); + +/* algebraic operations */ +SPMAT *sp_smlt(const SPMAT *A,double alpha,SPMAT *B), + *sp_add(const SPMAT *A,const SPMAT *B,SPMAT *C), + *sp_sub(const SPMAT *A,const SPMAT *B,SPMAT *C), + *sp_mltadd(const SPMAT *A,const SPMAT *B,double alpha,SPMAT *C); + +/* sparse row operations */ +SPROW *sprow_get(int), *sprow_xpd(SPROW *r,int n,int type), + *sprow_resize(SPROW *r,int n,int type), + *sprow_merge(const SPROW *,const SPROW *,SPROW *,int type), + *sprow_copy(const SPROW *,const SPROW *,SPROW *,int type), + *sprow_mltadd(const SPROW *r1,const SPROW *r2, double alpha, + int j0, SPROW *r_out, int type); +SPROW *sprow_add(const SPROW *r1,const SPROW *r2, int j0,SPROW *r_out, int type), + *sprow_sub(const SPROW *r1,const SPROW *r2, int j0,SPROW *r_out, int type), + *sprow_smlt(const SPROW *r1,double alpha, int j0,SPROW *r_out, int type); +double sprow_set_val(SPROW *,int,double); +int sprow_free(SPROW *); +int sprow_idx(const SPROW *,int); +void sprow_foutput(FILE *,const SPROW *); + +/* dump */ +void sp_dump(FILE *fp, const SPMAT *A); +void sprow_dump(FILE *fp, const SPROW *r); +MAT *sp_m2dense(const SPMAT *A,MAT *out); + +#endif /* ANSI_C */ + +/* MACROS */ + +#define sp_input() sp_finput(stdin) +#define sp_output(A) sp_foutput(stdout,(A)) +#define sp_output2(A) sp_foutput2(stdout,(A)) +#define row_mltadd(r1,r2,alpha,out) sprow_mltadd(r1,r2,alpha,0,out) +#define out_row(r) sprow_foutput(stdout,(r)) + +#define SP_FREE(A) ( sp_free((A)), (A)=(SPMAT *)NULL) + +/* utility for index computations -- ensures index returned >= 0 */ +#define fixindex(idx) ((idx) == -1 ? (error(E_BOUNDS,"fixindex"),0) : \ + (idx) < 0 ? -((idx)+2) : (idx)) + + +/* NOT USED */ + +/* loop over the columns in a row */ +/* +#define loop_cols(r,e,code) \ + do { int _r_idx; row_elt *e; SPROW *_t_row; \ + _t_row = (r); e = &(_t_row->elt); \ + for ( _r_idx = 0; _r_idx < _t_row->len; _r_idx++, e++ ) \ + { code; } } while ( 0 ) +*/ +/* loop over the rows in a column */ +/* +#define loop_cols(A,col,e,code) \ + do { int _r_num, _r_idx, _c; SPROW *_r; row_elt *e; \ + if ( ! (A)->flag_col ) sp_col_access((A)); \ + col_num = (col); \ + if ( col_num < 0 || col_num >= A->n ) \ + error(E_BOUNDS,"loop_cols"); \ + _r_num = (A)->start_row[_c]; _r_idx = (A)->start_idx[_c]; \ + while ( _r_num >= 0 ) { \ + _r = &((A)->row[_r_num]); \ + _r_idx = sprow_idx2(_r,_c,_r_idx); \ + if ( _r_idx < 0 ) continue; \ + e = &(_r->elt[_r_idx]); code; \ + _r_num = e->nxt_row; _r_idx = e->nxt_idx; \ + } } while ( 0 ) + +*/ + +#endif /* SPARSEH */ + diff --git a/sparse2.h b/sparse2.h new file mode 100644 index 0000000..4c4f53d --- /dev/null +++ b/sparse2.h @@ -0,0 +1,95 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* Sparse matrix factorise/solve header */ +/* RCS id: $Id: sparse2.h,v 1.4 1994/01/13 05:33:46 des Exp $ */ + + + +#ifndef SPARSE2H + +#define SPARSE2H + +#include "sparse.h" + + +#ifdef ANSI_C +SPMAT *spCHfactor(SPMAT *A), *spICHfactor(SPMAT *A), *spCHsymb(SPMAT *A); +VEC *spCHsolve(SPMAT *CH, const VEC *b, VEC *x); + +SPMAT *spLUfactor(SPMAT *A,PERM *pivot,double threshold); +SPMAT *spILUfactor(SPMAT *A,double theshold); +VEC *spLUsolve(const SPMAT *LU,PERM *pivot, const VEC *b,VEC *x), + *spLUTsolve(SPMAT *LU,PERM *pivot, const VEC *b,VEC *x); + +SPMAT *spBKPfactor(SPMAT *, PERM *, PERM *, double); +VEC *spBKPsolve(SPMAT *, PERM *, PERM *, const VEC *, VEC *); + +VEC *pccg(VEC *(*A)(),void *A_par,VEC *(*M_inv)(),void *M_par,VEC *b, + double tol,VEC *x); +VEC *sp_pccg(SPMAT *,SPMAT *,VEC *,double,VEC *); +VEC *cgs(VEC *(*A)(),void *A_par,VEC *b,VEC *r0,double tol,VEC *x); +VEC *sp_cgs(SPMAT *,VEC *,VEC *,double,VEC *); +VEC *lsqr(VEC *(*A)(),VEC *(*AT)(),void *A_par,VEC *b,double tol,VEC *x); +VEC *sp_lsqr(SPMAT *,VEC *,double,VEC *); +int cg_set_maxiter(int); + +void lanczos(VEC *(*A)(),void *A_par,int m,VEC *x0,VEC *a,VEC *b, + Real *beta_m1,MAT *Q); +void sp_lanczos(SPMAT *,int,VEC *,VEC *,VEC *,Real *,MAT *); +VEC *lanczos2(VEC *(*A)(),void *A_par,int m,VEC *x0,VEC *evals, + VEC *err_est); +VEC *sp_lanczos2(SPMAT *,int,VEC *,VEC *,VEC *); +extern void scan_to(SPMAT *,IVEC *,IVEC *,IVEC *,int); +extern row_elt *chase_col(const SPMAT *,int,int *,int *,int); +extern row_elt *chase_past(const SPMAT *,int,int *,int *,int); +extern row_elt *bump_col(const SPMAT *,int,int *,int *); + +#else +extern SPMAT *spCHfactor(), *spICHfactor(), *spCHsymb(); +extern VEC *spCHsolve(); + +extern SPMAT *spLUfactor(); +extern SPMAT *spILUfactor(); +extern VEC *spLUsolve(), *spLUTsolve(); + +extern SPMAT *spBKPfactor(); +extern VEC *spBKPsolve(); + +extern VEC *pccg(), *sp_pccg(), *cgs(), *sp_cgs(), *lsqr(), *sp_lsqr(); +extern int cg_set_maxiter(); + +void lanczos(), sp_lanczos(); +VEC *lanczos2(), *sp_lanczos2(); +extern void scan_to(); +extern row_elt *chase_col(); +extern row_elt *chase_past(); +extern row_elt *bump_col(); + +#endif + + +#endif diff --git a/sparseio.c b/sparseio.c new file mode 100644 index 0000000..ae3eedd --- /dev/null +++ b/sparseio.c @@ -0,0 +1,361 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file has the routines for sparse matrix input/output + It works in conjunction with sparse.c, sparse.h etc +*/ + +#include +#include "sparse.h" + +static char rcsid[] = "$Id: sparseio.c,v 1.4 1994/01/13 05:34:25 des Exp $"; + + + +/* local variables */ +static char line[MAXLINE]; + +/* sp_foutput -- output sparse matrix A to file/stream fp */ +#ifndef ANSI_C +void sp_foutput(fp,A) +FILE *fp; +SPMAT *A; +#else +void sp_foutput(FILE *fp, const SPMAT *A) +#endif +{ + int i, j_idx, m /* , n */; + SPROW *rows; + row_elt *elts; + + fprintf(fp,"SparseMatrix: "); + if ( A == SMNULL ) + { + fprintf(fp,"*** NULL ***\n"); + error(E_NULL,"sp_foutput"); return; + } + fprintf(fp,"%d by %d\n",A->m,A->n); + m = A->m; /* n = A->n; */ + if ( ! (rows=A->row) ) + { + fprintf(fp,"*** NULL rows ***\n"); + error(E_NULL,"sp_foutput"); return; + } + + for ( i = 0; i < m; i++ ) + { + fprintf(fp,"row %d: ",i); + if ( ! (elts=rows[i].elt) ) + { + fprintf(fp,"*** NULL element list ***\n"); + continue; + } + for ( j_idx = 0; j_idx < rows[i].len; j_idx++ ) + { + fprintf(fp,"%d:%-20.15g ",elts[j_idx].col, + elts[j_idx].val); + if ( j_idx % 3 == 2 && j_idx != rows[i].len-1 ) + fprintf(fp,"\n "); + } + fprintf(fp,"\n"); + } + fprintf(fp,"#\n"); /* to stop looking beyond for next entry */ +} + +/* sp_foutput2 -- print out sparse matrix **as a dense matrix** + -- see output format used in matrix.h etc */ +/****************************************************************** +void sp_foutput2(fp,A) +FILE *fp; +SPMAT *A; +{ + int cnt, i, j, j_idx; + SPROW *r; + row_elt *elt; + + if ( A == SMNULL ) + { + fprintf(fp,"Matrix: *** NULL ***\n"); + return; + } + fprintf(fp,"Matrix: %d by %d\n",A->m,A->n); + for ( i = 0; i < A->m; i++ ) + { + fprintf(fp,"row %d:",i); + r = &(A->row[i]); + elt = r->elt; + cnt = j = j_idx = 0; + while ( j_idx < r->len || j < A->n ) + { + if ( j_idx >= r->len ) + fprintf(fp,"%14.9g ",0.0); + else if ( j < elt[j_idx].col ) + fprintf(fp,"%14.9g ",0.0); + else + fprintf(fp,"%14.9g ",elt[j_idx++].val); + if ( cnt++ % 4 == 3 ) + fprintf(fp,"\n"); + j++; + } + fprintf(fp,"\n"); + } +} +******************************************************************/ + +/* sp_dump -- prints ALL relevant information about the sparse matrix A */ +#ifndef ANSI_C +void sp_dump(fp,A) +FILE *fp; +SPMAT *A; +#else +void sp_dump(FILE *fp, const SPMAT *A) +#endif +{ + int i, j, j_idx; + SPROW *rows; + row_elt *elts; + + fprintf(fp,"SparseMatrix dump:\n"); + if ( ! A ) + { fprintf(fp,"*** NULL ***\n"); return; } + fprintf(fp,"Matrix at 0x%lx\n",(long)A); + fprintf(fp,"Dimensions: %d by %d\n",A->m,A->n); + fprintf(fp,"MaxDimensions: %d by %d\n",A->max_m,A->max_n); + fprintf(fp,"flag_col = %d, flag_diag = %d\n",A->flag_col,A->flag_diag); + fprintf(fp,"start_row @ 0x%lx:\n",(long)(A->start_row)); + for ( j = 0; j < A->n; j++ ) + { + fprintf(fp,"%d ",A->start_row[j]); + if ( j % 10 == 9 ) + fprintf(fp,"\n"); + } + fprintf(fp,"\n"); + fprintf(fp,"start_idx @ 0x%lx:\n",(long)(A->start_idx)); + for ( j = 0; j < A->n; j++ ) + { + fprintf(fp,"%d ",A->start_idx[j]); + if ( j % 10 == 9 ) + fprintf(fp,"\n"); + } + fprintf(fp,"\n"); + fprintf(fp,"Rows @ 0x%lx:\n",(long)(A->row)); + if ( ! A->row ) + { fprintf(fp,"*** NULL row ***\n"); return; } + rows = A->row; + for ( i = 0; i < A->m; i++ ) + { + fprintf(fp,"row %d: len = %d, maxlen = %d, diag idx = %d\n", + i,rows[i].len,rows[i].maxlen,rows[i].diag); + fprintf(fp,"element list @ 0x%lx\n",(long)(rows[i].elt)); + if ( ! rows[i].elt ) + { + fprintf(fp,"*** NULL element list ***\n"); + continue; + } + elts = rows[i].elt; + for ( j_idx = 0; j_idx < rows[i].len; j_idx++, elts++ ) + fprintf(fp,"Col: %d, Val: %g, nxt_row = %d, nxt_idx = %d\n", + elts->col,elts->val,elts->nxt_row,elts->nxt_idx); + fprintf(fp,"\n"); + } +} + +#define MINSCRATCH 100 + +/* sp_finput -- input sparse matrix from stream/file fp + -- uses friendly input routine if fp is a tty + -- uses format identical to output format otherwise */ +#ifndef ANSI_C +SPMAT *sp_finput(fp) +FILE *fp; +#else +SPMAT *sp_finput(FILE *fp) +#endif +{ + int i, len, ret_val; + int col, curr_col, m, n, tmp, tty; + Real val; + SPMAT *A; + SPROW *rows; + + static row_elt *scratch; + static int scratch_len = 0; + + if ( ! scratch ) + { + scratch = NEW_A(MINSCRATCH,row_elt); + if ( scratch == NULL ) + error(E_MEM,"sp_finput"); + scratch_len = MINSCRATCH; + } + + for ( i = 0; i < scratch_len; i++ ) + scratch[i].nxt_row = scratch[i].nxt_idx = -1; + + tty = isatty(fileno(fp)); + + if ( tty ) + { + fprintf(stderr,"SparseMatrix: "); + do { + fprintf(stderr,"input rows cols: "); + if ( ! fgets(line,MAXLINE,fp) ) + error(E_INPUT,"sp_finput"); + } while ( sscanf(line,"%u %u",&m,&n) != 2 ); + A = sp_get(m,n,5); + rows = A->row; + + for ( i = 0; i < m; i++ ) + { + /* get a row... */ + fprintf(stderr,"Row %d:\n",i); + fprintf(stderr,"Enter or 'e' to end row\n"); + curr_col = -1; + + len = 0; + for ( ; ; ) /* forever do... */ + { + /* if we need more scratch space, let's get it! + -- using amortized doubling */ + if ( len >= scratch_len ) + { + scratch = RENEW(scratch,2*scratch_len,row_elt); + if ( ! scratch ) + error(E_MEM,"sp_finput"); + scratch_len = 2*scratch_len; + } + do { /* get an entry... */ + fprintf(stderr,"Entry %d: ",len); + if ( ! fgets(line,MAXLINE,fp) ) + error(E_INPUT,"sp_finput"); + if ( *line == 'e' || *line == 'E' ) + break; +#if REAL == DOUBLE + } while ( sscanf(line,"%u %lf",&col,&val) != 2 || +#elif REAL == FLOAT + } while ( sscanf(line,"%u %f",&col,&val) != 2 || +#endif + col >= n || col <= curr_col ); + + if ( *line == 'e' || *line == 'E' ) + break; + + scratch[len].col = col; + scratch[len].val = val; + curr_col = col; + + len++; + } + + /* Note: len = # elements in row */ + if ( len > 5 ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPMAT, + A->row[i].maxlen*sizeof(row_elt), + len*sizeof(row_elt)); + } + + rows[i].elt = (row_elt *)realloc((char *)rows[i].elt, + len*sizeof(row_elt)); + rows[i].maxlen = len; + } + MEM_COPY(scratch,rows[i].elt,len*sizeof(row_elt)); + rows[i].len = len; + rows[i].diag = sprow_idx(&(rows[i]),i); + } + } + else /* not tty */ + { + ret_val = 0; + skipjunk(fp); + fscanf(fp,"SparseMatrix:"); + skipjunk(fp); + if ( (ret_val=fscanf(fp,"%u by %u",&m,&n)) != 2 ) + error((ret_val == EOF) ? E_EOF : E_FORMAT,"sp_finput"); + A = sp_get(m,n,5); + + /* initialise start_row */ + for ( i = 0; i < A->n; i++ ) + A->start_row[i] = -1; + + rows = A->row; + for ( i = 0; i < m; i++ ) + { + /* printf("Reading row # %d\n",i); */ + rows[i].diag = -1; + skipjunk(fp); + if ( (ret_val=fscanf(fp,"row %d :",&tmp)) != 1 || + tmp != i ) + error((ret_val == EOF) ? E_EOF : E_FORMAT, + "sp_finput"); + curr_col = -1; + len = 0; + for ( ; ; ) /* forever do... */ + { + /* if we need more scratch space, let's get it! + -- using amortized doubling */ + if ( len >= scratch_len ) + { + scratch = RENEW(scratch,2*scratch_len,row_elt); + if ( ! scratch ) + error(E_MEM,"sp_finput"); + scratch_len = 2*scratch_len; + } +#if REAL == DOUBLE + if ( (ret_val=fscanf(fp,"%u : %lf",&col,&val)) != 2 ) +#elif REAL == FLOAT + if ( (ret_val=fscanf(fp,"%u : %f",&col,&val)) != 2 ) +#endif + break; + if ( col <= curr_col || col >= n ) + error(E_FORMAT,"sp_finput"); + scratch[len].col = col; + scratch[len].val = val; + + len++; + } + if ( ret_val == EOF ) + error(E_EOF,"sp_finput"); + + if ( len > rows[i].maxlen ) + { + rows[i].elt = (row_elt *)realloc((char *)rows[i].elt, + len*sizeof(row_elt)); + rows[i].maxlen = len; + } + MEM_COPY(scratch,rows[i].elt,len*sizeof(row_elt)); + rows[i].len = len; + /* printf("Have read row # %d\n",i); */ + rows[i].diag = sprow_idx(&(rows[i]),i); + /* printf("Have set diag index for row # %d\n",i); */ + } + } + + return A; +} + diff --git a/spbkp.c b/spbkp.c new file mode 100644 index 0000000..fe9d4c2 --- /dev/null +++ b/spbkp.c @@ -0,0 +1,1445 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Sparse matrix Bunch--Kaufman--Parlett factorisation and solve + Radical revision started Thu 05th Nov 1992, 09:36:12 AM + to use Karen George's suggestion of leaving the the row elements unordered + Radical revision completed Mon 07th Dec 1992, 10:59:57 AM +*/ + +static char rcsid[] = "$Id: spbkp.c,v 1.6 1996/08/20 19:53:10 stewart Exp $"; + +#include +#include +#include "sparse2.h" + + +#ifdef MALLOCDECL +#include +#endif + +#define alpha 0.6403882032022076 /* = (1+sqrt(17))/8 */ + + +#define btos(x) ((x) ? "TRUE" : "FALSE") + +/* assume no use of sqr() uses side-effects */ +#define sqr(x) ((x)*(x)) + +/* unord_get_idx -- returns index (encoded if entry not allocated) + of the element of row r with column j + -- uses linear search */ +#ifndef ANSI_C +int unord_get_idx(r,j) +SPROW *r; +int j; +#else +int unord_get_idx(SPROW *r, int j) +#endif +{ + int idx; + row_elt *e; + + if ( ! r || ! r->elt ) + error(E_NULL,"unord_get_idx"); + for ( idx = 0, e = r->elt; idx < r->len; idx++, e++ ) + if ( e->col == j ) + break; + if ( idx >= r->len ) + return -(r->len+2); + else + return idx; +} + +/* unord_get_val -- returns value of the (i,j) entry of A + -- same assumptions as unord_get_idx() */ +#ifndef ANSI_C +double unord_get_val(A,i,j) +SPMAT *A; +int i, j; +#else +double unord_get_val(SPMAT *A, int i, int j) +#endif +{ + SPROW *r; + int idx; + + if ( ! A ) + error(E_NULL,"unord_get_val"); + if ( i < 0 || i >= A->m || j < 0 || j >= A->n ) + error(E_BOUNDS,"unord_get_val"); + + r = &(A->row[i]); + idx = unord_get_idx(r,j); + if ( idx < 0 ) + return 0.0; + else + return r->elt[idx].val; +} + + +/* bkp_swap_elt -- swaps the (i,j) with the (k,l) entry of sparse matrix + -- either or both of the entries may be unallocated */ +#ifndef ANSI_C +static SPMAT *bkp_swap_elt(A,i1,j1,idx1,i2,j2,idx2) +SPMAT *A; +int i1, j1, idx1, i2, j2, idx2; +#else +static SPMAT *bkp_swap_elt(SPMAT *A, int i1, int j1, + int idx1, int i2, int j2, int idx2) +#endif +{ + int tmp_row, tmp_idx; + SPROW *r1, *r2; + row_elt *e1, *e2; + Real tmp; + + if ( ! A ) + error(E_NULL,"bkp_swap_elt"); + + if ( i1 < 0 || j1 < 0 || i2 < 0 || j2 < 0 || + i1 >= A->m || j1 >= A->n || i2 >= A->m || j2 >= A->n ) + { + error(E_BOUNDS,"bkp_swap_elt"); + } + + if ( i1 == i2 && j1 == j2 ) + return A; + if ( idx1 < 0 && idx2 < 0 ) /* neither allocated */ + return A; + + r1 = &(A->row[i1]); r2 = &(A->row[i2]); + /* if ( idx1 >= r1->len || idx2 >= r2->len ) + error(E_BOUNDS,"bkp_swap_elt"); */ + if ( idx1 < 0 ) /* assume not allocated */ + { + idx1 = r1->len; + if ( idx1 >= r1->maxlen ) + { tracecatch(sprow_xpd(r1,2*r1->maxlen+1,TYPE_SPMAT), + "bkp_swap_elt"); } + r1->len = idx1+1; + r1->elt[idx1].col = j1; + r1->elt[idx1].val = 0.0; + /* now patch up column access path */ + tmp_row = -1; tmp_idx = j1; + chase_col(A,j1,&tmp_row,&tmp_idx,i1-1); + + if ( tmp_row < 0 ) + { + r1->elt[idx1].nxt_row = A->start_row[j1]; + r1->elt[idx1].nxt_idx = A->start_idx[j1]; + A->start_row[j1] = i1; + A->start_idx[j1] = idx1; + } + else + { + row_elt *tmp_e; + + tmp_e = &(A->row[tmp_row].elt[tmp_idx]); + r1->elt[idx1].nxt_row = tmp_e->nxt_row; + r1->elt[idx1].nxt_idx = tmp_e->nxt_idx; + tmp_e->nxt_row = i1; + tmp_e->nxt_idx = idx1; + } + } + else if ( r1->elt[idx1].col != j1 ) + error(E_INTERN,"bkp_swap_elt"); + if ( idx2 < 0 ) + { + idx2 = r2->len; + if ( idx2 >= r2->maxlen ) + { tracecatch(sprow_xpd(r2,2*r2->maxlen+1,TYPE_SPMAT), + "bkp_swap_elt"); } + + r2->len = idx2+1; + r2->elt[idx2].col = j2; + r2->elt[idx2].val = 0.0; + /* now patch up column access path */ + tmp_row = -1; tmp_idx = j2; + chase_col(A,j2,&tmp_row,&tmp_idx,i2-1); + if ( tmp_row < 0 ) + { + r2->elt[idx2].nxt_row = A->start_row[j2]; + r2->elt[idx2].nxt_idx = A->start_idx[j2]; + A->start_row[j2] = i2; + A->start_idx[j2] = idx2; + } + else + { + row_elt *tmp_e; + + tmp_e = &(A->row[tmp_row].elt[tmp_idx]); + r2->elt[idx2].nxt_row = tmp_e->nxt_row; + r2->elt[idx2].nxt_idx = tmp_e->nxt_idx; + tmp_e->nxt_row = i2; + tmp_e->nxt_idx = idx2; + } + } + else if ( r2->elt[idx2].col != j2 ) + error(E_INTERN,"bkp_swap_elt"); + + e1 = &(r1->elt[idx1]); e2 = &(r2->elt[idx2]); + + tmp = e1->val; + e1->val = e2->val; + e2->val = tmp; + + return A; +} + +/* bkp_bump_col -- bumps row and idx to next entry in column j */ +#ifndef ANSI_C +row_elt *bkp_bump_col(A, j, row, idx) +SPMAT *A; +int j, *row, *idx; +#else +row_elt *bkp_bump_col(SPMAT *A, int j, int *row, int *idx) +#endif +{ + SPROW *r; + row_elt *e; + + if ( *row < 0 ) + { + *row = A->start_row[j]; + *idx = A->start_idx[j]; + } + else + { + r = &(A->row[*row]); + e = &(r->elt[*idx]); + if ( e->col != j ) + error(E_INTERN,"bkp_bump_col"); + *row = e->nxt_row; + *idx = e->nxt_idx; + } + if ( *row < 0 ) + return (row_elt *)NULL; + else + return &(A->row[*row].elt[*idx]); +} + +/* bkp_interchange -- swap rows/cols i and j (symmetric pivot) + -- uses just the upper triangular part */ +#ifndef ANSI_C +SPMAT *bkp_interchange(A, i1, i2) +SPMAT *A; +int i1, i2; +#else +SPMAT *bkp_interchange(SPMAT *A, int i1, int i2) +#endif +{ + int tmp_row, tmp_idx; + int row1, row2, idx1, idx2, tmp_row1, tmp_idx1, tmp_row2, tmp_idx2; + SPROW *r1, *r2; + row_elt *e1, *e2; + IVEC *done_list = IVNULL; + + if ( ! A ) + error(E_NULL,"bkp_interchange"); + if ( i1 < 0 || i1 >= A->n || i2 < 0 || i2 >= A->n ) + error(E_BOUNDS,"bkp_interchange"); + if ( A->m != A->n ) + error(E_SQUARE,"bkp_interchange"); + + if ( i1 == i2 ) + return A; + if ( i1 > i2 ) + { tmp_idx = i1; i1 = i2; i2 = tmp_idx; } + + done_list = iv_resize(done_list,A->n); + for ( tmp_idx = 0; tmp_idx < A->n; tmp_idx++ ) + done_list->ive[tmp_idx] = FALSE; + row1 = -1; idx1 = i1; + row2 = -1; idx2 = i2; + e1 = bkp_bump_col(A,i1,&row1,&idx1); + e2 = bkp_bump_col(A,i2,&row2,&idx2); + + while ( (row1 >= 0 && row1 < i1) || (row2 >= 0 && row2 < i1) ) + /* Note: "row2 < i1" not "row2 < i2" as we must stop before the + "knee bend" */ + { + if ( row1 >= 0 && row1 < i1 && ( row1 < row2 || row2 < 0 ) ) + { + tmp_row1 = row1; tmp_idx1 = idx1; + e1 = bkp_bump_col(A,i1,&tmp_row1,&tmp_idx1); + if ( ! done_list->ive[row1] ) + { + if ( row1 == row2 ) + bkp_swap_elt(A,row1,i1,idx1,row1,i2,idx2); + else + bkp_swap_elt(A,row1,i1,idx1,row1,i2,-1); + done_list->ive[row1] = TRUE; + } + row1 = tmp_row1; idx1 = tmp_idx1; + } + else if ( row2 >= 0 && row2 < i1 && ( row2 < row1 || row1 < 0 ) ) + { + tmp_row2 = row2; tmp_idx2 = idx2; + e2 = bkp_bump_col(A,i2,&tmp_row2,&tmp_idx2); + if ( ! done_list->ive[row2] ) + { + if ( row1 == row2 ) + bkp_swap_elt(A,row2,i1,idx1,row2,i2,idx2); + else + bkp_swap_elt(A,row2,i1,-1,row2,i2,idx2); + done_list->ive[row2] = TRUE; + } + row2 = tmp_row2; idx2 = tmp_idx2; + } + else if ( row1 == row2 ) + { + tmp_row1 = row1; tmp_idx1 = idx1; + e1 = bkp_bump_col(A,i1,&tmp_row1,&tmp_idx1); + tmp_row2 = row2; tmp_idx2 = idx2; + e2 = bkp_bump_col(A,i2,&tmp_row2,&tmp_idx2); + if ( ! done_list->ive[row1] ) + { + bkp_swap_elt(A,row1,i1,idx1,row2,i2,idx2); + done_list->ive[row1] = TRUE; + } + row1 = tmp_row1; idx1 = tmp_idx1; + row2 = tmp_row2; idx2 = tmp_idx2; + } + } + + /* ensure we are **past** the first knee */ + while ( row2 >= 0 && row2 <= i1 ) + e2 = bkp_bump_col(A,i2,&row2,&idx2); + + /* at/after 1st "knee bend" */ + r1 = &(A->row[i1]); + idx1 = 0; + e1 = &(r1->elt[idx1]); + while ( row2 >= 0 && row2 < i2 ) + { + /* used for update of e2 at end of loop */ + tmp_row = row2; tmp_idx = idx2; + if ( ! done_list->ive[row2] ) + { + r2 = &(A->row[row2]); + bkp_bump_col(A,i2,&tmp_row,&tmp_idx); + done_list->ive[row2] = TRUE; + tmp_idx1 = unord_get_idx(r1,row2); + tracecatch(bkp_swap_elt(A,row2,i2,idx2,i1,row2,tmp_idx1), + "bkp_interchange"); + } + + /* update e1 and e2 */ + row2 = tmp_row; idx2 = tmp_idx; + e2 = ( row2 >= 0 ) ? &(A->row[row2].elt[idx2]) : (row_elt *)NULL; + } + + idx1 = 0; + e1 = r1->elt; + while ( idx1 < r1->len ) + { + if ( e1->col >= i2 || e1->col <= i1 ) + { + idx1++; + e1++; + continue; + } + if ( ! done_list->ive[e1->col] ) + { + tmp_idx2 = unord_get_idx(&(A->row[e1->col]),i2); + tracecatch(bkp_swap_elt(A,i1,e1->col,idx1,e1->col,i2,tmp_idx2), + "bkp_interchange"); + done_list->ive[e1->col] = TRUE; + } + idx1++; + e1++; + } + + /* at/after 2nd "knee bend" */ + idx1 = 0; + e1 = &(r1->elt[idx1]); + r2 = &(A->row[i2]); + idx2 = 0; + e2 = &(r2->elt[idx2]); + while ( idx1 < r1->len ) + { + if ( e1->col <= i2 ) + { + idx1++; e1++; + continue; + } + if ( ! done_list->ive[e1->col] ) + { + tmp_idx2 = unord_get_idx(r2,e1->col); + tracecatch(bkp_swap_elt(A,i1,e1->col,idx1,i2,e1->col,tmp_idx2), + "bkp_interchange"); + done_list->ive[e1->col] = TRUE; + } + idx1++; e1++; + } + + idx2 = 0; e2 = r2->elt; + while ( idx2 < r2->len ) + { + if ( e2->col <= i2 ) + { + idx2++; e2++; + continue; + } + if ( ! done_list->ive[e2->col] ) + { + tmp_idx1 = unord_get_idx(r1,e2->col); + tracecatch(bkp_swap_elt(A,i2,e2->col,idx2,i1,e2->col,tmp_idx1), + "bkp_interchange"); + done_list->ive[e2->col] = TRUE; + } + idx2++; e2++; + } + + /* now interchange the digonal entries! */ + idx1 = unord_get_idx(&(A->row[i1]),i1); + idx2 = unord_get_idx(&(A->row[i2]),i2); + if ( idx1 >= 0 || idx2 >= 0 ) + { + tracecatch(bkp_swap_elt(A,i1,i1,idx1,i2,i2,idx2), + "bkp_interchange"); + } + + return A; +} + + +/* iv_min -- returns minimum of an integer vector + -- sets index to the position in iv if index != NULL */ +#ifndef ANSI_C +int iv_min(iv,index) +IVEC *iv; +int *index; +#else +int iv_min(IVEC *iv, int *index) +#endif +{ + int i, i_min, min_val, tmp; + + if ( ! iv ) + error(E_NULL,"iv_min"); + if ( iv->dim <= 0 ) + error(E_SIZES,"iv_min"); + i_min = 0; + min_val = iv->ive[0]; + for ( i = 1; i < iv->dim; i++ ) + { + tmp = iv->ive[i]; + if ( tmp < min_val ) + { + min_val = tmp; + i_min = i; + } + } + + if ( index != (int *)NULL ) + *index = i_min; + + return min_val; +} + +/* max_row_col -- returns max { |A[j][k]| : k >= i, k != j, k != l } given j + using symmetry and only the upper triangular part of A */ +#ifndef ANSI_C +static double max_row_col(A,i,j,l) +SPMAT *A; +int i, j, l; +#else +static double max_row_col(SPMAT *A, int i,int j, int l) +#endif +{ + int row_num, idx; + SPROW *r; + row_elt *e; + Real max_val, tmp; + + if ( ! A ) + error(E_NULL,"max_row_col"); + if ( i < 0 || i > A->n || j < 0 || j >= A->n ) + error(E_BOUNDS,"max_row_col"); + + max_val = 0.0; + + idx = unord_get_idx(&(A->row[i]),j); + if ( idx < 0 ) + { + row_num = -1; idx = j; + e = chase_past(A,j,&row_num,&idx,i); + } + else + { + row_num = i; + e = &(A->row[i].elt[idx]); + } + while ( row_num >= 0 && row_num < j ) + { + if ( row_num != l ) + { + tmp = fabs(e->val); + if ( tmp > max_val ) + max_val = tmp; + } + e = bump_col(A,j,&row_num,&idx); + } + r = &(A->row[j]); + for ( idx = 0, e = r->elt; idx < r->len; idx++, e++ ) + { + if ( e->col > j && e->col != l ) + { + tmp = fabs(e->val); + if ( tmp > max_val ) + max_val = tmp; + } + } + + return max_val; +} + +/* nonzeros -- counts non-zeros in A */ +#ifndef ANSI_C +static int nonzeros(A) +SPMAT *A; +#else +static int nonzeros(const SPMAT *A) +#endif +{ + int cnt, i; + + if ( ! A ) + return 0; + cnt = 0; + for ( i = 0; i < A->m; i++ ) + cnt += A->row[i].len; + + return cnt; +} + +/* chk_col_access -- for spBKPfactor() + -- checks that column access path is OK */ +#ifndef ANSI_C +int chk_col_access(A) +SPMAT *A; +#else +int chk_col_access(const SPMAT *A) +#endif +{ + int cnt_nz, j, row, idx; + SPROW *r; + row_elt *e; + + if ( ! A ) + error(E_NULL,"chk_col_access"); + + /* count nonzeros as we go down columns */ + cnt_nz = 0; + for ( j = 0; j < A->n; j++ ) + { + row = A->start_row[j]; + idx = A->start_idx[j]; + while ( row >= 0 ) + { + if ( row >= A->m || idx < 0 ) + return FALSE; + r = &(A->row[row]); + if ( idx >= r->len ) + return FALSE; + e = &(r->elt[idx]); + if ( e->nxt_row >= 0 && e->nxt_row <= row ) + return FALSE; + row = e->nxt_row; + idx = e->nxt_idx; + cnt_nz++; + } + } + + if ( cnt_nz != nonzeros(A) ) + return FALSE; + else + return TRUE; +} + +/* col_cmp -- compare two columns -- for sorting rows using qsort() */ +#ifndef ANSI_C +static int col_cmp(e1,e2) +row_elt *e1, *e2; +#else +static int col_cmp(const row_elt *e1, const row_elt *e2) +#endif +{ + return e1->col - e2->col; +} + +/* spBKPfactor -- sparse Bunch-Kaufman-Parlett factorisation of A in-situ + -- A is factored into the form P'AP = MDM' where + P is a permutation matrix, M lower triangular and D is block + diagonal with blocks of size 1 or 2 + -- P is stored in pivot; blocks[i]==i iff D[i][i] is a block */ +#ifndef ANSI_C +SPMAT *spBKPfactor(A,pivot,blocks,tol) +SPMAT *A; +PERM *pivot, *blocks; +double tol; +#else +SPMAT *spBKPfactor(SPMAT *A, PERM *pivot, PERM *blocks, double tol) +#endif +{ + int i, j, k, l, n, onebyone, r; + int idx, idx1, idx_piv; + int row_num; + int best_deg, best_j, best_l, best_cost, mark_cost, deg, deg_j, + deg_l, ignore_deg; + int list_idx, list_idx2, old_list_idx; + SPROW *row, *r_piv, *r1_piv; + row_elt *e, *e1; + Real aii, aip1, aip1i; + Real det, max_j, max_l, s, t; + STATIC IVEC *scan_row = IVNULL, *scan_idx = IVNULL, *col_list = IVNULL, + *tmp_iv = IVNULL; + STATIC IVEC *deg_list = IVNULL; + STATIC IVEC *orig_idx = IVNULL, *orig1_idx = IVNULL; + STATIC PERM *order = PNULL; + + if ( ! A || ! pivot || ! blocks ) + error(E_NULL,"spBKPfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"spBKPfactor"); + if ( A->m != pivot->size || pivot->size != blocks->size ) + error(E_SIZES,"spBKPfactor"); + if ( tol <= 0.0 || tol > 1.0 ) + error(E_RANGE,"spBKPfactor"); + + n = A->n; + + px_ident(pivot); px_ident(blocks); + sp_col_access(A); sp_diag_access(A); + ignore_deg = FALSE; + + deg_list = iv_resize(deg_list,n); + if ( order != NULL ) + px_ident(order); + order = px_resize(order,n); + MEM_STAT_REG(deg_list,TYPE_IVEC); + MEM_STAT_REG(order,TYPE_PERM); + + scan_row = iv_resize(scan_row,5); + scan_idx = iv_resize(scan_idx,5); + col_list = iv_resize(col_list,5); + orig_idx = iv_resize(orig_idx,5); + orig_idx = iv_resize(orig1_idx,5); + orig_idx = iv_resize(tmp_iv,5); + MEM_STAT_REG(scan_row,TYPE_IVEC); + MEM_STAT_REG(scan_idx,TYPE_IVEC); + MEM_STAT_REG(col_list,TYPE_IVEC); + MEM_STAT_REG(orig_idx,TYPE_IVEC); + MEM_STAT_REG(orig1_idx,TYPE_IVEC); + MEM_STAT_REG(tmp_iv,TYPE_IVEC); + + for ( i = 0; i < n-1; i = onebyone ? i+1 : i+2 ) + { + /* now we want to use a Markowitz-style selection rule for + determining which rows to swap and whether to use + 1x1 or 2x2 pivoting */ + + /* get list of degrees of nodes */ + deg_list = iv_resize(deg_list,n-i); + if ( ! ignore_deg ) + for ( j = i; j < n; j++ ) + deg_list->ive[j-i] = 0; + else + { + for ( j = i; j < n; j++ ) + deg_list->ive[j-i] = 1; + if ( i < n ) + deg_list->ive[0] = 0; + } + order = px_resize(order,n-i); + px_ident(order); + + if ( ! ignore_deg ) + { + for ( j = i; j < n; j++ ) + { + /* idx = sprow_idx(&(A->row[j]),j+1); */ + /* idx = fixindex(idx); */ + idx = 0; + row = &(A->row[j]); + e = &(row->elt[idx]); + /* deg_list->ive[j-i] += row->len - idx; */ + for ( ; idx < row->len; idx++, e++ ) + if ( e->col >= i ) + deg_list->ive[e->col - i]++; + } + /* now deg_list[k] == degree of node k+i */ + + /* now sort them into increasing order */ + iv_sort(deg_list,order); + /* now deg_list[idx] == degree of node i+order[idx] */ + } + + /* now we can chase through the nodes in order of increasing + degree, picking out the ones that satisfy our stability + criterion */ + list_idx = 0; r = -1; + best_j = best_l = -1; + for ( deg = 0; deg <= n; deg++ ) + { + Real ajj, all, ajl; + + if ( list_idx >= deg_list->dim ) + break; /* That's all folks! */ + old_list_idx = list_idx; + while ( list_idx < deg_list->dim && + deg_list->ive[list_idx] <= deg ) + { + j = i+order->pe[list_idx]; + if ( j < i ) + continue; + /* can we use row/col j for a 1 x 1 pivot? */ + /* find max_j = max_{k>=i} {|A[k][j]|,|A[j][k]|} */ + ajj = fabs(unord_get_val(A,j,j)); + if ( ajj == 0.0 ) + { + list_idx++; + continue; /* can't use this for 1 x 1 pivot */ + } + + max_j = max_row_col(A,i,j,-1); + if ( ajj >= tol/* *alpha */ *max_j ) + { + onebyone = TRUE; + best_j = j; + best_deg = deg_list->ive[list_idx]; + break; + } + list_idx++; + } + if ( best_j >= 0 ) + break; + best_cost = 2*n; /* > any possible Markowitz cost (bound) */ + best_j = best_l = -1; + list_idx = old_list_idx; + while ( list_idx < deg_list->dim && + deg_list->ive[list_idx] <= deg ) + { + j = i+order->pe[list_idx]; + ajj = fabs(unord_get_val(A,j,j)); + for ( list_idx2 = 0; list_idx2 < list_idx; list_idx2++ ) + { + deg_j = deg; + deg_l = deg_list->ive[list_idx2]; + l = i+order->pe[list_idx2]; + if ( l < i ) + continue; + /* try using rows/cols (j,l) for a 2 x 2 pivot block */ + all = fabs(unord_get_val(A,l,l)); + ajl = ( j > l ) ? fabs(unord_get_val(A,l,j)) : + fabs(unord_get_val(A,j,l)); + det = fabs(ajj*all - ajl*ajl); + if ( det == 0.0 ) + continue; + max_j = max_row_col(A,i,j,l); + max_l = max_row_col(A,i,l,j); + if ( tol*(all*max_j+ajl*max_l) < det && + tol*(ajl*max_j+ajj*max_l) < det ) + { + /* acceptably stable 2 x 2 pivot */ + /* this is actually an overestimate of the + Markowitz cost for choosing (j,l) */ + mark_cost = (ajj == 0.0) ? + ((all == 0.0) ? deg_j+deg_l : deg_j+2*deg_l) : + ((all == 0.0) ? 2*deg_j+deg_l : + 2*(deg_j+deg_l)); + if ( mark_cost < best_cost ) + { + onebyone = FALSE; + best_cost = mark_cost; + best_j = j; + best_l = l; + best_deg = deg_j; + } + } + } + list_idx++; + } + if ( best_j >= 0 ) + break; + } + + if ( best_deg > (int)floor(0.8*(n-i)) ) + ignore_deg = TRUE; + + /* now do actual interchanges */ + if ( best_j >= 0 && onebyone ) + { + bkp_interchange(A,i,best_j); + px_transp(pivot,i,best_j); + } + else if ( best_j >= 0 && best_l >= 0 && ! onebyone ) + { + if ( best_j == i || best_j == i+1 ) + { + if ( best_l == i || best_l == i+1 ) + { + /* no pivoting, but must update blocks permutation */ + px_transp(blocks,i,i+1); + goto dopivot; + } + bkp_interchange(A,(best_j == i) ? i+1 : i,best_l); + px_transp(pivot,(best_j == i) ? i+1 : i,best_l); + } + else if ( best_l == i || best_l == i+1 ) + { + bkp_interchange(A,(best_l == i) ? i+1 : i,best_j); + px_transp(pivot,(best_l == i) ? i+1 : i,best_j); + } + else /* best_j & best_l outside i, i+1 */ + { + if ( i != best_j ) + { + bkp_interchange(A,i,best_j); + px_transp(pivot,i,best_j); + } + if ( i+1 != best_l ) + { + bkp_interchange(A,i+1,best_l); + px_transp(pivot,i+1,best_l); + } + } + } + else /* can't pivot &/or nothing to pivot */ + continue; + + /* update blocks permutation */ + if ( ! onebyone ) + px_transp(blocks,i,i+1); + + dopivot: + if ( onebyone ) + { + int idx_j, idx_k, s_idx, s_idx2; + row_elt *e_ij, *e_ik; + + r_piv = &(A->row[i]); + idx_piv = unord_get_idx(r_piv,i); + /* if idx_piv < 0 then aii == 0 and no pivoting can be done; + -- this means that we should continue to the next iteration */ + if ( idx_piv < 0 ) + continue; + aii = r_piv->elt[idx_piv].val; + if ( aii == 0.0 ) + continue; + + /* for ( j = i+1; j < n; j++ ) { ... pivot step ... } */ + /* initialise scan_... etc for the 1 x 1 pivot */ + scan_row = iv_resize(scan_row,r_piv->len); + scan_idx = iv_resize(scan_idx,r_piv->len); + col_list = iv_resize(col_list,r_piv->len); + orig_idx = iv_resize(orig_idx,r_piv->len); + row_num = i; s_idx = idx = 0; + e = &(r_piv->elt[idx]); + for ( idx = 0; idx < r_piv->len; idx++, e++ ) + { + if ( e->col < i ) + continue; + scan_row->ive[s_idx] = i; + scan_idx->ive[s_idx] = idx; + orig_idx->ive[s_idx] = idx; + col_list->ive[s_idx] = e->col; + s_idx++; + } + scan_row = iv_resize(scan_row,s_idx); + scan_idx = iv_resize(scan_idx,s_idx); + col_list = iv_resize(col_list,s_idx); + orig_idx = iv_resize(orig_idx,s_idx); + + order = px_resize(order,scan_row->dim); + px_ident(order); + iv_sort(col_list,order); + + tmp_iv = iv_resize(tmp_iv,scan_row->dim); + for ( idx = 0; idx < order->size; idx++ ) + tmp_iv->ive[idx] = scan_idx->ive[order->pe[idx]]; + iv_copy(tmp_iv,scan_idx); + for ( idx = 0; idx < order->size; idx++ ) + tmp_iv->ive[idx] = scan_row->ive[order->pe[idx]]; + iv_copy(tmp_iv,scan_row); + for ( idx = 0; idx < scan_row->dim; idx++ ) + tmp_iv->ive[idx] = orig_idx->ive[order->pe[idx]]; + iv_copy(tmp_iv,orig_idx); + + /* now do actual pivot */ + /* for ( j = i+1; j < n-1; j++ ) .... */ + + for ( s_idx = 0; s_idx < scan_row->dim; s_idx++ ) + { + idx_j = orig_idx->ive[s_idx]; + if ( idx_j < 0 ) + error(E_INTERN,"spBKPfactor"); + e_ij = &(r_piv->elt[idx_j]); + j = e_ij->col; + if ( j < i+1 ) + continue; + scan_to(A,scan_row,scan_idx,col_list,j); + + /* compute multiplier */ + t = e_ij->val / aii; + + /* for ( k = j; k < n; k++ ) { .... update A[j][k] .... } */ + /* this is the row in which pivoting is done */ + row = &(A->row[j]); + for ( s_idx2 = s_idx; s_idx2 < scan_row->dim; s_idx2++ ) + { + idx_k = orig_idx->ive[s_idx2]; + e_ik = &(r_piv->elt[idx_k]); + k = e_ik->col; + /* k >= j since col_list has been sorted */ + + if ( scan_row->ive[s_idx2] == j ) + { /* no fill-in -- can be done directly */ + idx = scan_idx->ive[s_idx2]; + /* idx = sprow_idx2(row,k,idx); */ + row->elt[idx].val -= t*e_ik->val; + } + else + { /* fill-in -- insert entry & patch column */ + int old_row, old_idx; + row_elt *old_e, *new_e; + + old_row = scan_row->ive[s_idx2]; + old_idx = scan_idx->ive[s_idx2]; + /* old_idx = sprow_idx2(&(A->row[old_row]),k,old_idx); */ + + if ( old_idx < 0 ) + error(E_INTERN,"spBKPfactor"); + /* idx = sprow_idx(row,k); */ + /* idx = fixindex(idx); */ + idx = row->len; + + /* sprow_set_val(row,k,-t*e_ik->val); */ + if ( row->len >= row->maxlen ) + { tracecatch(sprow_xpd(row,2*row->maxlen+1,TYPE_SPMAT), + "spBKPfactor"); } + + row->len = idx+1; + + new_e = &(row->elt[idx]); + new_e->val = -t*e_ik->val; + new_e->col = k; + + old_e = &(A->row[old_row].elt[old_idx]); + new_e->nxt_row = old_e->nxt_row; + new_e->nxt_idx = old_e->nxt_idx; + old_e->nxt_row = j; + old_e->nxt_idx = idx; + } + } + e_ij->val = t; + } + } + else /* onebyone == FALSE */ + { /* do 2 x 2 pivot */ + int idx_k, idx1_k, s_idx, s_idx2; + int old_col; + row_elt *e_tmp; + + r_piv = &(A->row[i]); + idx_piv = unord_get_idx(r_piv,i); + aii = aip1i = 0.0; + e_tmp = r_piv->elt; + for ( idx_piv = 0; idx_piv < r_piv->len; idx_piv++, e_tmp++ ) + if ( e_tmp->col == i ) + aii = e_tmp->val; + else if ( e_tmp->col == i+1 ) + aip1i = e_tmp->val; + + r1_piv = &(A->row[i+1]); + e_tmp = r1_piv->elt; + aip1 = unord_get_val(A,i+1,i+1); + det = aii*aip1 - aip1i*aip1i; /* Must have det < 0 */ + if ( aii == 0.0 && aip1i == 0.0 ) + { + /* error(E_RANGE,"spBKPfactor"); */ + onebyone = TRUE; + continue; /* cannot pivot */ + } + + if ( det == 0.0 ) + { + if ( aii != 0.0 ) + error(E_RANGE,"spBKPfactor"); + onebyone = TRUE; + continue; /* cannot pivot */ + } + aip1i = aip1i/det; + aii = aii/det; + aip1 = aip1/det; + + /* initialise scan_... etc for the 2 x 2 pivot */ + s_idx = r_piv->len + r1_piv->len; + scan_row = iv_resize(scan_row,s_idx); + scan_idx = iv_resize(scan_idx,s_idx); + col_list = iv_resize(col_list,s_idx); + orig_idx = iv_resize(orig_idx,s_idx); + orig1_idx = iv_resize(orig1_idx,s_idx); + + e = r_piv->elt; + for ( idx = 0; idx < r_piv->len; idx++, e++ ) + { + scan_row->ive[idx] = i; + scan_idx->ive[idx] = idx; + col_list->ive[idx] = e->col; + orig_idx->ive[idx] = idx; + orig1_idx->ive[idx] = -1; + } + e = r_piv->elt; + e1 = r1_piv->elt; + for ( idx = 0; idx < r1_piv->len; idx++, e1++ ) + { + scan_row->ive[idx+r_piv->len] = i+1; + scan_idx->ive[idx+r_piv->len] = idx; + col_list->ive[idx+r_piv->len] = e1->col; + orig_idx->ive[idx+r_piv->len] = -1; + orig1_idx->ive[idx+r_piv->len] = idx; + } + + e1 = r1_piv->elt; + order = px_resize(order,scan_row->dim); + px_ident(order); + iv_sort(col_list,order); + tmp_iv = iv_resize(tmp_iv,scan_row->dim); + for ( idx = 0; idx < order->size; idx++ ) + tmp_iv->ive[idx] = scan_idx->ive[order->pe[idx]]; + iv_copy(tmp_iv,scan_idx); + for ( idx = 0; idx < order->size; idx++ ) + tmp_iv->ive[idx] = scan_row->ive[order->pe[idx]]; + iv_copy(tmp_iv,scan_row); + for ( idx = 0; idx < scan_row->dim; idx++ ) + tmp_iv->ive[idx] = orig_idx->ive[order->pe[idx]]; + iv_copy(tmp_iv,orig_idx); + for ( idx = 0; idx < scan_row->dim; idx++ ) + tmp_iv->ive[idx] = orig1_idx->ive[order->pe[idx]]; + iv_copy(tmp_iv,orig1_idx); + + s_idx = 0; + old_col = -1; + for ( idx = 0; idx < scan_row->dim; idx++ ) + { + if ( col_list->ive[idx] == old_col ) + { + if ( scan_row->ive[idx] == i ) + { + scan_row->ive[s_idx-1] = scan_row->ive[idx]; + scan_idx->ive[s_idx-1] = scan_idx->ive[idx]; + col_list->ive[s_idx-1] = col_list->ive[idx]; + orig_idx->ive[s_idx-1] = orig_idx->ive[idx]; + orig1_idx->ive[s_idx-1] = orig1_idx->ive[idx-1]; + } + else if ( idx > 0 ) + { + scan_row->ive[s_idx-1] = scan_row->ive[idx-1]; + scan_idx->ive[s_idx-1] = scan_idx->ive[idx-1]; + col_list->ive[s_idx-1] = col_list->ive[idx-1]; + orig_idx->ive[s_idx-1] = orig_idx->ive[idx-1]; + orig1_idx->ive[s_idx-1] = orig1_idx->ive[idx]; + } + } + else + { + scan_row->ive[s_idx] = scan_row->ive[idx]; + scan_idx->ive[s_idx] = scan_idx->ive[idx]; + col_list->ive[s_idx] = col_list->ive[idx]; + orig_idx->ive[s_idx] = orig_idx->ive[idx]; + orig1_idx->ive[s_idx] = orig1_idx->ive[idx]; + s_idx++; + } + old_col = col_list->ive[idx]; + } + scan_row = iv_resize(scan_row,s_idx); + scan_idx = iv_resize(scan_idx,s_idx); + col_list = iv_resize(col_list,s_idx); + orig_idx = iv_resize(orig_idx,s_idx); + orig1_idx = iv_resize(orig1_idx,s_idx); + + /* for ( j = i+2; j < n; j++ ) { .... row operation .... } */ + for ( s_idx = 0; s_idx < scan_row->dim; s_idx++ ) + { + int idx_piv, idx1_piv; + Real aip1j, aij, aik, aip1k; + row_elt *e_ik, *e_ip1k; + + j = col_list->ive[s_idx]; + if ( j < i+2 ) + continue; + tracecatch(scan_to(A,scan_row,scan_idx,col_list,j), + "spBKPfactor"); + + idx_piv = orig_idx->ive[s_idx]; + aij = ( idx_piv < 0 ) ? 0.0 : r_piv->elt[idx_piv].val; + /* aij = ( s_idx < r_piv->len ) ? r_piv->elt[s_idx].val : + 0.0; */ + /* aij = sp_get_val(A,i,j); */ + idx1_piv = orig1_idx->ive[s_idx]; + aip1j = ( idx1_piv < 0 ) ? 0.0 : r1_piv->elt[idx1_piv].val; + /* aip1j = ( s_idx < r_piv->len ) ? 0.0 : + r1_piv->elt[s_idx-r_piv->len].val; */ + /* aip1j = sp_get_val(A,i+1,j); */ + s = - aip1i*aip1j + aip1*aij; + t = - aip1i*aij + aii*aip1j; + + /* for ( k = j; k < n; k++ ) { .... update entry .... } */ + row = &(A->row[j]); + /* set idx_k and idx1_k indices */ + s_idx2 = s_idx; + k = col_list->ive[s_idx2]; + idx_k = orig_idx->ive[s_idx2]; + idx1_k = orig1_idx->ive[s_idx2]; + + while ( s_idx2 < scan_row->dim ) + { + k = col_list->ive[s_idx2]; + idx_k = orig_idx->ive[s_idx2]; + idx1_k = orig1_idx->ive[s_idx2]; + e_ik = ( idx_k < 0 ) ? (row_elt *)NULL : + &(r_piv->elt[idx_k]); + e_ip1k = ( idx1_k < 0 ) ? (row_elt *)NULL : + &(r1_piv->elt[idx1_k]); + aik = ( idx_k >= 0 ) ? e_ik->val : 0.0; + aip1k = ( idx1_k >= 0 ) ? e_ip1k->val : 0.0; + if ( scan_row->ive[s_idx2] == j ) + { /* no fill-in */ + row = &(A->row[j]); + /* idx = sprow_idx(row,k); */ + idx = scan_idx->ive[s_idx2]; + if ( idx < 0 ) + error(E_INTERN,"spBKPfactor"); + row->elt[idx].val -= s*aik + t*aip1k; + } + else + { /* fill-in -- insert entry & patch column */ + Real tmp; + int old_row, old_idx; + row_elt *old_e, *new_e; + + tmp = - s*aik - t*aip1k; + if ( tmp != 0.0 ) + { + row = &(A->row[j]); + old_row = scan_row->ive[s_idx2]; + old_idx = scan_idx->ive[s_idx2]; + + idx = row->len; + if ( row->len >= row->maxlen ) + { tracecatch(sprow_xpd(row,2*row->maxlen+1, + TYPE_SPMAT), + "spBKPfactor"); } + + row->len = idx + 1; + /* idx = sprow_idx(row,k); */ + new_e = &(row->elt[idx]); + new_e->val = tmp; + new_e->col = k; + + if ( old_row < 0 ) + error(E_INTERN,"spBKPfactor"); + /* old_idx = sprow_idx2(&(A->row[old_row]), + k,old_idx); */ + old_e = &(A->row[old_row].elt[old_idx]); + new_e->nxt_row = old_e->nxt_row; + new_e->nxt_idx = old_e->nxt_idx; + old_e->nxt_row = j; + old_e->nxt_idx = idx; + } + } + + /* update idx_k, idx1_k, s_idx2 etc */ + s_idx2++; + } + + /* store multipliers -- may involve fill-in (!) */ + /* idx = sprow_idx(r_piv,j); */ + idx = orig_idx->ive[s_idx]; + if ( idx >= 0 ) + { + r_piv->elt[idx].val = s; + } + else if ( s != 0.0 ) + { + int old_row, old_idx; + row_elt *new_e, *old_e; + + old_row = -1; old_idx = j; + + if ( i > 0 ) + { + tracecatch(chase_col(A,j,&old_row,&old_idx,i-1), + "spBKPfactor"); + } + /* sprow_set_val(r_piv,j,s); */ + idx = r_piv->len; + if ( r_piv->len >= r_piv->maxlen ) + { tracecatch(sprow_xpd(r_piv,2*r_piv->maxlen+1, + TYPE_SPMAT), + "spBKPfactor"); } + + r_piv->len = idx + 1; + /* idx = sprow_idx(r_piv,j); */ + /* if ( idx < 0 ) + error(E_INTERN,"spBKPfactor"); */ + new_e = &(r_piv->elt[idx]); + new_e->val = s; + new_e->col = j; + if ( old_row < 0 ) + { + new_e->nxt_row = A->start_row[j]; + new_e->nxt_idx = A->start_idx[j]; + A->start_row[j] = i; + A->start_idx[j] = idx; + } + else + { + /* old_idx = sprow_idx2(&(A->row[old_row]),j,old_idx);*/ + if ( old_idx < 0 ) + error(E_INTERN,"spBKPfactor"); + old_e = &(A->row[old_row].elt[old_idx]); + new_e->nxt_row = old_e->nxt_row; + new_e->nxt_idx = old_e->nxt_idx; + old_e->nxt_row = i; + old_e->nxt_idx = idx; + } + } + /* idx1 = sprow_idx(r1_piv,j); */ + idx1 = orig1_idx->ive[s_idx]; + if ( idx1 >= 0 ) + { + r1_piv->elt[idx1].val = t; + } + else if ( t != 0.0 ) + { + int old_row, old_idx; + row_elt *new_e, *old_e; + + old_row = -1; old_idx = j; + tracecatch(chase_col(A,j,&old_row,&old_idx,i), + "spBKPfactor"); + /* sprow_set_val(r1_piv,j,t); */ + idx1 = r1_piv->len; + if ( r1_piv->len >= r1_piv->maxlen ) + { tracecatch(sprow_xpd(r1_piv,2*r1_piv->maxlen+1, + TYPE_SPMAT), + "spBKPfactor"); } + + r1_piv->len = idx1 + 1; + /* idx1 = sprow_idx(r1_piv,j); */ + /* if ( idx < 0 ) + error(E_INTERN,"spBKPfactor"); */ + new_e = &(r1_piv->elt[idx1]); + new_e->val = t; + new_e->col = j; + if ( idx1 < 0 ) + error(E_INTERN,"spBKPfactor"); + new_e = &(r1_piv->elt[idx1]); + if ( old_row < 0 ) + { + new_e->nxt_row = A->start_row[j]; + new_e->nxt_idx = A->start_idx[j]; + A->start_row[j] = i+1; + A->start_idx[j] = idx1; + } + else + { + old_idx = sprow_idx2(&(A->row[old_row]),j,old_idx); + if ( old_idx < 0 ) + error(E_INTERN,"spBKPfactor"); + old_e = &(A->row[old_row].elt[old_idx]); + new_e->nxt_row = old_e->nxt_row; + new_e->nxt_idx = old_e->nxt_idx; + old_e->nxt_row = i+1; + old_e->nxt_idx = idx1; + } + } + } + } + } + + /* now sort the rows arrays */ + for ( i = 0; i < A->m; i++ ) + qsort(A->row[i].elt,A->row[i].len,sizeof(row_elt),(int(*)())col_cmp); + A->flag_col = A->flag_diag = FALSE; + +#ifdef THREADSAFE + IV_FREE(scan_row); IV_FREE(scan_idx); IV_FREE(col_list); + IV_FREE(tmp_iv); IV_FREE(deg_list); IV_FREE(orig_idx); + IV_FREE(orig1_idx); PX_FREE(order); +#endif + return A; +} + +/* spBKPsolve -- solves A.x = b where A has been factored a la BKPfactor() + -- returns x, which is created if NULL */ +#ifndef ANSI_C +VEC *spBKPsolve(A,pivot,block,b,x) +SPMAT *A; +PERM *pivot, *block; +VEC *b, *x; +#else +VEC *spBKPsolve(SPMAT *A, PERM *pivot, PERM *block, + const VEC *b, VEC *x) +#endif +{ + STATIC VEC *tmp=VNULL; /* dummy storage needed */ + int i /* , j */, n, onebyone; + int row_num, idx; + Real a11, a12, a22, b1, b2, det, sum, *tmp_ve, tmp_diag; + SPROW *r; + row_elt *e; + + if ( ! A || ! pivot || ! block || ! b ) + error(E_NULL,"spBKPsolve"); + if ( A->m != A->n ) + error(E_SQUARE,"spBKPsolve"); + n = A->n; + if ( b->dim != n || pivot->size != n || block->size != n ) + error(E_SIZES,"spBKPsolve"); + x = v_resize(x,n); + tmp = v_resize(tmp,n); + MEM_STAT_REG(tmp,TYPE_VEC); + + tmp_ve = tmp->ve; + + if ( ! A->flag_col ) + sp_col_access(A); + + px_vec(pivot,b,tmp); + /* printf("# BKPsolve: effect of pivot: tmp =\n"); v_output(tmp); */ + + /* solve for lower triangular part */ + for ( i = 0; i < n; i++ ) + { + sum = tmp_ve[i]; + if ( block->pe[i] < i ) + { + /* for ( j = 0; j < i-1; j++ ) + sum -= A_me[j][i]*tmp_ve[j]; */ + row_num = -1; idx = i; + e = bump_col(A,i,&row_num,&idx); + while ( row_num >= 0 && row_num < i-1 ) + { + sum -= e->val*tmp_ve[row_num]; + e = bump_col(A,i,&row_num,&idx); + } + } + else + { + /* for ( j = 0; j < i; j++ ) + sum -= A_me[j][i]*tmp_ve[j]; */ + row_num = -1; idx = i; + e = bump_col(A,i,&row_num,&idx); + while ( row_num >= 0 && row_num < i ) + { + sum -= e->val*tmp_ve[row_num]; + e = bump_col(A,i,&row_num,&idx); + } + } + tmp_ve[i] = sum; + } + + /* printf("# BKPsolve: solving L part: tmp =\n"); v_output(tmp); */ + /* solve for diagonal part */ + for ( i = 0; i < n; i = onebyone ? i+1 : i+2 ) + { + onebyone = ( block->pe[i] == i ); + if ( onebyone ) + { + /* tmp_ve[i] /= A_me[i][i]; */ + tmp_diag = sp_get_val(A,i,i); + if ( tmp_diag == 0.0 ) + error(E_SING,"spBKPsolve"); + tmp_ve[i] /= tmp_diag; + } + else + { + a11 = sp_get_val(A,i,i); + a22 = sp_get_val(A,i+1,i+1); + a12 = sp_get_val(A,i,i+1); + b1 = tmp_ve[i]; + b2 = tmp_ve[i+1]; + det = a11*a22-a12*a12; /* < 0 : see BKPfactor() */ + if ( det == 0.0 ) + error(E_SING,"BKPsolve"); + det = 1/det; + tmp_ve[i] = det*(a22*b1-a12*b2); + tmp_ve[i+1] = det*(a11*b2-a12*b1); + } + } + + /* printf("# BKPsolve: solving D part: tmp =\n"); v_output(tmp); */ + /* solve for transpose of lower triangular part */ + for ( i = n-2; i >= 0; i-- ) + { + sum = tmp_ve[i]; + if ( block->pe[i] > i ) + { + /* onebyone is false */ + /* for ( j = i+2; j < n; j++ ) + sum -= A_me[i][j]*tmp_ve[j]; */ + if ( i+2 >= n ) + continue; + r = &(A->row[i]); + idx = sprow_idx(r,i+2); + idx = fixindex(idx); + e = &(r->elt[idx]); + for ( ; idx < r->len; idx++, e++ ) + sum -= e->val*tmp_ve[e->col]; + } + else /* onebyone */ + { + /* for ( j = i+1; j < n; j++ ) + sum -= A_me[i][j]*tmp_ve[j]; */ + r = &(A->row[i]); + idx = sprow_idx(r,i+1); + idx = fixindex(idx); + e = &(r->elt[idx]); + for ( ; idx < r->len; idx++, e++ ) + sum -= e->val*tmp_ve[e->col]; + } + tmp_ve[i] = sum; + } + + /* printf("# BKPsolve: solving L^T part: tmp =\n");v_output(tmp); */ + /* and do final permutation */ + x = pxinv_vec(pivot,tmp,x); + +#ifdef THREADSAFE + V_FREE(tmp); +#endif + + return x; +} + + + diff --git a/spchfctr.c b/spchfctr.c new file mode 100644 index 0000000..1a6383b --- /dev/null +++ b/spchfctr.c @@ -0,0 +1,659 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Sparse Cholesky factorisation code + To be used with sparse.h, sparse.c etc + +*/ + +static char rcsid[] = "$Id: spchfctr.c,v 1.5 1996/08/20 19:45:33 stewart Exp $"; + +#include +#include +#include "sparse2.h" + + +#ifndef MALLOCDECL +#ifndef ANSI_C +extern char *calloc(), *realloc(); +#endif +#endif + + + +/* sprow_ip -- finds the (partial) inner product of a pair of sparse rows + -- uses a "merging" approach & assumes column ordered rows + -- row indices for inner product are all < lim */ +#ifndef ANSI_C +static double sprow_ip(row1, row2, lim) +SPROW *row1, *row2; +int lim; +#else +static double sprow_ip(const SPROW *row1, const SPROW *row2, int lim) +#endif +{ + int idx1, idx2, len1, len2, tmp; + register row_elt *elts1, *elts2; + register Real sum; + + elts1 = row1->elt; elts2 = row2->elt; + len1 = row1->len; len2 = row2->len; + + sum = 0.0; + + if ( len1 <= 0 || len2 <= 0 ) + return 0.0; + if ( elts1->col >= lim || elts2->col >= lim ) + return 0.0; + + /* use sprow_idx() to speed up inner product where one row is + much longer than the other */ + idx1 = idx2 = 0; + if ( len1 > 2*len2 ) + { + idx1 = sprow_idx(row1,elts2->col); + idx1 = (idx1 < 0) ? -(idx1+2) : idx1; + if ( idx1 < 0 ) + error(E_UNKNOWN,"sprow_ip"); + len1 -= idx1; + } + else if ( len2 > 2*len1 ) + { + idx2 = sprow_idx(row2,elts1->col); + idx2 = (idx2 < 0) ? -(idx2+2) : idx2; + if ( idx2 < 0 ) + error(E_UNKNOWN,"sprow_ip"); + len2 -= idx2; + } + if ( len1 <= 0 || len2 <= 0 ) + return 0.0; + + elts1 = &(elts1[idx1]); elts2 = &(elts2[idx2]); + + + for ( ; ; ) /* forever do... */ + { + if ( (tmp=elts1->col-elts2->col) < 0 ) + { + len1--; elts1++; + if ( ! len1 || elts1->col >= lim ) + break; + } + else if ( tmp > 0 ) + { + len2--; elts2++; + if ( ! len2 || elts2->col >= lim ) + break; + } + else + { + sum += elts1->val * elts2->val; + len1--; elts1++; + len2--; elts2++; + if ( ! len1 || ! len2 || + elts1->col >= lim || elts2->col >= lim ) + break; + } + } + + return sum; +} + +/* sprow_sqr -- returns same as sprow_ip(row, row, lim) */ +#ifndef ANSI_C +static double sprow_sqr(row, lim) +SPROW *row; +int lim; +#else +static double sprow_sqr(const SPROW *row, int lim) +#endif +{ + register row_elt *elts; + int idx, len; + register Real sum, tmp; + + sum = 0.0; + elts = row->elt; len = row->len; + for ( idx = 0; idx < len; idx++, elts++ ) + { + if ( elts->col >= lim ) + break; + tmp = elts->val; + sum += tmp*tmp; + } + + return sum; +} + +static int *scan_row = (int *)NULL, *scan_idx = (int *)NULL, + *col_list = (int *)NULL; +static int scan_len = 0; + +/* set_scan -- expand scan_row and scan_idx arrays + -- return new length */ +#ifndef ANSI_C +int set_scan(new_len) +int new_len; +#else +int set_scan(int new_len) +#endif +{ + if ( new_len <= scan_len ) + return scan_len; + if ( new_len <= scan_len+5 ) + new_len += 5; + + /* update scan_len */ + scan_len = new_len; + + if ( ! scan_row || ! scan_idx || ! col_list ) + { + scan_row = (int *)calloc(new_len,sizeof(int)); + scan_idx = (int *)calloc(new_len,sizeof(int)); + col_list = (int *)calloc(new_len,sizeof(int)); + } + else + { + scan_row = (int *)realloc((char *)scan_row,new_len*sizeof(int)); + scan_idx = (int *)realloc((char *)scan_idx,new_len*sizeof(int)); + col_list = (int *)realloc((char *)col_list,new_len*sizeof(int)); + } + + if ( ! scan_row || ! scan_idx || ! col_list ) + error(E_MEM,"set_scan"); + return new_len; +} + +/* spCHfactor -- sparse Cholesky factorisation + -- only the lower triangular part of A (incl. diagonal) is used */ +#ifndef ANSI_C +SPMAT *spCHfactor(A) +SPMAT *A; +#else +SPMAT *spCHfactor(SPMAT *A) +#endif +{ + register int i; + int idx, k, m, minim, n, num_scan, diag_idx, tmp1; + Real pivot, tmp2; + SPROW *r_piv, *r_op; + row_elt *elt_piv, *elt_op, *old_elt; + + if ( A == SMNULL ) + error(E_NULL,"spCHfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"spCHfactor"); + + /* set up access paths if not already done so */ + sp_col_access(A); + sp_diag_access(A); + + /* printf("spCHfactor() -- checkpoint 1\n"); */ + m = A->m; n = A->n; + for ( k = 0; k < m; k++ ) + { + r_piv = &(A->row[k]); + if ( r_piv->len > scan_len ) + set_scan(r_piv->len); + elt_piv = r_piv->elt; + diag_idx = sprow_idx2(r_piv,k,r_piv->diag); + if ( diag_idx < 0 ) + error(E_POSDEF,"spCHfactor"); + old_elt = &(elt_piv[diag_idx]); + for ( i = 0; i < r_piv->len; i++ ) + { + if ( elt_piv[i].col > k ) + break; + col_list[i] = elt_piv[i].col; + scan_row[i] = elt_piv[i].nxt_row; + scan_idx[i] = elt_piv[i].nxt_idx; + } + /* printf("spCHfactor() -- checkpoint 2\n"); */ + num_scan = i; /* number of actual entries in scan_row etc. */ + /* printf("num_scan = %d\n",num_scan); */ + + /* set diagonal entry of Cholesky factor */ + tmp2 = elt_piv[diag_idx].val - sprow_sqr(r_piv,k); + if ( tmp2 <= 0.0 ) + error(E_POSDEF,"spCHfactor"); + elt_piv[diag_idx].val = pivot = sqrt(tmp2); + + /* now set the k-th column of the Cholesky factors */ + /* printf("k = %d\n",k); */ + for ( ; ; ) /* forever do... */ + { + /* printf("spCHfactor() -- checkpoint 3\n"); */ + /* find next row where something (non-trivial) happens + i.e. find min(scan_row) */ + /* printf("scan_row: "); */ + minim = n; + for ( i = 0; i < num_scan; i++ ) + { + tmp1 = scan_row[i]; + /* printf("%d ",tmp1); */ + minim = ( tmp1 >= 0 && tmp1 < minim ) ? tmp1 : minim; + } + /* printf("minim = %d\n",minim); */ + /* printf("col_list: "); */ + /* for ( i = 0; i < num_scan; i++ ) */ + /* printf("%d ",col_list[i]); */ + /* printf("\n"); */ + + if ( minim >= n ) + break; /* nothing more to do for this column */ + r_op = &(A->row[minim]); + elt_op = r_op->elt; + + /* set next entry in column k of Cholesky factors */ + idx = sprow_idx2(r_op,k,scan_idx[num_scan-1]); + if ( idx < 0 ) + { /* fill-in */ + sp_set_val(A,minim,k, + -sprow_ip(r_piv,r_op,k)/pivot); + /* in case a realloc() has occurred... */ + elt_op = r_op->elt; + /* now set up column access path again */ + idx = sprow_idx2(r_op,k,-(idx+2)); + tmp1 = old_elt->nxt_row; + old_elt->nxt_row = minim; + r_op->elt[idx].nxt_row = tmp1; + tmp1 = old_elt->nxt_idx; + old_elt->nxt_idx = idx; + r_op->elt[idx].nxt_idx = tmp1; + } + else + elt_op[idx].val = (elt_op[idx].val - + sprow_ip(r_piv,r_op,k))/pivot; + + /* printf("spCHfactor() -- checkpoint 4\n"); */ + + /* remember current element in column k for column chain */ + idx = sprow_idx2(r_op,k,idx); + old_elt = &(r_op->elt[idx]); + + /* update scan_row */ + /* printf("spCHfactor() -- checkpoint 5\n"); */ + /* printf("minim = %d\n",minim); */ + for ( i = 0; i < num_scan; i++ ) + { + if ( scan_row[i] != minim ) + continue; + idx = sprow_idx2(r_op,col_list[i],scan_idx[i]); + if ( idx < 0 ) + { scan_row[i] = -1; continue; } + scan_row[i] = elt_op[idx].nxt_row; + scan_idx[i] = elt_op[idx].nxt_idx; + /* printf("scan_row[%d] = %d\n",i,scan_row[i]); */ + /* printf("scan_idx[%d] = %d\n",i,scan_idx[i]); */ + } + + } + /* printf("spCHfactor() -- checkpoint 6\n"); */ + /* sp_dump(stdout,A); */ + /* printf("\n\n\n"); */ + } + + return A; +} + +/* spCHsolve -- solve L.L^T.out=b where L is a sparse matrix, + -- out, b dense vectors + -- returns out; operation may be in-situ */ +#ifndef ANSI_C +VEC *spCHsolve(L,b,out) +SPMAT *L; +VEC *b, *out; +#else +VEC *spCHsolve(SPMAT *L, const VEC *b, VEC *out) +#endif +{ + int i, j_idx, n, scan_idx, scan_row; + SPROW *row; + row_elt *elt; + Real diag_val, sum, *out_ve; + + if ( L == SMNULL || b == VNULL ) + error(E_NULL,"spCHsolve"); + if ( L->m != L->n ) + error(E_SQUARE,"spCHsolve"); + if ( b->dim != L->m ) + error(E_SIZES,"spCHsolve"); + + if ( ! L->flag_col ) + sp_col_access(L); + if ( ! L->flag_diag ) + sp_diag_access(L); + + out = v_copy(b,out); + out_ve = out->ve; + + /* forward substitution: solve L.x=b for x */ + n = L->n; + for ( i = 0; i < n; i++ ) + { + sum = out_ve[i]; + row = &(L->row[i]); + elt = row->elt; + for ( j_idx = 0; j_idx < row->len; j_idx++, elt++ ) + { + if ( elt->col >= i ) + break; + sum -= elt->val*out_ve[elt->col]; + } + if ( row->diag >= 0 ) + out_ve[i] = sum/(row->elt[row->diag].val); + else + error(E_SING,"spCHsolve"); + } + + /* backward substitution: solve L^T.out = x for out */ + for ( i = n-1; i >= 0; i-- ) + { + sum = out_ve[i]; + row = &(L->row[i]); + /* Note that row->diag >= 0 by above loop */ + elt = &(row->elt[row->diag]); + diag_val = elt->val; + + /* scan down column */ + scan_idx = elt->nxt_idx; + scan_row = elt->nxt_row; + while ( scan_row >= 0 /* && scan_idx >= 0 */ ) + { + row = &(L->row[scan_row]); + elt = &(row->elt[scan_idx]); + sum -= elt->val*out_ve[scan_row]; + scan_idx = elt->nxt_idx; + scan_row = elt->nxt_row; + } + out_ve[i] = sum/diag_val; + } + + return out; +} + +/* spICHfactor -- sparse Incomplete Cholesky factorisation + -- does a Cholesky factorisation assuming NO FILL-IN + -- as for spCHfactor(), only the lower triangular part of A is used */ +#ifndef ANSI_C +SPMAT *spICHfactor(A) +SPMAT *A; +#else +SPMAT *spICHfactor(SPMAT *A) +#endif +{ + int k, m, n, nxt_row, nxt_idx, diag_idx; + Real pivot, tmp2; + SPROW *r_piv, *r_op; + row_elt *elt_piv, *elt_op; + + if ( A == SMNULL ) + error(E_NULL,"spICHfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"spICHfactor"); + + /* set up access paths if not already done so */ + if ( ! A->flag_col ) + sp_col_access(A); + if ( ! A->flag_diag ) + sp_diag_access(A); + + m = A->m; n = A->n; + for ( k = 0; k < m; k++ ) + { + r_piv = &(A->row[k]); + + diag_idx = r_piv->diag; + if ( diag_idx < 0 ) + error(E_POSDEF,"spICHfactor"); + + elt_piv = r_piv->elt; + + /* set diagonal entry of Cholesky factor */ + tmp2 = elt_piv[diag_idx].val - sprow_sqr(r_piv,k); + if ( tmp2 <= 0.0 ) + error(E_POSDEF,"spICHfactor"); + elt_piv[diag_idx].val = pivot = sqrt(tmp2); + + /* find next row where something (non-trivial) happens */ + nxt_row = elt_piv[diag_idx].nxt_row; + nxt_idx = elt_piv[diag_idx].nxt_idx; + + /* now set the k-th column of the Cholesky factors */ + while ( nxt_row >= 0 && nxt_idx >= 0 ) + { + /* nxt_row and nxt_idx give next next row (& index) + of the entry to be modified */ + r_op = &(A->row[nxt_row]); + elt_op = r_op->elt; + elt_op[nxt_idx].val = (elt_op[nxt_idx].val - + sprow_ip(r_piv,r_op,k))/pivot; + + nxt_row = elt_op[nxt_idx].nxt_row; + nxt_idx = elt_op[nxt_idx].nxt_idx; + } + } + + return A; +} + + +/* spCHsymb -- symbolic sparse Cholesky factorisation + -- does NOT do any floating point arithmetic; just sets up the structure + -- only the lower triangular part of A (incl. diagonal) is used */ +#ifndef ANSI_C +SPMAT *spCHsymb(A) +SPMAT *A; +#else +SPMAT *spCHsymb(SPMAT *A) +#endif +{ + register int i; + int idx, k, m, minim, n, num_scan, diag_idx, tmp1; + SPROW *r_piv, *r_op; + row_elt *elt_piv, *elt_op, *old_elt; + + if ( A == SMNULL ) + error(E_NULL,"spCHsymb"); + if ( A->m != A->n ) + error(E_SQUARE,"spCHsymb"); + + /* set up access paths if not already done so */ + if ( ! A->flag_col ) + sp_col_access(A); + if ( ! A->flag_diag ) + sp_diag_access(A); + + /* printf("spCHsymb() -- checkpoint 1\n"); */ + m = A->m; n = A->n; + for ( k = 0; k < m; k++ ) + { + r_piv = &(A->row[k]); + if ( r_piv->len > scan_len ) + set_scan(r_piv->len); + elt_piv = r_piv->elt; + diag_idx = sprow_idx2(r_piv,k,r_piv->diag); + if ( diag_idx < 0 ) + error(E_POSDEF,"spCHsymb"); + old_elt = &(elt_piv[diag_idx]); + for ( i = 0; i < r_piv->len; i++ ) + { + if ( elt_piv[i].col > k ) + break; + col_list[i] = elt_piv[i].col; + scan_row[i] = elt_piv[i].nxt_row; + scan_idx[i] = elt_piv[i].nxt_idx; + } + /* printf("spCHsymb() -- checkpoint 2\n"); */ + num_scan = i; /* number of actual entries in scan_row etc. */ + /* printf("num_scan = %d\n",num_scan); */ + + /* now set the k-th column of the Cholesky factors */ + /* printf("k = %d\n",k); */ + for ( ; ; ) /* forever do... */ + { + /* printf("spCHsymb() -- checkpoint 3\n"); */ + /* find next row where something (non-trivial) happens + i.e. find min(scan_row) */ + minim = n; + for ( i = 0; i < num_scan; i++ ) + { + tmp1 = scan_row[i]; + /* printf("%d ",tmp1); */ + minim = ( tmp1 >= 0 && tmp1 < minim ) ? tmp1 : minim; + } + + if ( minim >= n ) + break; /* nothing more to do for this column */ + r_op = &(A->row[minim]); + elt_op = r_op->elt; + + /* set next entry in column k of Cholesky factors */ + idx = sprow_idx2(r_op,k,scan_idx[num_scan-1]); + if ( idx < 0 ) + { /* fill-in */ + sp_set_val(A,minim,k,0.0); + /* in case a realloc() has occurred... */ + elt_op = r_op->elt; + /* now set up column access path again */ + idx = sprow_idx2(r_op,k,-(idx+2)); + tmp1 = old_elt->nxt_row; + old_elt->nxt_row = minim; + r_op->elt[idx].nxt_row = tmp1; + tmp1 = old_elt->nxt_idx; + old_elt->nxt_idx = idx; + r_op->elt[idx].nxt_idx = tmp1; + } + + /* printf("spCHsymb() -- checkpoint 4\n"); */ + + /* remember current element in column k for column chain */ + idx = sprow_idx2(r_op,k,idx); + old_elt = &(r_op->elt[idx]); + + /* update scan_row */ + /* printf("spCHsymb() -- checkpoint 5\n"); */ + /* printf("minim = %d\n",minim); */ + for ( i = 0; i < num_scan; i++ ) + { + if ( scan_row[i] != minim ) + continue; + idx = sprow_idx2(r_op,col_list[i],scan_idx[i]); + if ( idx < 0 ) + { scan_row[i] = -1; continue; } + scan_row[i] = elt_op[idx].nxt_row; + scan_idx[i] = elt_op[idx].nxt_idx; + /* printf("scan_row[%d] = %d\n",i,scan_row[i]); */ + /* printf("scan_idx[%d] = %d\n",i,scan_idx[i]); */ + } + + } + /* printf("spCHsymb() -- checkpoint 6\n"); */ + } + + return A; +} + +/* comp_AAT -- compute A.A^T where A is a given sparse matrix */ +#ifndef ANSI_C +SPMAT *comp_AAT(A) +SPMAT *A; +#else +SPMAT *comp_AAT(SPMAT *A) +#endif +{ + SPMAT *AAT; + SPROW *r, *r2; + row_elt *elts, *elts2; + int i, idx, idx2, j, m, minim, n, num_scan, tmp1; + Real ip; + + if ( ! A ) + error(E_NULL,"comp_AAT"); + m = A->m; n = A->n; + + /* set up column access paths */ + if ( ! A->flag_col ) + sp_col_access(A); + + AAT = sp_get(m,m,10); + + for ( i = 0; i < m; i++ ) + { + /* initialisation */ + r = &(A->row[i]); + elts = r->elt; + + /* set up scan lists for this row */ + if ( r->len > scan_len ) + set_scan(r->len); + for ( j = 0; j < r->len; j++ ) + { + col_list[j] = elts[j].col; + scan_row[j] = elts[j].nxt_row; + scan_idx[j] = elts[j].nxt_idx; + } + num_scan = r->len; + + /* scan down the rows for next non-zero not + associated with a diagonal entry */ + for ( ; ; ) + { + minim = m; + for ( idx = 0; idx < num_scan; idx++ ) + { + tmp1 = scan_row[idx]; + minim = ( tmp1 >= 0 && tmp1 < minim ) ? tmp1 : minim; + } + if ( minim >= m ) + break; + r2 = &(A->row[minim]); + if ( minim > i ) + { + ip = sprow_ip(r,r2,n); + sp_set_val(AAT,minim,i,ip); + sp_set_val(AAT,i,minim,ip); + } + /* update scan entries */ + elts2 = r2->elt; + for ( idx = 0; idx < num_scan; idx++ ) + { + if ( scan_row[idx] != minim || scan_idx[idx] < 0 ) + continue; + idx2 = scan_idx[idx]; + scan_row[idx] = elts2[idx2].nxt_row; + scan_idx[idx] = elts2[idx2].nxt_idx; + } + } + + /* set the diagonal entry */ + sp_set_val(AAT,i,i,sprow_sqr(r,n)); + } + + return AAT; +} + diff --git a/splufctr.c b/splufctr.c new file mode 100644 index 0000000..9f79d0c --- /dev/null +++ b/splufctr.c @@ -0,0 +1,433 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Sparse LU factorisation + See also: sparse.[ch] etc for details about sparse matrices +*/ + +#include +#include +#include "sparse2.h" + + + +/* Macro for speedup */ +/* #define sprow_idx2(r,c,hint) \ + ( ( (hint) >= 0 && (r)->elt[hint].col == (c)) ? hint : sprow_idx((r),(c)) ) */ + + +/* spLUfactor -- sparse LU factorisation with pivoting + -- uses partial pivoting and Markowitz criterion + |a[p][k]| >= alpha * max_i |a[i][k]| + -- creates fill-in as needed + -- in situ factorisation */ +#ifndef ANSI_C +SPMAT *spLUfactor(A,px,alpha) +SPMAT *A; +PERM *px; +double alpha; +#else +SPMAT *spLUfactor(SPMAT *A, PERM *px, double alpha) +#endif +{ + int i, best_i, k, idx, len, best_len, m, n; + SPROW *r, *r_piv, tmp_row; + STATIC SPROW *merge = (SPROW *)NULL; + Real max_val, tmp; + STATIC VEC *col_vals=VNULL; + + if ( ! A || ! px ) + error(E_NULL,"spLUfctr"); + if ( alpha <= 0.0 || alpha > 1.0 ) + error(E_RANGE,"alpha in spLUfctr"); + if ( px->size <= A->m ) + px = px_resize(px,A->m); + px_ident(px); + col_vals = v_resize(col_vals,A->m); + MEM_STAT_REG(col_vals,TYPE_VEC); + + m = A->m; n = A->n; + if ( ! A->flag_col ) + sp_col_access(A); + if ( ! A->flag_diag ) + sp_diag_access(A); + A->flag_col = A->flag_diag = FALSE; + if ( ! merge ) { + merge = sprow_get(20); + MEM_STAT_REG(merge,TYPE_SPROW); + } + + for ( k = 0; k < n; k++ ) + { + /* find pivot row/element for partial pivoting */ + + /* get first row with a non-zero entry in the k-th column */ + max_val = 0.0; + for ( i = k; i < m; i++ ) + { + r = &(A->row[i]); + idx = sprow_idx(r,k); + if ( idx < 0 ) + tmp = 0.0; + else + tmp = r->elt[idx].val; + if ( fabs(tmp) > max_val ) + max_val = fabs(tmp); + col_vals->ve[i] = tmp; + } + + if ( max_val == 0.0 ) + continue; + + best_len = n+1; /* only if no possibilities */ + best_i = -1; + for ( i = k; i < m; i++ ) + { + tmp = fabs(col_vals->ve[i]); + if ( tmp == 0.0 ) + continue; + if ( tmp >= alpha*max_val ) + { + r = &(A->row[i]); + idx = sprow_idx(r,k); + len = (r->len) - idx; + if ( len < best_len ) + { + best_len = len; + best_i = i; + } + } + } + + /* swap row #best_i with row #k */ + MEM_COPY(&(A->row[best_i]),&tmp_row,sizeof(SPROW)); + MEM_COPY(&(A->row[k]),&(A->row[best_i]),sizeof(SPROW)); + MEM_COPY(&tmp_row,&(A->row[k]),sizeof(SPROW)); + /* swap col_vals entries */ + tmp = col_vals->ve[best_i]; + col_vals->ve[best_i] = col_vals->ve[k]; + col_vals->ve[k] = tmp; + px_transp(px,k,best_i); + + r_piv = &(A->row[k]); + for ( i = k+1; i < n; i++ ) + { + /* compute and set multiplier */ + tmp = col_vals->ve[i]/col_vals->ve[k]; + if ( tmp != 0.0 ) + sp_set_val(A,i,k,tmp); + else + continue; + + /* perform row operations */ + merge->len = 0; + r = &(A->row[i]); + sprow_mltadd(r,r_piv,-tmp,k+1,merge,TYPE_SPROW); + idx = sprow_idx(r,k+1); + if ( idx < 0 ) + idx = -(idx+2); + /* see if r needs expanding */ + if ( r->maxlen < idx + merge->len ) + sprow_xpd(r,idx+merge->len,TYPE_SPMAT); + r->len = idx+merge->len; + MEM_COPY((char *)(merge->elt),(char *)&(r->elt[idx]), + merge->len*sizeof(row_elt)); + } + } +#ifdef THREADSAFE + sprow_free(merge); V_FREE(col_vals); +#endif + + return A; +} + +/* spLUsolve -- solve A.x = b using factored matrix A from spLUfactor() + -- returns x + -- may not be in-situ */ +#ifndef ANSI_C +VEC *spLUsolve(A,pivot,b,x) +SPMAT *A; +PERM *pivot; +VEC *b, *x; +#else +VEC *spLUsolve(const SPMAT *A, PERM *pivot, const VEC *b, VEC *x) +#endif +{ + int i, idx, len, lim; + Real sum, *x_ve; + SPROW *r; + row_elt *elt; + + if ( ! A || ! b ) + error(E_NULL,"spLUsolve"); + if ( (pivot != PNULL && A->m != pivot->size) || A->m != b->dim ) + error(E_SIZES,"spLUsolve"); + if ( ! x || x->dim != A->n ) + x = v_resize(x,A->n); + + if ( pivot != PNULL ) + x = px_vec(pivot,b,x); + else + x = v_copy(b,x); + + x_ve = x->ve; + lim = min(A->m,A->n); + for ( i = 0; i < lim; i++ ) + { + sum = x_ve[i]; + r = &(A->row[i]); + len = r->len; + elt = r->elt; + for ( idx = 0; idx < len && elt->col < i; idx++, elt++ ) + sum -= elt->val*x_ve[elt->col]; + x_ve[i] = sum; + } + + for ( i = lim-1; i >= 0; i-- ) + { + sum = x_ve[i]; + r = &(A->row[i]); + len = r->len; + elt = &(r->elt[len-1]); + for ( idx = len-1; idx >= 0 && elt->col > i; idx--, elt-- ) + sum -= elt->val*x_ve[elt->col]; + if ( idx < 0 || elt->col != i || elt->val == 0.0 ) + error(E_SING,"spLUsolve"); + x_ve[i] = sum/elt->val; + } + + return x; +} + +/* spLUTsolve -- solve A.x = b using factored matrix A from spLUfactor() + -- returns x + -- may not be in-situ */ +#ifndef ANSI_C +VEC *spLUTsolve(A,pivot,b,x) +SPMAT *A; +PERM *pivot; +VEC *b, *x; +#else +VEC *spLUTsolve(SPMAT *A, PERM *pivot, const VEC *b, VEC *x) +#endif +{ + int i, idx, lim, rownum; + Real sum, *tmp_ve; + /* SPROW *r; */ + row_elt *elt; + STATIC VEC *tmp=VNULL; + + if ( ! A || ! b ) + error(E_NULL,"spLUTsolve"); + if ( (pivot != PNULL && A->m != pivot->size) || A->m != b->dim ) + error(E_SIZES,"spLUTsolve"); + tmp = v_copy(b,tmp); + MEM_STAT_REG(tmp,TYPE_VEC); + + if ( ! A->flag_col ) + sp_col_access(A); + if ( ! A->flag_diag ) + sp_diag_access(A); + + lim = min(A->m,A->n); + tmp_ve = tmp->ve; + /* solve U^T.tmp = b */ + for ( i = 0; i < lim; i++ ) + { + sum = tmp_ve[i]; + rownum = A->start_row[i]; + idx = A->start_idx[i]; + if ( rownum < 0 || idx < 0 ) + error(E_SING,"spLUTsolve"); + while ( rownum < i && rownum >= 0 && idx >= 0 ) + { + elt = &(A->row[rownum].elt[idx]); + sum -= elt->val*tmp_ve[rownum]; + rownum = elt->nxt_row; + idx = elt->nxt_idx; + } + if ( rownum != i ) + error(E_SING,"spLUTsolve"); + elt = &(A->row[rownum].elt[idx]); + if ( elt->val == 0.0 ) + error(E_SING,"spLUTsolve"); + tmp_ve[i] = sum/elt->val; + } + + /* now solve L^T.tmp = (old) tmp */ + for ( i = lim-1; i >= 0; i-- ) + { + sum = tmp_ve[i]; + rownum = i; + idx = A->row[rownum].diag; + if ( idx < 0 ) + error(E_NULL,"spLUTsolve"); + elt = &(A->row[rownum].elt[idx]); + rownum = elt->nxt_row; + idx = elt->nxt_idx; + while ( rownum < lim && rownum >= 0 && idx >= 0 ) + { + elt = &(A->row[rownum].elt[idx]); + sum -= elt->val*tmp_ve[rownum]; + rownum = elt->nxt_row; + idx = elt->nxt_idx; + } + tmp_ve[i] = sum; + } + + if ( pivot != PNULL ) + x = pxinv_vec(pivot,tmp,x); + else + x = v_copy(tmp,x); + +#ifdef THREADSAFE + V_FREE(tmp); +#endif + + return x; +} + +/* spILUfactor -- sparse modified incomplete LU factorisation with + no pivoting + -- all pivot entries are ensured to be >= alpha in magnitude + -- setting alpha = 0 gives incomplete LU factorisation + -- no fill-in is generated + -- in situ factorisation */ +#ifndef ANSI_C +SPMAT *spILUfactor(A,alpha) +SPMAT *A; +double alpha; +#else +SPMAT *spILUfactor(SPMAT *A, double alpha) +#endif +{ + int i, k, idx, idx_piv, m, n, old_idx, old_idx_piv; + SPROW *r, *r_piv; + Real piv_val, tmp; + + /* printf("spILUfactor: entered\n"); */ + if ( ! A ) + error(E_NULL,"spILUfactor"); + if ( alpha < 0.0 ) + error(E_RANGE,"[alpha] in spILUfactor"); + + m = A->m; n = A->n; + sp_diag_access(A); + sp_col_access(A); + + for ( k = 0; k < n; k++ ) + { + /* printf("spILUfactor(l.%d): checkpoint A: k = %d\n",__LINE__,k); */ + /* printf("spILUfactor(l.%d): A =\n", __LINE__); */ + /* sp_output(A); */ + r_piv = &(A->row[k]); + idx_piv = r_piv->diag; + if ( idx_piv < 0 ) + { + sprow_set_val(r_piv,k,alpha); + idx_piv = sprow_idx(r_piv,k); + } + /* printf("spILUfactor: checkpoint B\n"); */ + if ( idx_piv < 0 ) + error(E_BOUNDS,"spILUfactor"); + old_idx_piv = idx_piv; + piv_val = r_piv->elt[idx_piv].val; + /* printf("spILUfactor: checkpoint C\n"); */ + if ( fabs(piv_val) < alpha ) + piv_val = ( piv_val < 0.0 ) ? -alpha : alpha; + if ( piv_val == 0.0 ) /* alpha == 0.0 too! */ + error(E_SING,"spILUfactor"); + + /* go to next row with a non-zero in this column */ + i = r_piv->elt[idx_piv].nxt_row; + old_idx = idx = r_piv->elt[idx_piv].nxt_idx; + while ( i >= k ) + { + /* printf("spILUfactor: checkpoint D: i = %d\n",i); */ + /* perform row operations */ + r = &(A->row[i]); + /* idx = sprow_idx(r,k); */ + /* printf("spLUfactor(l.%d) i = %d, idx = %d\n", + __LINE__, i, idx); */ + if ( idx < 0 ) + { + idx = r->elt[old_idx].nxt_idx; + i = r->elt[old_idx].nxt_row; + continue; + } + /* printf("spILUfactor: checkpoint E\n"); */ + /* compute and set multiplier */ + r->elt[idx].val = tmp = r->elt[idx].val/piv_val; + /* printf("spILUfactor: piv_val = %g, multiplier = %g\n", + piv_val, tmp); */ + /* printf("spLUfactor(l.%d) multiplier = %g\n", __LINE__, tmp); */ + if ( tmp == 0.0 ) + { + idx = r->elt[old_idx].nxt_idx; + i = r->elt[old_idx].nxt_row; + continue; + } + /* idx = sprow_idx(r,k+1); */ + /* if ( idx < 0 ) + idx = -(idx+2); */ + idx_piv++; idx++; /* now look beyond the multiplier entry */ + /* printf("spILUfactor: checkpoint F: idx = %d, idx_piv = %d\n", + idx, idx_piv); */ + while ( idx_piv < r_piv->len && idx < r->len ) + { + /* printf("spILUfactor: checkpoint G: idx = %d, idx_piv = %d\n", + idx, idx_piv); */ + if ( r_piv->elt[idx_piv].col < r->elt[idx].col ) + idx_piv++; + else if ( r_piv->elt[idx_piv].col > r->elt[idx].col ) + idx++; + else /* column numbers match */ + { + /* printf("spILUfactor(l.%d) subtract %g times the ", + __LINE__, tmp); */ + /* printf("(%d,%d) entry to the (%d,%d) entry\n", + k, r_piv->elt[idx_piv].col, + i, r->elt[idx].col); */ + r->elt[idx].val -= tmp*r_piv->elt[idx_piv].val; + idx++; idx_piv++; + } + } + + /* bump to next row with a non-zero in column k */ + /* printf("spILUfactor(l.%d) column = %d, row[%d] =\n", + __LINE__, r->elt[old_idx].col, i); */ + /* sprow_foutput(stdout,r); */ + i = r->elt[old_idx].nxt_row; + old_idx = idx = r->elt[old_idx].nxt_idx; + /* printf("spILUfactor(l.%d) i = %d, idx = %d\n", __LINE__, i, idx); */ + /* and restore idx_piv to index of pivot entry */ + idx_piv = old_idx_piv; + } + } + /* printf("spILUfactor: exiting\n"); */ + return A; +} diff --git a/sprow.c b/sprow.c new file mode 100644 index 0000000..39624f6 --- /dev/null +++ b/sprow.c @@ -0,0 +1,774 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + Sparse rows package + See also: sparse.h, matrix.h + */ + +#include +#include +#include +#include "sparse.h" + + +static char rcsid[] = "$Id: sprow.c,v 1.1 1994/01/13 05:35:36 des Exp $"; + +#define MINROWLEN 10 + + +#ifndef MEX +/* sprow_dump - prints relevant information about the sparse row r */ +#ifndef ANSI_C +void sprow_dump(fp,r) +FILE *fp; +SPROW *r; +#else +void sprow_dump(FILE *fp, const SPROW *r) +#endif +{ + int j_idx; + row_elt *elts; + + fprintf(fp,"SparseRow dump:\n"); + if ( ! r ) + { fprintf(fp,"*** NULL row ***\n"); return; } + + fprintf(fp,"row: len = %d, maxlen = %d, diag idx = %d\n", + r->len,r->maxlen,r->diag); + fprintf(fp,"element list @ 0x%lx\n",(long)(r->elt)); + if ( ! r->elt ) + { + fprintf(fp,"*** NULL element list ***\n"); + return; + } + elts = r->elt; + for ( j_idx = 0; j_idx < r->len; j_idx++, elts++ ) + fprintf(fp,"Col: %d, Val: %g, nxt_row = %d, nxt_idx = %d\n", + elts->col,elts->val,elts->nxt_row,elts->nxt_idx); + fprintf(fp,"\n"); +} +#endif /* MEX */ + +/* sprow_idx -- get index into row for a given column in a given row + -- return -1 on error + -- return -(idx+2) where idx is index to insertion point */ +#ifndef ANSI_C +int sprow_idx(r,col) +SPROW *r; +int col; +#else +int sprow_idx(const SPROW *r, int col) +#endif +{ + register int lo, hi, mid; + int tmp; + register row_elt *r_elt; + + /******************************************* + if ( r == (SPROW *)NULL ) + return -1; + if ( col < 0 ) + return -1; + *******************************************/ + + r_elt = r->elt; + if ( r->len <= 0 ) + return -2; + + /* try the hint */ + /* if ( hint >= 0 && hint < r->len && r_elt[hint].col == col ) + return hint; */ + + /* otherwise use binary search... */ + /* code from K&R Ch. 6, p. 125 */ + lo = 0; hi = r->len - 1; mid = lo; + while ( lo <= hi ) + { + mid = (hi + lo)/2; + if ( (tmp=r_elt[mid].col-col) > 0 ) + hi = mid-1; + else if ( tmp < 0 ) + lo = mid+1; + else /* tmp == 0 */ + return mid; + } + tmp = r_elt[mid].col - col; + + if ( tmp > 0 ) + return -(mid+2); /* insert at mid */ + else /* tmp < 0 */ + return -(mid+3); /* insert at mid+1 */ +} + + +/* sprow_get -- gets, initialises and returns a SPROW structure + -- max. length is maxlen */ +#ifndef ANSI_C +SPROW *sprow_get(maxlen) +int maxlen; +#else +SPROW *sprow_get(int maxlen) +#endif +{ + SPROW *r; + + if ( maxlen < 0 ) + error(E_NEG,"sprow_get"); + + r = NEW(SPROW); + if ( ! r ) + error(E_MEM,"sprow_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPROW,0,sizeof(SPROW)); + mem_numvar(TYPE_SPROW,1); + } + r->elt = NEW_A(maxlen,row_elt); + if ( ! r->elt ) + error(E_MEM,"sprow_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_SPROW,0,maxlen*sizeof(row_elt)); + } + r->len = 0; + r->maxlen = maxlen; + r->diag = -1; + + return r; +} + + +/* sprow_xpd -- expand row by means of realloc() + -- type must be TYPE_SPMAT if r is a row of a SPMAT structure, + otherwise it must be TYPE_SPROW + -- returns r */ +#ifndef ANSI_C +SPROW *sprow_xpd(r,n,type) +SPROW *r; +int n,type; +#else +SPROW *sprow_xpd(SPROW *r, int n, int type) +#endif +{ + int newlen; + + if ( ! r ) { + r = NEW(SPROW); + if (! r ) + error(E_MEM,"sprow_xpd"); + else if ( mem_info_is_on()) { + if (type != TYPE_SPMAT && type != TYPE_SPROW) + warning(WARN_WRONG_TYPE,"sprow_xpd"); + mem_bytes(type,0,sizeof(SPROW)); + if (type == TYPE_SPROW) + mem_numvar(type,1); + } + } + + if ( ! r->elt ) + { + r->elt = NEW_A((unsigned)n,row_elt); + if ( ! r->elt ) + error(E_MEM,"sprow_xpd"); + else if (mem_info_is_on()) { + mem_bytes(type,0,n*sizeof(row_elt)); + } + r->len = 0; + r->maxlen = n; + return r; + } + if ( n <= r->len ) + newlen = max(2*r->len + 1,MINROWLEN); + else + newlen = n; + if ( newlen <= r->maxlen ) + { + MEM_ZERO((char *)(&(r->elt[r->len])), + (newlen-r->len)*sizeof(row_elt)); + r->len = newlen; + } + else + { + if (mem_info_is_on()) { + mem_bytes(type,r->maxlen*sizeof(row_elt), + newlen*sizeof(row_elt)); + } + r->elt = RENEW(r->elt,newlen,row_elt); + if ( ! r->elt ) + error(E_MEM,"sprow_xpd"); + r->maxlen = newlen; + r->len = newlen; + } + + return r; +} + +/* sprow_resize -- resize a SPROW variable by means of realloc() + -- n is a new size + -- returns r */ +#ifndef ANSI_C +SPROW *sprow_resize(r,n,type) +SPROW *r; +int n,type; +#else +SPROW *sprow_resize(SPROW *r, int n, int type) +#endif +{ + if (n < 0) + error(E_NEG,"sprow_resize"); + + if ( ! r ) + return sprow_get(n); + + if (n == r->len) + return r; + + if ( ! r->elt ) + { + r->elt = NEW_A((unsigned)n,row_elt); + if ( ! r->elt ) + error(E_MEM,"sprow_resize"); + else if (mem_info_is_on()) { + mem_bytes(type,0,n*sizeof(row_elt)); + } + r->maxlen = r->len = n; + return r; + } + + if ( n <= r->maxlen ) + r->len = n; + else + { + if (mem_info_is_on()) { + mem_bytes(type,r->maxlen*sizeof(row_elt), + n*sizeof(row_elt)); + } + r->elt = RENEW(r->elt,n,row_elt); + if ( ! r->elt ) + error(E_MEM,"sprow_resize"); + r->maxlen = r->len = n; + } + + return r; +} + + +/* release a row of a matrix */ +#ifndef ANSI_C +int sprow_free(r) +SPROW *r; +#else +int sprow_free(SPROW *r) +#endif +{ + if ( ! r ) + return -1; + + if (mem_info_is_on()) { + mem_bytes(TYPE_SPROW,sizeof(SPROW),0); + mem_numvar(TYPE_SPROW,-1); + } + + if ( r->elt ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_SPROW,r->maxlen*sizeof(row_elt),0); + } + free((char *)r->elt); + } + free((char *)r); + return 0; +} + + +/* sprow_merge -- merges r1 and r2 into r_out + -- cannot be done in-situ + -- type must be TYPE_SPMAT or TYPE_SPROW depending on + whether r_out is a row of a SPMAT structure + or a SPROW variable + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_merge(r1,r2,r_out,type) +SPROW *r1, *r2, *r_out; +int type; +#else +SPROW *sprow_merge(const SPROW *r1, const SPROW *r2, SPROW *r_out, int type) +#endif +{ + int idx1, idx2, idx_out, len1, len2, len_out; + row_elt *elt1, *elt2, *elt_out; + + if ( ! r1 || ! r2 ) + error(E_NULL,"sprow_merge"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + if ( r1 == r_out || r2 == r_out ) + error(E_INSITU,"sprow_merge"); + + /* Initialise */ + len1 = r1->len; len2 = r2->len; len_out = r_out->maxlen; + idx1 = idx2 = idx_out = 0; + elt1 = r1->elt; elt2 = r2->elt; elt_out = r_out->elt; + + while ( idx1 < len1 || idx2 < len2 ) + { + if ( idx_out >= len_out ) + { /* r_out is too small */ + r_out->len = idx_out; + r_out = sprow_xpd(r_out,0,type); + len_out = r_out->len; + elt_out = &(r_out->elt[idx_out]); + } + if ( idx2 >= len2 || (idx1 < len1 && elt1->col <= elt2->col) ) + { + elt_out->col = elt1->col; + elt_out->val = elt1->val; + if ( elt1->col == elt2->col && idx2 < len2 ) + { elt2++; idx2++; } + elt1++; idx1++; + } + else + { + elt_out->col = elt2->col; + elt_out->val = elt2->val; + elt2++; idx2++; + } + elt_out++; idx_out++; + } + r_out->len = idx_out; + + return r_out; +} + +/* sprow_copy -- copies r1 and r2 into r_out + -- cannot be done in-situ + -- type must be TYPE_SPMAT or TYPE_SPROW depending on + whether r_out is a row of a SPMAT structure + or a SPROW variable + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_copy(r1,r2,r_out,type) +SPROW *r1, *r2, *r_out; +int type; +#else +SPROW *sprow_copy(const SPROW *r1, const SPROW *r2, SPROW *r_out, int type) +#endif +{ + int idx1, idx2, idx_out, len1, len2, len_out; + row_elt *elt1, *elt2, *elt_out; + + if ( ! r1 || ! r2 ) + error(E_NULL,"sprow_copy"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + if ( r1 == r_out || r2 == r_out ) + error(E_INSITU,"sprow_copy"); + + /* Initialise */ + len1 = r1->len; len2 = r2->len; len_out = r_out->maxlen; + idx1 = idx2 = idx_out = 0; + elt1 = r1->elt; elt2 = r2->elt; elt_out = r_out->elt; + + while ( idx1 < len1 || idx2 < len2 ) + { + while ( idx_out >= len_out ) + { /* r_out is too small */ + r_out->len = idx_out; + r_out = sprow_xpd(r_out,0,type); + len_out = r_out->maxlen; + elt_out = &(r_out->elt[idx_out]); + } + if ( idx2 >= len2 || (idx1 < len1 && elt1->col <= elt2->col) ) + { + elt_out->col = elt1->col; + elt_out->val = elt1->val; + if ( elt1->col == elt2->col && idx2 < len2 ) + { elt2++; idx2++; } + elt1++; idx1++; + } + else + { + elt_out->col = elt2->col; + elt_out->val = 0.0; + elt2++; idx2++; + } + elt_out++; idx_out++; + } + r_out->len = idx_out; + + return r_out; +} + +/* sprow_mltadd -- sets r_out <- r1 + alpha.r2 + -- cannot be in situ + -- only for columns j0, j0+1, ... + -- type must be TYPE_SPMAT or TYPE_SPROW depending on + whether r_out is a row of a SPMAT structure + or a SPROW variable + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_mltadd(r1,r2,alpha,j0,r_out,type) +SPROW *r1, *r2, *r_out; +double alpha; +int j0, type; +#else +SPROW *sprow_mltadd(const SPROW *r1,const SPROW *r2, double alpha, + int j0, SPROW *r_out, int type) +#endif +{ + int idx1, idx2, idx_out, len1, len2, len_out; + row_elt *elt1, *elt2, *elt_out; + + if ( ! r1 || ! r2 ) + error(E_NULL,"sprow_mltadd"); + if ( r1 == r_out || r2 == r_out ) + error(E_INSITU,"sprow_mltadd"); + if ( j0 < 0 ) + error(E_BOUNDS,"sprow_mltadd"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + + /* Initialise */ + len1 = r1->len; len2 = r2->len; len_out = r_out->maxlen; + /* idx1 = idx2 = idx_out = 0; */ + idx1 = sprow_idx(r1,j0); + idx2 = sprow_idx(r2,j0); + idx_out = sprow_idx(r_out,j0); + idx1 = (idx1 < 0) ? -(idx1+2) : idx1; + idx2 = (idx2 < 0) ? -(idx2+2) : idx2; + idx_out = (idx_out < 0) ? -(idx_out+2) : idx_out; + elt1 = &(r1->elt[idx1]); + elt2 = &(r2->elt[idx2]); + elt_out = &(r_out->elt[idx_out]); + + while ( idx1 < len1 || idx2 < len2 ) + { + if ( idx_out >= len_out ) + { /* r_out is too small */ + r_out->len = idx_out; + r_out = sprow_xpd(r_out,0,type); + len_out = r_out->maxlen; + elt_out = &(r_out->elt[idx_out]); + } + if ( idx2 >= len2 || (idx1 < len1 && elt1->col <= elt2->col) ) + { + elt_out->col = elt1->col; + elt_out->val = elt1->val; + if ( idx2 < len2 && elt1->col == elt2->col ) + { + elt_out->val += alpha*elt2->val; + elt2++; idx2++; + } + elt1++; idx1++; + } + else + { + elt_out->col = elt2->col; + elt_out->val = alpha*elt2->val; + elt2++; idx2++; + } + elt_out++; idx_out++; + } + r_out->len = idx_out; + + return r_out; +} + +/* sprow_add -- sets r_out <- r1 + r2 + -- cannot be in situ + -- only for columns j0, j0+1, ... + -- type must be TYPE_SPMAT or TYPE_SPROW depending on + whether r_out is a row of a SPMAT structure + or a SPROW variable + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_add(r1,r2,j0,r_out,type) +SPROW *r1, *r2, *r_out; +int j0, type; +#else +SPROW *sprow_add(const SPROW *r1,const SPROW *r2, + int j0, SPROW *r_out, int type) +#endif +{ + int idx1, idx2, idx_out, len1, len2, len_out; + row_elt *elt1, *elt2, *elt_out; + + if ( ! r1 || ! r2 ) + error(E_NULL,"sprow_add"); + if ( r1 == r_out || r2 == r_out ) + error(E_INSITU,"sprow_add"); + if ( j0 < 0 ) + error(E_BOUNDS,"sprow_add"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + + /* Initialise */ + len1 = r1->len; len2 = r2->len; len_out = r_out->maxlen; + /* idx1 = idx2 = idx_out = 0; */ + idx1 = sprow_idx(r1,j0); + idx2 = sprow_idx(r2,j0); + idx_out = sprow_idx(r_out,j0); + idx1 = (idx1 < 0) ? -(idx1+2) : idx1; + idx2 = (idx2 < 0) ? -(idx2+2) : idx2; + idx_out = (idx_out < 0) ? -(idx_out+2) : idx_out; + elt1 = &(r1->elt[idx1]); + elt2 = &(r2->elt[idx2]); + elt_out = &(r_out->elt[idx_out]); + + while ( idx1 < len1 || idx2 < len2 ) + { + if ( idx_out >= len_out ) + { /* r_out is too small */ + r_out->len = idx_out; + r_out = sprow_xpd(r_out,0,type); + len_out = r_out->maxlen; + elt_out = &(r_out->elt[idx_out]); + } + if ( idx2 >= len2 || (idx1 < len1 && elt1->col <= elt2->col) ) + { + elt_out->col = elt1->col; + elt_out->val = elt1->val; + if ( idx2 < len2 && elt1->col == elt2->col ) + { + elt_out->val += elt2->val; + elt2++; idx2++; + } + elt1++; idx1++; + } + else + { + elt_out->col = elt2->col; + elt_out->val = elt2->val; + elt2++; idx2++; + } + elt_out++; idx_out++; + } + r_out->len = idx_out; + + return r_out; +} + +/* sprow_sub -- sets r_out <- r1 - r2 + -- cannot be in situ + -- only for columns j0, j0+1, ... + -- type must be TYPE_SPMAT or TYPE_SPROW depending on + whether r_out is a row of a SPMAT structure + or a SPROW variable + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_sub(r1,r2,j0,r_out,type) +SPROW *r1, *r2, *r_out; +int j0, type; +#else +SPROW *sprow_sub(const SPROW *r1, const SPROW *r2, + int j0, SPROW *r_out, int type) +#endif +{ + int idx1, idx2, idx_out, len1, len2, len_out; + row_elt *elt1, *elt2, *elt_out; + + if ( ! r1 || ! r2 ) + error(E_NULL,"sprow_sub"); + if ( r1 == r_out || r2 == r_out ) + error(E_INSITU,"sprow_sub"); + if ( j0 < 0 ) + error(E_BOUNDS,"sprow_sub"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + + /* Initialise */ + len1 = r1->len; len2 = r2->len; len_out = r_out->maxlen; + /* idx1 = idx2 = idx_out = 0; */ + idx1 = sprow_idx(r1,j0); + idx2 = sprow_idx(r2,j0); + idx_out = sprow_idx(r_out,j0); + idx1 = (idx1 < 0) ? -(idx1+2) : idx1; + idx2 = (idx2 < 0) ? -(idx2+2) : idx2; + idx_out = (idx_out < 0) ? -(idx_out+2) : idx_out; + elt1 = &(r1->elt[idx1]); + elt2 = &(r2->elt[idx2]); + elt_out = &(r_out->elt[idx_out]); + + while ( idx1 < len1 || idx2 < len2 ) + { + if ( idx_out >= len_out ) + { /* r_out is too small */ + r_out->len = idx_out; + r_out = sprow_xpd(r_out,0,type); + len_out = r_out->maxlen; + elt_out = &(r_out->elt[idx_out]); + } + if ( idx2 >= len2 || (idx1 < len1 && elt1->col <= elt2->col) ) + { + elt_out->col = elt1->col; + elt_out->val = elt1->val; + if ( idx2 < len2 && elt1->col == elt2->col ) + { + elt_out->val -= elt2->val; + elt2++; idx2++; + } + elt1++; idx1++; + } + else + { + elt_out->col = elt2->col; + elt_out->val = -elt2->val; + elt2++; idx2++; + } + elt_out++; idx_out++; + } + r_out->len = idx_out; + + return r_out; +} + + +/* sprow_smlt -- sets r_out <- alpha*r1 + -- can be in situ + -- only for columns j0, j0+1, ... + -- returns r_out */ +#ifndef ANSI_C +SPROW *sprow_smlt(r1,alpha,j0,r_out,type) +SPROW *r1, *r_out; +double alpha; +int j0, type; +#else +SPROW *sprow_smlt(const SPROW *r1, double alpha, int j0, SPROW *r_out, int type) +#endif +{ + int idx1, idx_out, len1; + row_elt *elt1, *elt_out; + + if ( ! r1 ) + error(E_NULL,"sprow_smlt"); + if ( j0 < 0 ) + error(E_BOUNDS,"sprow_smlt"); + if ( ! r_out ) + r_out = sprow_get(MINROWLEN); + + /* Initialise */ + len1 = r1->len; + idx1 = sprow_idx(r1,j0); + idx_out = sprow_idx(r_out,j0); + idx1 = (idx1 < 0) ? -(idx1+2) : idx1; + idx_out = (idx_out < 0) ? -(idx_out+2) : idx_out; + elt1 = &(r1->elt[idx1]); + + r_out = sprow_resize(r_out,idx_out+len1-idx1,type); + elt_out = &(r_out->elt[idx_out]); + + for ( ; idx1 < len1; elt1++,elt_out++,idx1++,idx_out++ ) + { + elt_out->col = elt1->col; + elt_out->val = alpha*elt1->val; + } + + r_out->len = idx_out; + + return r_out; +} + +#ifndef MEX +/* sprow_foutput -- print a representation of r on stream fp */ +#ifndef ANSI_C +void sprow_foutput(fp,r) +FILE *fp; +SPROW *r; +#else +void sprow_foutput(FILE *fp, const SPROW *r) +#endif +{ + int i, len; + row_elt *e; + + if ( ! r ) + { + fprintf(fp,"SparseRow: **** NULL ****\n"); + return; + } + len = r->len; + fprintf(fp,"SparseRow: length: %d\n",len); + for ( i = 0, e = r->elt; i < len; i++, e++ ) + fprintf(fp,"Column %d: %g, next row: %d, next index %d\n", + e->col, e->val, e->nxt_row, e->nxt_idx); +} +#endif + + +/* sprow_set_val -- sets the j-th column entry of the sparse row r + -- Note: destroys the usual column & row access paths */ +#ifndef ANSI_C +double sprow_set_val(r,j,val) +SPROW *r; +int j; +double val; +#else +double sprow_set_val(SPROW *r, int j, double val) +#endif +{ + int idx, idx2, new_len; + + if ( ! r ) + error(E_NULL,"sprow_set_val"); + + idx = sprow_idx(r,j); + if ( idx >= 0 ) + { r->elt[idx].val = val; return val; } + /* else */ if ( idx < -1 ) + { + /* shift & insert new value */ + idx = -(idx+2); /* this is the intended insertion index */ + if ( r->len >= r->maxlen ) + { + r->len = r->maxlen; + new_len = max(2*r->maxlen+1,5); + if (mem_info_is_on()) { + mem_bytes(TYPE_SPROW,r->maxlen*sizeof(row_elt), + new_len*sizeof(row_elt)); + } + + r->elt = RENEW(r->elt,new_len,row_elt); + if ( ! r->elt ) /* can't allocate */ + error(E_MEM,"sprow_set_val"); + r->maxlen = 2*r->maxlen+1; + } + for ( idx2 = r->len-1; idx2 >= idx; idx2-- ) + MEM_COPY((char *)(&(r->elt[idx2])), + (char *)(&(r->elt[idx2+1])),sizeof(row_elt)); + /************************************************************ + if ( idx < r->len ) + MEM_COPY((char *)(&(r->elt[idx])),(char *)(&(r->elt[idx+1])), + (r->len-idx)*sizeof(row_elt)); + ************************************************************/ + r->len++; + r->elt[idx].col = j; + r->elt[idx].nxt_row = -1; + r->elt[idx].nxt_idx = -1; + return r->elt[idx].val = val; + } + /* else -- idx == -1, error in index/matrix! */ + return 0.0; +} + + diff --git a/spswap.c b/spswap.c new file mode 100644 index 0000000..2bc9ec9 --- /dev/null +++ b/spswap.c @@ -0,0 +1,326 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Sparse matrix swap and permutation routines + Modified Mon 09th Nov 1992, 08:50:54 PM + to use Karen George's suggestion to use unordered rows +*/ + +static char rcsid[] = "$Id: spswap.c,v 1.3 1994/01/13 05:44:43 des Exp $"; + +#include +#include +#include "sparse2.h" + + +#define btos(x) ((x) ? "TRUE" : "FALSE") + +/* scan_to -- updates scan (int) vectors to point to the last row in each + column with row # <= max_row, if any */ +#ifndef ANSI_C +void scan_to(A, scan_row, scan_idx, col_list, max_row) +SPMAT *A; +IVEC *scan_row, *scan_idx, *col_list; +int max_row; +#else +void scan_to(SPMAT *A, IVEC *scan_row, IVEC *scan_idx, IVEC *col_list, + int max_row) +#endif +{ + int col, idx, j_idx, row_num; + SPROW *r; + row_elt *e; + + if ( ! A || ! scan_row || ! scan_idx || ! col_list ) + error(E_NULL,"scan_to"); + if ( scan_row->dim != scan_idx->dim || scan_idx->dim != col_list->dim ) + error(E_SIZES,"scan_to"); + + if ( max_row < 0 ) + return; + + if ( ! A->flag_col ) + sp_col_access(A); + + for ( j_idx = 0; j_idx < scan_row->dim; j_idx++ ) + { + row_num = scan_row->ive[j_idx]; + idx = scan_idx->ive[j_idx]; + col = col_list->ive[j_idx]; + + if ( col < 0 || col >= A->n ) + error(E_BOUNDS,"scan_to"); + if ( row_num < 0 ) + { + idx = col; + continue; + } + r = &(A->row[row_num]); + if ( idx < 0 ) + error(E_INTERN,"scan_to"); + e = &(r->elt[idx]); + if ( e->col != col ) + error(E_INTERN,"scan_to"); + if ( idx < 0 ) + { + printf("scan_to: row_num = %d, idx = %d, col = %d\n", + row_num, idx, col); + error(E_INTERN,"scan_to"); + } + /* if ( e->nxt_row <= max_row ) + chase_col(A, col, &row_num, &idx, max_row); */ + while ( e->nxt_row >= 0 && e->nxt_row <= max_row ) + { + row_num = e->nxt_row; + idx = e->nxt_idx; + e = &(A->row[row_num].elt[idx]); + } + + /* printf("scan_to: computed j_idx = %d, row_num = %d, idx = %d\n", + j_idx, row_num, idx); */ + scan_row->ive[j_idx] = row_num; + scan_idx->ive[j_idx] = idx; + } +} + +/* patch_col -- patches column access paths for fill-in */ +#ifndef ANSI_C +void patch_col(A, col, old_row, old_idx, row_num, idx) +SPMAT *A; +int col, old_row, old_idx, row_num, idx; +#else +void patch_col(SPMAT *A, int col, int old_row, int old_idx, int row_num, + int idx) +#endif +{ + SPROW *r; + row_elt *e; + + if ( old_row >= 0 ) + { + r = &(A->row[old_row]); + old_idx = sprow_idx2(r,col,old_idx); + e = &(r->elt[old_idx]); + e->nxt_row = row_num; + e->nxt_idx = idx; + } + else + { + A->start_row[col] = row_num; + A->start_idx[col] = idx; + } +} + +/* chase_col -- chases column access path in column col, starting with + row_num and idx, to find last row # in this column <= max_row + -- row_num is returned; idx is also set by this routine + -- assumes that the column access paths (possibly without the + nxt_idx fields) are set up */ +#ifndef ANSI_C +row_elt *chase_col(A, col, row_num, idx, max_row) +SPMAT *A; +int col, *row_num, *idx, max_row; +#else +row_elt *chase_col(const SPMAT *A, int col, int *row_num, int *idx, + int max_row) +#endif +{ + int old_idx, old_row, tmp_idx, tmp_row; + SPROW *r; + row_elt *e; + + if ( col < 0 || col >= A->n ) + error(E_BOUNDS,"chase_col"); + tmp_row = *row_num; + if ( tmp_row < 0 ) + { + if ( A->start_row[col] > max_row ) + { + tmp_row = -1; + tmp_idx = col; + return (row_elt *)NULL; + } + else + { + tmp_row = A->start_row[col]; + tmp_idx = A->start_idx[col]; + } + } + else + tmp_idx = *idx; + + old_row = tmp_row; + old_idx = tmp_idx; + while ( tmp_row >= 0 && tmp_row < max_row ) + { + r = &(A->row[tmp_row]); + /* tmp_idx = sprow_idx2(r,col,tmp_idx); */ + if ( tmp_idx < 0 || tmp_idx >= r->len || + r->elt[tmp_idx].col != col ) + { +#ifdef DEBUG + printf("chase_col:error: col = %d, row # = %d, idx = %d\n", + col, tmp_row, tmp_idx); + printf("chase_col:error: old_row = %d, old_idx = %d\n", + old_row, old_idx); + printf("chase_col:error: A =\n"); + sp_dump(stdout,A); +#endif + error(E_INTERN,"chase_col"); + } + e = &(r->elt[tmp_idx]); + old_row = tmp_row; + old_idx = tmp_idx; + tmp_row = e->nxt_row; + tmp_idx = e->nxt_idx; + } + if ( old_row > max_row ) + { + old_row = -1; + old_idx = col; + e = (row_elt *)NULL; + } + else if ( tmp_row <= max_row && tmp_row >= 0 ) + { + old_row = tmp_row; + old_idx = tmp_idx; + } + + *row_num = old_row; + if ( old_row >= 0 ) + *idx = old_idx; + else + *idx = col; + + return e; +} + +/* chase_past -- as for chase_col except that we want the first + row whose row # >= min_row; -1 indicates no such row */ +#ifndef ANSI_C +row_elt *chase_past(A, col, row_num, idx, min_row) +SPMAT *A; +int col, *row_num, *idx, min_row; +#else +row_elt *chase_past(const SPMAT *A, int col, int *row_num, int *idx, + int min_row) +#endif +{ + SPROW *r; + row_elt *e; + int tmp_idx, tmp_row; + + tmp_row = *row_num; + tmp_idx = *idx; + chase_col(A,col,&tmp_row,&tmp_idx,min_row); + if ( tmp_row < 0 ) /* use A->start_row[..] etc. */ + { + if ( A->start_row[col] < 0 ) + tmp_row = -1; + else + { + tmp_row = A->start_row[col]; + tmp_idx = A->start_idx[col]; + } + } + else if ( tmp_row < min_row ) + { + r = &(A->row[tmp_row]); + if ( tmp_idx < 0 || tmp_idx >= r->len || + r->elt[tmp_idx].col != col ) + error(E_INTERN,"chase_past"); + tmp_row = r->elt[tmp_idx].nxt_row; + tmp_idx = r->elt[tmp_idx].nxt_idx; + } + + *row_num = tmp_row; + *idx = tmp_idx; + if ( tmp_row < 0 ) + e = (row_elt *)NULL; + else + { + if ( tmp_idx < 0 || tmp_idx >= A->row[tmp_row].len || + A->row[tmp_row].elt[tmp_idx].col != col ) + error(E_INTERN,"bump_col"); + e = &(A->row[tmp_row].elt[tmp_idx]); + } + + return e; +} + +/* bump_col -- move along to next nonzero entry in column col after row_num + -- update row_num and idx */ +#ifndef ANSI_C +row_elt *bump_col(A, col, row_num, idx) +SPMAT *A; +int col, *row_num, *idx; +#else +row_elt *bump_col(const SPMAT *A, int col, int *row_num, int *idx) +#endif +{ + SPROW *r; + row_elt *e; + int tmp_row, tmp_idx; + + tmp_row = *row_num; + tmp_idx = *idx; + /* printf("bump_col: col = %d, row# = %d, idx = %d\n", + col, *row_num, *idx); */ + if ( tmp_row < 0 ) + { + tmp_row = A->start_row[col]; + tmp_idx = A->start_idx[col]; + } + else + { + r = &(A->row[tmp_row]); + if ( tmp_idx < 0 || tmp_idx >= r->len || + r->elt[tmp_idx].col != col ) + error(E_INTERN,"bump_col"); + e = &(r->elt[tmp_idx]); + tmp_row = e->nxt_row; + tmp_idx = e->nxt_idx; + } + if ( tmp_row < 0 ) + { + e = (row_elt *)NULL; + tmp_idx = col; + } + else + { + if ( tmp_idx < 0 || tmp_idx >= A->row[tmp_row].len || + A->row[tmp_row].elt[tmp_idx].col != col ) + error(E_INTERN,"bump_col"); + e = &(A->row[tmp_row].elt[tmp_idx]); + } + *row_num = tmp_row; + *idx = tmp_idx; + + return e; +} + + diff --git a/sptort.c b/sptort.c new file mode 100644 index 0000000..d669b4c --- /dev/null +++ b/sptort.c @@ -0,0 +1,485 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains tests for the sparse matrix part of Meschach +*/ + +#include +#include +#include "matrix2.h" +#include "sparse2.h" +#include "iter.h" + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + +/* for iterative methods */ + +#if REAL == DOUBLE +#define EPS 1e-7 +#elif REAL == FLOAT +#define EPS 1e-3 +#endif + +int chk_col_accessSPT(A) +SPMAT *A; +{ + int i, j, nxt_idx, nxt_row, scan_cnt, total_cnt; + SPROW *r; + row_elt *e; + + if ( ! A ) + error(E_NULL,"chk_col_accessSPT"); + if ( ! A->flag_col ) + return FALSE; + + /* scan down each column, counting the number of entries met */ + scan_cnt = 0; + for ( j = 0; j < A->n; j++ ) + { + i = -1; + nxt_idx = A->start_idx[j]; + nxt_row = A->start_row[j]; + while ( nxt_row >= 0 && nxt_idx >= 0 && nxt_row > i ) + { + i = nxt_row; + r = &(A->row[i]); + e = &(r->elt[nxt_idx]); + nxt_idx = e->nxt_idx; + nxt_row = e->nxt_row; + scan_cnt++; + } + } + + total_cnt = 0; + for ( i = 0; i < A->m; i++ ) + total_cnt += A->row[i].len; + if ( total_cnt != scan_cnt ) + return FALSE; + else + return TRUE; +} + + +void main(argc, argv) +int argc; +char *argv[]; +{ + VEC *x, *y, *z, *u, *v; + Real s1, s2; + PERM *pivot; + SPMAT *A, *B, *C; + SPMAT *B1, *C1; + SPROW *r; + int i, j, k, deg, seed, m, m_old, n, n_old; + + + mem_info_on(TRUE); + + setbuf(stdout, (char *)NULL); + /* get seed if in argument list */ + if ( argc == 1 ) + seed = 1111; + else if ( argc == 2 && sscanf(argv[1],"%d",&seed) == 1 ) + ; + else + { + printf("usage: %s [seed]\n", argv[0]); + exit(0); + } + srand(seed); + + /* set up two random sparse matrices */ + m = 120; + n = 100; + deg = 8; + notice("allocating sparse matrices"); + A = sp_get(m,n,deg); + B = sp_get(m,n,deg); + notice("setting and getting matrix entries"); + for ( k = 0; k < m*deg; k++ ) + { + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(A,i,j,rand()/((Real)MAX_RAND)); + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(B,i,j,rand()/((Real)MAX_RAND)); + } + for ( k = 0; k < 10; k++ ) + { + s1 = rand()/((Real)MAX_RAND); + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(A,i,j,s1); + s2 = sp_get_val(A,i,j); + if ( fabs(s1 - s2) >= MACHEPS ) + break; + } + if ( k < 10 ) + errmesg("sp_set_val()/sp_get_val()"); + + /* test copy routines */ + notice("copy routines"); + x = v_get(n); + y = v_get(m); + z = v_get(m); + /* first copy routine */ + C = sp_copy(A); + for ( k = 0; k < 100; k++ ) + { + v_rand(x); + sp_mv_mlt(A,x,y); + sp_mv_mlt(C,x,z); + if ( v_norm_inf(v_sub(y,z,z)) >= MACHEPS*deg*m ) + break; + } + if ( k < 100 ) + { + errmesg("sp_copy()/sp_mv_mlt()"); + printf("# Error in A.x (inf norm) = %g [cf MACHEPS = %g]\n", + v_norm_inf(z), MACHEPS); + } + /* second copy routine + -- note that A & B have different sparsity patterns */ + + mem_stat_mark(1); + sp_copy2(A,B); + mem_stat_free(1); + for ( k = 0; k < 10; k++ ) + { + v_rand(x); + sp_mv_mlt(A,x,y); + sp_mv_mlt(B,x,z); + if ( v_norm_inf(v_sub(y,z,z)) >= MACHEPS*deg*m ) + break; + } + if ( k < 10 ) + { + errmesg("sp_copy2()/sp_mv_mlt()"); + printf("# Error in A.x (inf norm) = %g [cf MACHEPS = %g]\n", + v_norm_inf(z), MACHEPS); + } + + /* now check compacting routine */ + notice("compacting routine"); + sp_compact(B,0.0); + for ( k = 0; k < 10; k++ ) + { + v_rand(x); + sp_mv_mlt(A,x,y); + sp_mv_mlt(B,x,z); + if ( v_norm_inf(v_sub(y,z,z)) >= MACHEPS*deg*m ) + break; + } + if ( k < 10 ) + { + errmesg("sp_compact()"); + printf("# Error in A.x (inf norm) = %g [cf MACHEPS = %g]\n", + v_norm_inf(z), MACHEPS); + } + for ( i = 0; i < B->m; i++ ) + { + r = &(B->row[i]); + for ( j = 0; j < r->len; j++ ) + if ( r->elt[j].val == 0.0 ) + break; + } + if ( i < B->m ) + { + errmesg("sp_compact()"); + printf("# Zero entry in compacted matrix\n"); + } + + /* check column access paths */ + notice("resizing and access paths"); + m_old = A->m-1; + n_old = A->n-1; + A = sp_resize(A,A->m+10,A->n+10); + for ( k = 0 ; k < 20; k++ ) + { + i = m_old + ((rand() >> 8) % 10); + j = n_old + ((rand() >> 8) % 10); + s1 = rand()/((Real)MAX_RAND); + sp_set_val(A,i,j,s1); + if ( fabs(s1 - sp_get_val(A,i,j)) >= MACHEPS ) + break; + } + if ( k < 20 ) + errmesg("sp_resize()"); + sp_col_access(A); + if ( ! chk_col_accessSPT(A) ) + { + errmesg("sp_col_access()"); + } + sp_diag_access(A); + for ( i = 0; i < A->m; i++ ) + { + r = &(A->row[i]); + if ( r->diag != sprow_idx(r,i) ) + break; + } + if ( i < A->m ) + { + errmesg("sp_diag_access()"); + } + + /* test both sp_mv_mlt() and sp_vm_mlt() */ + x = v_resize(x,B->n); + y = v_resize(y,B->m); + u = v_get(B->m); + v = v_get(B->n); + for ( k = 0; k < 10; k++ ) + { + v_rand(x); + v_rand(y); + sp_mv_mlt(B,x,u); + sp_vm_mlt(B,y,v); + if ( fabs(in_prod(x,v) - in_prod(y,u)) >= + MACHEPS*v_norm2(x)*v_norm2(u)*5 ) + break; + } + if ( k < 10 ) + { + errmesg("sp_mv_mlt()/sp_vm_mlt()"); + printf("# Error in inner products = %g [cf MACHEPS = %g]\n", + fabs(in_prod(x,v) - in_prod(y,u)), MACHEPS); + } + + SP_FREE(A); + SP_FREE(B); + SP_FREE(C); + + /* now test Cholesky and LU factorise and solve */ + notice("sparse Cholesky factorise/solve"); + A = iter_gen_sym(120,8); + B = sp_copy(A); + spCHfactor(A); + x = v_resize(x,A->m); + y = v_resize(y,A->m); + v_rand(x); + sp_mv_mlt(B,x,y); + z = v_resize(z,A->m); + spCHsolve(A,y,z); + v = v_resize(v,A->m); + sp_mv_mlt(B,z,v); + /* compute residual */ + v_sub(y,v,v); + if ( v_norm2(v) >= MACHEPS*v_norm2(y)*10 ) + { + errmesg("spCHfactor()/spCHsolve()"); + printf("# Sparse Cholesky residual = %g [cf MACHEPS = %g]\n", + v_norm2(v), MACHEPS); + } + /* compute error in solution */ + v_sub(x,z,z); + if ( v_norm2(z) > MACHEPS*v_norm2(x)*10 ) + { + errmesg("spCHfactor()/spCHsolve()"); + printf("# Solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + + /* now test symbolic and incomplete factorisation */ + SP_FREE(A); + A = sp_copy(B); + + mem_stat_mark(2); + spCHsymb(A); + mem_stat_mark(2); + + spICHfactor(A); + spCHsolve(A,y,z); + v = v_resize(v,A->m); + sp_mv_mlt(B,z,v); + /* compute residual */ + v_sub(y,v,v); + if ( v_norm2(v) >= MACHEPS*v_norm2(y)*5 ) + { + errmesg("spCHsymb()/spICHfactor()"); + printf("# Sparse Cholesky residual = %g [cf MACHEPS = %g]\n", + v_norm2(v), MACHEPS); + } + /* compute error in solution */ + v_sub(x,z,z); + if ( v_norm2(z) > MACHEPS*v_norm2(x)*10 ) + { + errmesg("spCHsymb()/spICHfactor()"); + printf("# Solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + + /* now test sparse LU factorisation */ + notice("sparse LU factorise/solve"); + SP_FREE(A); + SP_FREE(B); + A = iter_gen_nonsym(100,100,8,1.0); + + B = sp_copy(A); + x = v_resize(x,A->n); + z = v_resize(z,A->n); + y = v_resize(y,A->m); + v = v_resize(v,A->m); + + v_rand(x); + sp_mv_mlt(B,x,y); + pivot = px_get(A->m); + + mem_stat_mark(3); + spLUfactor(A,pivot,0.1); + spLUsolve(A,pivot,y,z); + mem_stat_free(3); + sp_mv_mlt(B,z,v); + + /* compute residual */ + v_sub(y,v,v); + if ( v_norm2(v) >= MACHEPS*v_norm2(y)*A->m ) + { + errmesg("spLUfactor()/spLUsolve()"); + printf("# Sparse LU residual = %g [cf MACHEPS = %g]\n", + v_norm2(v), MACHEPS); + } + /* compute error in solution */ + v_sub(x,z,z); + if ( v_norm2(z) > MACHEPS*v_norm2(x)*100*A->m ) + { + errmesg("spLUfactor()/spLUsolve()"); + printf("# Sparse LU solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + + /* now check spLUTsolve */ + mem_stat_mark(4); + sp_vm_mlt(B,x,y); + spLUTsolve(A,pivot,y,z); + sp_vm_mlt(B,z,v); + mem_stat_free(4); + + /* compute residual */ + v_sub(y,v,v); + if ( v_norm2(v) >= MACHEPS*v_norm2(y)*A->m ) + { + errmesg("spLUTsolve()"); + printf("# Sparse LU residual = %g [cf MACHEPS = %g]\n", + v_norm2(v), MACHEPS); + } + /* compute error in solution */ + v_sub(x,z,z); + if ( v_norm2(z) > MACHEPS*v_norm2(x)*100*A->m ) + { + errmesg("spLUTsolve()"); + printf("# Sparse LU solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + + /* algebraic operations */ + notice("addition,subtraction and multiplying by a number"); + SP_FREE(A); + SP_FREE(B); + + m = 120; + n = 120; + deg = 5; + A = sp_get(m,n,deg); + B = sp_get(m,n,deg); + C = sp_get(m,n,deg); + C1 = sp_get(m,n,deg); + + for ( k = 0; k < m*deg; k++ ) + { + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(A,i,j,rand()/((Real)MAX_RAND)); + i = (rand() >> 8) % m; + j = (rand() >> 8) % n; + sp_set_val(B,i,j,rand()/((Real)MAX_RAND)); + } + + s1 = mrand(); + B1 = sp_copy(B); + + mem_stat_mark(1); + sp_smlt(B,s1,C); + sp_add(A,C,C1); + sp_sub(C1,A,C); + sp_smlt(C,-1.0/s1,C); + sp_add(C,B1,C); + + s2 = 0.0; + for (k=0; k < C->m; k++) { + r = &(C->row[k]); + for (j=0; j < r->len; j++) { + if (s2 < fabs(r->elt[j].val)) + s2 = fabs(r->elt[j].val); + } + } + + if (s2 > MACHEPS*A->m) { + errmesg("add, sub, mlt sparse matrices (args not in situ)\n"); + printf(" difference = %g [MACEPS = %g]\n",s2,MACHEPS); + } + + sp_mltadd(A,B1,s1,C1); + sp_sub(C1,A,A); + sp_smlt(A,1.0/s1,C1); + sp_sub(C1,B1,C1); + mem_stat_free(1); + + s2 = 0.0; + for (k=0; k < C1->m; k++) { + r = &(C1->row[k]); + for (j=0; j < r->len; j++) { + if (s2 < fabs(r->elt[j].val)) + s2 = fabs(r->elt[j].val); + } + } + + if (s2 > MACHEPS*A->m) { + errmesg("add, sub, mlt sparse matrices (args not in situ)\n"); + printf(" difference = %g [MACEPS = %g]\n",s2,MACHEPS); + } + + V_FREE(x); + V_FREE(y); + V_FREE(z); + V_FREE(u); + V_FREE(v); + PX_FREE(pivot); + SP_FREE(A); + SP_FREE(B); + SP_FREE(C); + SP_FREE(B1); + SP_FREE(C1); + + printf("# Done testing (%s)\n",argv[0]); + mem_info(); +} + + + + + diff --git a/submat.c b/submat.c new file mode 100644 index 0000000..0102631 --- /dev/null +++ b/submat.c @@ -0,0 +1,206 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* 1.2 submat.c 11/25/87 */ + +#include +#include "matrix.h" + +static char rcsid[] = "$Id: submat.c,v 1.2 1994/01/13 05:28:12 des Exp $"; + + +/* get_col -- gets a specified column of a matrix and retruns it as a vector */ +#ifndef ANSI_C +VEC *get_col(mat,col,vec) +unsigned int col; +MAT *mat; +VEC *vec; +#else +VEC *get_col(const MAT *mat, unsigned int col, VEC *vec) +#endif +{ + unsigned int i; + + if ( mat==(MAT *)NULL ) + error(E_NULL,"get_col"); + if ( col >= mat->n ) + error(E_RANGE,"get_col"); + if ( vec==(VEC *)NULL || vec->dimm ) + vec = v_resize(vec,mat->m); + + for ( i=0; im; i++ ) + vec->ve[i] = mat->me[i][col]; + + return (vec); +} + +/* get_row -- gets a specified row of a matrix and retruns it as a vector */ +#ifndef ANSI_C +VEC *get_row(mat,row,vec) +unsigned int row; +MAT *mat; +VEC *vec; +#else +VEC *get_row(const MAT *mat, unsigned int row, VEC *vec) +#endif +{ + unsigned int i; + + if ( mat==(MAT *)NULL ) + error(E_NULL,"get_row"); + if ( row >= mat->m ) + error(E_RANGE,"get_row"); + if ( vec==(VEC *)NULL || vec->dimn ) + vec = v_resize(vec,mat->n); + + for ( i=0; in; i++ ) + vec->ve[i] = mat->me[row][i]; + + return (vec); +} + +/* _set_col -- sets column of matrix to values given in vec (in situ) + -- that is, mat(i0:lim,col) <- vec(i0:lim) */ +#ifndef ANSI_C +MAT *_set_col(mat,col,vec,i0) +MAT *mat; +VEC *vec; +unsigned int col,i0; +#else +MAT *_set_col(MAT *mat, unsigned int col, const VEC *vec, unsigned int i0) +#endif +{ + unsigned int i,lim; + + if ( mat==(MAT *)NULL || vec==(VEC *)NULL ) + error(E_NULL,"_set_col"); + if ( col >= mat->n ) + error(E_RANGE,"_set_col"); + lim = min(mat->m,vec->dim); + for ( i=i0; ime[i][col] = vec->ve[i]; + + return (mat); +} + +/* _set_row -- sets row of matrix to values given in vec (in situ) */ +#ifndef ANSI_C +MAT *_set_row(mat,row,vec,j0) +MAT *mat; +VEC *vec; +unsigned int row,j0; +#else +MAT *_set_row(MAT *mat, unsigned int row, const VEC *vec, unsigned int j0) +#endif +{ + unsigned int j,lim; + + if ( mat==(MAT *)NULL || vec==(VEC *)NULL ) + error(E_NULL,"_set_row"); + if ( row >= mat->m ) + error(E_RANGE,"_set_row"); + lim = min(mat->n,vec->dim); + for ( j=j0; jme[row][j] = vec->ve[j]; + + return (mat); +} + +/* sub_mat -- returns sub-matrix of old which is formed by the rectangle + from (row1,col1) to (row2,col2) + -- Note: storage is shared so that altering the "new" + matrix will alter the "old" matrix */ +#ifndef ANSI_C +MAT *sub_mat(old,row1,col1,row2,col2,new) +MAT *old,*new; +unsigned int row1,col1,row2,col2; +#else +MAT *sub_mat(const MAT *old, + unsigned int row1, unsigned int col1, + unsigned int row2, unsigned int col2, + MAT *new) +#endif +{ + unsigned int i; + + if ( old==(MAT *)NULL ) + error(E_NULL,"sub_mat"); + if ( row1 > row2 || col1 > col2 || row2 >= old->m || col2 >= old->n ) + error(E_RANGE,"sub_mat"); + if ( new==(MAT *)NULL || new->m < row2-row1+1 ) + { + new = NEW(MAT); + new->me = NEW_A(row2-row1+1,Real *); + if ( new==(MAT *)NULL || new->me==(Real **)NULL ) + error(E_MEM,"sub_mat"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_MAT,0,sizeof(MAT)+ + (row2-row1+1)*sizeof(Real *)); + } + + } + new->m = row2-row1+1; + + new->n = col2-col1+1; + + new->base = (Real *)NULL; + + for ( i=0; i < new->m; i++ ) + new->me[i] = (old->me[i+row1]) + col1; + + return (new); +} + + +/* sub_vec -- returns sub-vector which is formed by the elements i1 to i2 + -- as for sub_mat, storage is shared */ +#ifndef ANSI_C +VEC *sub_vec(old,i1,i2,new) +VEC *old, *new; +int i1, i2; +#else +VEC *sub_vec(const VEC *old, int i1, int i2, VEC *new) +#endif +{ + if ( old == (VEC *)NULL ) + error(E_NULL,"sub_vec"); + if ( i1 > i2 || old->dim < i2 ) + error(E_RANGE,"sub_vec"); + + if ( new == (VEC *)NULL ) + new = NEW(VEC); + if ( new == (VEC *)NULL ) + error(E_MEM,"sub_vec"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_VEC,0,sizeof(VEC)); + } + + + new->dim = i2 - i1 + 1; + new->ve = &(old->ve[i1]); + + return new; +} diff --git a/svd.c b/svd.c new file mode 100644 index 0000000..0e40e0f --- /dev/null +++ b/svd.c @@ -0,0 +1,433 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File containing routines for computing the SVD of matrices +*/ + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +static char rcsid[] = "$Id: svd.c,v 1.7 1995/09/08 14:45:43 des Exp $"; + + + +#define sgn(x) ((x) >= 0 ? 1 : -1) +#define MAX_STACK 100 + +/* fixsvd -- fix minor details about SVD + -- make singular values non-negative + -- sort singular values in decreasing order + -- variables as for bisvd() + -- no argument checking */ +#ifndef ANSI_C +static void fixsvd(d,U,V) +VEC *d; +MAT *U, *V; +#else +static void fixsvd(VEC *d, MAT *U, MAT *V) +#endif +{ + int i, j, k, l, r, stack[MAX_STACK], sp; + Real tmp, v; + + /* make singular values non-negative */ + for ( i = 0; i < d->dim; i++ ) + if ( d->ve[i] < 0.0 ) + { + d->ve[i] = - d->ve[i]; + if ( U != MNULL ) + for ( j = 0; j < U->m; j++ ) + U->me[i][j] = - U->me[i][j]; + } + + /* sort singular values */ + /* nonrecursive implementation of quicksort due to R.Sedgewick, + "Algorithms in C", p. 122 (1990) */ + sp = -1; + l = 0; r = d->dim - 1; + for ( ; ; ) + { + while ( r > l ) + { + /* i = partition(d->ve,l,r) */ + v = d->ve[r]; + + i = l - 1; j = r; + for ( ; ; ) + { /* inequalities are "backwards" for **decreasing** order */ + while ( d->ve[++i] > v ) + ; + while ( d->ve[--j] < v ) + ; + if ( i >= j ) + break; + /* swap entries in d->ve */ + tmp = d->ve[i]; d->ve[i] = d->ve[j]; d->ve[j] = tmp; + /* swap rows of U & V as well */ + if ( U != MNULL ) + for ( k = 0; k < U->n; k++ ) + { + tmp = U->me[i][k]; + U->me[i][k] = U->me[j][k]; + U->me[j][k] = tmp; + } + if ( V != MNULL ) + for ( k = 0; k < V->n; k++ ) + { + tmp = V->me[i][k]; + V->me[i][k] = V->me[j][k]; + V->me[j][k] = tmp; + } + } + tmp = d->ve[i]; d->ve[i] = d->ve[r]; d->ve[r] = tmp; + if ( U != MNULL ) + for ( k = 0; k < U->n; k++ ) + { + tmp = U->me[i][k]; + U->me[i][k] = U->me[r][k]; + U->me[r][k] = tmp; + } + if ( V != MNULL ) + for ( k = 0; k < V->n; k++ ) + { + tmp = V->me[i][k]; + V->me[i][k] = V->me[r][k]; + V->me[r][k] = tmp; + } + /* end i = partition(...) */ + if ( i - l > r - i ) + { stack[++sp] = l; stack[++sp] = i-1; l = i+1; } + else + { stack[++sp] = i+1; stack[++sp] = r; r = i-1; } + } + if ( sp < 0 ) + break; + r = stack[sp--]; l = stack[sp--]; + } +} + + +/* bisvd -- svd of a bidiagonal m x n matrix represented by d (diagonal) and + f (super-diagonals) + -- returns with d set to the singular values, f zeroed + -- if U, V non-NULL, the orthogonal operations are accumulated + in U, V; if U, V == I on entry, then SVD == U^T.A.V + where A is initial matrix + -- returns d on exit */ +#ifndef ANSI_C +VEC *bisvd(d,f,U,V) +VEC *d, *f; +MAT *U, *V; +#else +VEC *bisvd(VEC *d, VEC *f, MAT *U, MAT *V) +#endif +{ + int i, j, n; + int i_min, i_max, split; + Real c, s, shift, size, z; + Real d_tmp, diff, t11, t12, t22, *d_ve, *f_ve; + + if ( ! d || ! f ) + error(E_NULL,"bisvd"); + if ( d->dim != f->dim + 1 ) + error(E_SIZES,"bisvd"); + n = d->dim; + if ( ( U && U->n < n ) || ( V && V->m < n ) ) + error(E_SIZES,"bisvd"); + if ( ( U && U->m != U->n ) || ( V && V->m != V->n ) ) + error(E_SQUARE,"bisvd"); + + + if ( n == 1 ) + { + if ( d->ve[0] < 0.0 ) + { + d->ve[0] = - d->ve[0]; + if ( U != MNULL ) + sm_mlt(-1.0,U,U); + } + return d; + } + d_ve = d->ve; f_ve = f->ve; + + size = v_norm_inf(d) + v_norm_inf(f); + + i_min = 0; + while ( i_min < n ) /* outer while loop */ + { + /* find i_max to suit; + submatrix i_min..i_max should be irreducible */ + i_max = n - 1; + for ( i = i_min; i < n - 1; i++ ) + if ( d_ve[i] == 0.0 || f_ve[i] == 0.0 ) + { i_max = i; + if ( f_ve[i] != 0.0 ) + { + /* have to ``chase'' f[i] element out of matrix */ + z = f_ve[i]; f_ve[i] = 0.0; + for ( j = i; j < n-1 && z != 0.0; j++ ) + { + givens(d_ve[j+1],z, &c, &s); + s = -s; + d_ve[j+1] = c*d_ve[j+1] - s*z; + if ( j+1 < n-1 ) + { + z = s*f_ve[j+1]; + f_ve[j+1] = c*f_ve[j+1]; + } + if ( U ) + rot_rows(U,i,j+1,c,s,U); + } + } + break; + } + if ( i_max <= i_min ) + { + i_min = i_max + 1; + continue; + } + /* printf("bisvd: i_min = %d, i_max = %d\n",i_min,i_max); */ + + split = FALSE; + while ( ! split ) + { + /* compute shift */ + t11 = d_ve[i_max-1]*d_ve[i_max-1] + + (i_max > i_min+1 ? f_ve[i_max-2]*f_ve[i_max-2] : 0.0); + t12 = d_ve[i_max-1]*f_ve[i_max-1]; + t22 = d_ve[i_max]*d_ve[i_max] + f_ve[i_max-1]*f_ve[i_max-1]; + /* use e-val of [[t11,t12],[t12,t22]] matrix + closest to t22 */ + diff = (t11-t22)/2; + shift = t22 - t12*t12/(diff + + sgn(diff)*sqrt(diff*diff+t12*t12)); + + /* initial Givens' rotation */ + givens(d_ve[i_min]*d_ve[i_min]-shift, + d_ve[i_min]*f_ve[i_min], &c, &s); + + /* do initial Givens' rotations */ + d_tmp = c*d_ve[i_min] + s*f_ve[i_min]; + f_ve[i_min] = c*f_ve[i_min] - s*d_ve[i_min]; + d_ve[i_min] = d_tmp; + z = s*d_ve[i_min+1]; + d_ve[i_min+1] = c*d_ve[i_min+1]; + if ( V ) + rot_rows(V,i_min,i_min+1,c,s,V); + /* 2nd Givens' rotation */ + givens(d_ve[i_min],z, &c, &s); + d_ve[i_min] = c*d_ve[i_min] + s*z; + d_tmp = c*d_ve[i_min+1] - s*f_ve[i_min]; + f_ve[i_min] = s*d_ve[i_min+1] + c*f_ve[i_min]; + d_ve[i_min+1] = d_tmp; + if ( i_min+1 < i_max ) + { + z = s*f_ve[i_min+1]; + f_ve[i_min+1] = c*f_ve[i_min+1]; + } + if ( U ) + rot_rows(U,i_min,i_min+1,c,s,U); + + for ( i = i_min+1; i < i_max; i++ ) + { + /* get Givens' rotation for zeroing z */ + givens(f_ve[i-1],z, &c, &s); + f_ve[i-1] = c*f_ve[i-1] + s*z; + d_tmp = c*d_ve[i] + s*f_ve[i]; + f_ve[i] = c*f_ve[i] - s*d_ve[i]; + d_ve[i] = d_tmp; + z = s*d_ve[i+1]; + d_ve[i+1] = c*d_ve[i+1]; + if ( V ) + rot_rows(V,i,i+1,c,s,V); + /* get 2nd Givens' rotation */ + givens(d_ve[i],z, &c, &s); + d_ve[i] = c*d_ve[i] + s*z; + d_tmp = c*d_ve[i+1] - s*f_ve[i]; + f_ve[i] = c*f_ve[i] + s*d_ve[i+1]; + d_ve[i+1] = d_tmp; + if ( i+1 < i_max ) + { + z = s*f_ve[i+1]; + f_ve[i+1] = c*f_ve[i+1]; + } + if ( U ) + rot_rows(U,i,i+1,c,s,U); + } + /* should matrix be split? */ + for ( i = i_min; i < i_max; i++ ) + if ( fabs(f_ve[i]) < + MACHEPS*(fabs(d_ve[i])+fabs(d_ve[i+1])) ) + { + split = TRUE; + f_ve[i] = 0.0; + } + else if ( fabs(d_ve[i]) < MACHEPS*size ) + { + split = TRUE; + d_ve[i] = 0.0; + } + /* printf("bisvd: d =\n"); v_output(d); */ + /* printf("bisvd: f = \n"); v_output(f); */ + } + } + fixsvd(d,U,V); + + return d; +} + +/* bifactor -- perform preliminary factorisation for bisvd + -- updates U and/or V, which ever is not NULL */ +#ifndef ANSI_C +MAT *bifactor(A,U,V) +MAT *A, *U, *V; +#else +MAT *bifactor(MAT *A, MAT *U, MAT *V) +#endif +{ + int k; + STATIC VEC *tmp1=VNULL, *tmp2=VNULL, *w=VNULL; + Real beta; + + if ( ! A ) + error(E_NULL,"bifactor"); + if ( ( U && ( U->m != U->n ) ) || ( V && ( V->m != V->n ) ) ) + error(E_SQUARE,"bifactor"); + if ( ( U && U->m != A->m ) || ( V && V->m != A->n ) ) + error(E_SIZES,"bifactor"); + tmp1 = v_resize(tmp1,A->m); + tmp2 = v_resize(tmp2,A->n); + w = v_resize(w, max(A->m,A->n)); + MEM_STAT_REG(tmp1,TYPE_VEC); + MEM_STAT_REG(tmp2,TYPE_VEC); + MEM_STAT_REG(w, TYPE_VEC); + + if ( A->m >= A->n ) + for ( k = 0; k < A->n; k++ ) + { + get_col(A,k,tmp1); + hhvec(tmp1,k,&beta,tmp1,&(A->me[k][k])); + _hhtrcols(A,k,k+1,tmp1,beta,w); + if ( U ) + _hhtrcols(U,k,0,tmp1,beta,w); + if ( k+1 >= A->n ) + continue; + get_row(A,k,tmp2); + hhvec(tmp2,k+1,&beta,tmp2,&(A->me[k][k+1])); + hhtrrows(A,k+1,k+1,tmp2,beta); + if ( V ) + _hhtrcols(V,k+1,0,tmp2,beta,w); + } + else + for ( k = 0; k < A->m; k++ ) + { + get_row(A,k,tmp2); + hhvec(tmp2,k,&beta,tmp2,&(A->me[k][k])); + hhtrrows(A,k+1,k,tmp2,beta); + if ( V ) + _hhtrcols(V,k,0,tmp2,beta,w); + if ( k+1 >= A->m ) + continue; + get_col(A,k,tmp1); + hhvec(tmp1,k+1,&beta,tmp1,&(A->me[k+1][k])); + _hhtrcols(A,k+1,k+1,tmp1,beta,w); + if ( U ) + _hhtrcols(U,k+1,0,tmp1,beta,w); + } + +#ifdef THREADSAFE + V_FREE(tmp1); V_FREE(tmp2); +#endif + + return A; +} + +/* svd -- returns vector of singular values in d + -- also updates U and/or V, if one or the other is non-NULL + -- destroys A */ +#ifndef ANSI_C +VEC *svd(A,U,V,d) +MAT *A, *U, *V; +VEC *d; +#else +VEC *svd(MAT *A, MAT *U, MAT *V, VEC *d) +#endif +{ + STATIC VEC *f=VNULL; + int i, limit; + MAT *A_tmp; + + if ( ! A ) + error(E_NULL,"svd"); + if ( ( U && ( U->m != U->n ) ) || ( V && ( V->m != V->n ) ) ) + error(E_SQUARE,"svd"); + if ( ( U && U->m != A->m ) || ( V && V->m != A->n ) ) + error(E_SIZES,"svd"); + + A_tmp = m_copy(A,MNULL); + if ( U != MNULL ) + m_ident(U); + if ( V != MNULL ) + m_ident(V); + limit = min(A_tmp->m,A_tmp->n); + d = v_resize(d,limit); + f = v_resize(f,limit-1); + MEM_STAT_REG(f,TYPE_VEC); + + bifactor(A_tmp,U,V); + if ( A_tmp->m >= A_tmp->n ) + for ( i = 0; i < limit; i++ ) + { + d->ve[i] = A_tmp->me[i][i]; + if ( i+1 < limit ) + f->ve[i] = A_tmp->me[i][i+1]; + } + else + for ( i = 0; i < limit; i++ ) + { + d->ve[i] = A_tmp->me[i][i]; + if ( i+1 < limit ) + f->ve[i] = A_tmp->me[i+1][i]; + } + + + if ( A_tmp->m >= A_tmp->n ) + bisvd(d,f,U,V); + else + bisvd(d,f,V,U); + + M_FREE(A_tmp); +#ifdef THREADSAFE + V_FREE(f); +#endif + + return d; +} + diff --git a/symmeig.c b/symmeig.c new file mode 100644 index 0000000..0169e55 --- /dev/null +++ b/symmeig.c @@ -0,0 +1,223 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File containing routines for symmetric eigenvalue problems +*/ + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + +static char rcsid[] = "$Id: symmeig.c,v 1.6 1995/03/27 15:45:55 des Exp $"; + + + +#define SQRT2 1.4142135623730949 +#define sgn(x) ( (x) >= 0 ? 1 : -1 ) + +/* trieig -- finds eigenvalues of symmetric tridiagonal matrices + -- matrix represented by a pair of vectors a (diag entries) + and b (sub- & super-diag entries) + -- eigenvalues in a on return */ +#ifndef ANSI_C +VEC *trieig(a,b,Q) +VEC *a, *b; +MAT *Q; +#else +VEC *trieig(VEC *a, VEC *b, MAT *Q) +#endif +{ + int i, i_min, i_max, n, split; + Real *a_ve, *b_ve; + Real b_sqr, bk, ak1, bk1, ak2, bk2, z; + Real c, c2, cs, s, s2, d, mu; + + if ( ! a || ! b ) + error(E_NULL,"trieig"); + if ( a->dim != b->dim + 1 || ( Q && Q->m != a->dim ) ) + error(E_SIZES,"trieig"); + if ( Q && Q->m != Q->n ) + error(E_SQUARE,"trieig"); + + n = a->dim; + a_ve = a->ve; b_ve = b->ve; + + i_min = 0; + while ( i_min < n ) /* outer while loop */ + { + /* find i_max to suit; + submatrix i_min..i_max should be irreducible */ + i_max = n-1; + for ( i = i_min; i < n-1; i++ ) + if ( b_ve[i] == 0.0 ) + { i_max = i; break; } + if ( i_max <= i_min ) + { + /* printf("# i_min = %d, i_max = %d\n",i_min,i_max); */ + i_min = i_max + 1; + continue; /* outer while loop */ + } + + /* printf("# i_min = %d, i_max = %d\n",i_min,i_max); */ + + /* repeatedly perform QR method until matrix splits */ + split = FALSE; + while ( ! split ) /* inner while loop */ + { + + /* find Wilkinson shift */ + d = (a_ve[i_max-1] - a_ve[i_max])/2; + b_sqr = b_ve[i_max-1]*b_ve[i_max-1]; + mu = a_ve[i_max] - b_sqr/(d + sgn(d)*sqrt(d*d+b_sqr)); + /* printf("# Wilkinson shift = %g\n",mu); */ + + /* initial Givens' rotation */ + givens(a_ve[i_min]-mu,b_ve[i_min],&c,&s); + s = -s; + /* printf("# c = %g, s = %g\n",c,s); */ + if ( fabs(c) < SQRT2 ) + { c2 = c*c; s2 = 1-c2; } + else + { s2 = s*s; c2 = 1-s2; } + cs = c*s; + ak1 = c2*a_ve[i_min]+s2*a_ve[i_min+1]-2*cs*b_ve[i_min]; + bk1 = cs*(a_ve[i_min]-a_ve[i_min+1]) + + (c2-s2)*b_ve[i_min]; + ak2 = s2*a_ve[i_min]+c2*a_ve[i_min+1]+2*cs*b_ve[i_min]; + bk2 = ( i_min < i_max-1 ) ? c*b_ve[i_min+1] : 0.0; + z = ( i_min < i_max-1 ) ? -s*b_ve[i_min+1] : 0.0; + a_ve[i_min] = ak1; + a_ve[i_min+1] = ak2; + b_ve[i_min] = bk1; + if ( i_min < i_max-1 ) + b_ve[i_min+1] = bk2; + if ( Q ) + rot_cols(Q,i_min,i_min+1,c,-s,Q); + /* printf("# z = %g\n",z); */ + /* printf("# a [temp1] =\n"); v_output(a); */ + /* printf("# b [temp1] =\n"); v_output(b); */ + + for ( i = i_min+1; i < i_max; i++ ) + { + /* get Givens' rotation for sub-block -- k == i-1 */ + givens(b_ve[i-1],z,&c,&s); + s = -s; + /* printf("# c = %g, s = %g\n",c,s); */ + + /* perform Givens' rotation on sub-block */ + if ( fabs(c) < SQRT2 ) + { c2 = c*c; s2 = 1-c2; } + else + { s2 = s*s; c2 = 1-s2; } + cs = c*s; + bk = c*b_ve[i-1] - s*z; + ak1 = c2*a_ve[i]+s2*a_ve[i+1]-2*cs*b_ve[i]; + bk1 = cs*(a_ve[i]-a_ve[i+1]) + + (c2-s2)*b_ve[i]; + ak2 = s2*a_ve[i]+c2*a_ve[i+1]+2*cs*b_ve[i]; + bk2 = ( i+1 < i_max ) ? c*b_ve[i+1] : 0.0; + z = ( i+1 < i_max ) ? -s*b_ve[i+1] : 0.0; + a_ve[i] = ak1; a_ve[i+1] = ak2; + b_ve[i] = bk1; + if ( i < i_max-1 ) + b_ve[i+1] = bk2; + if ( i > i_min ) + b_ve[i-1] = bk; + if ( Q ) + rot_cols(Q,i,i+1,c,-s,Q); + /* printf("# a [temp2] =\n"); v_output(a); */ + /* printf("# b [temp2] =\n"); v_output(b); */ + } + + /* test to see if matrix should be split */ + for ( i = i_min; i < i_max; i++ ) + if ( fabs(b_ve[i]) < MACHEPS* + (fabs(a_ve[i])+fabs(a_ve[i+1])) ) + { b_ve[i] = 0.0; split = TRUE; } + + /* printf("# a =\n"); v_output(a); */ + /* printf("# b =\n"); v_output(b); */ + } + } + + return a; +} + +/* symmeig -- computes eigenvalues of a dense symmetric matrix + -- A **must** be symmetric on entry + -- eigenvalues stored in out + -- Q contains orthogonal matrix of eigenvectors + -- returns vector of eigenvalues */ +#ifndef ANSI_C +VEC *symmeig(A,Q,out) +MAT *A, *Q; +VEC *out; +#else +VEC *symmeig(const MAT *A, MAT *Q, VEC *out) +#endif +{ + int i; + STATIC MAT *tmp = MNULL; + STATIC VEC *b = VNULL, *diag = VNULL, *beta = VNULL; + + if ( ! A ) + error(E_NULL,"symmeig"); + if ( A->m != A->n ) + error(E_SQUARE,"symmeig"); + if ( ! out || out->dim != A->m ) + out = v_resize(out,A->m); + + tmp = m_resize(tmp,A->m,A->n); + tmp = m_copy(A,tmp); + b = v_resize(b,A->m - 1); + diag = v_resize(diag,(unsigned int)A->m); + beta = v_resize(beta,(unsigned int)A->m); + MEM_STAT_REG(tmp,TYPE_MAT); + MEM_STAT_REG(b,TYPE_VEC); + MEM_STAT_REG(diag,TYPE_VEC); + MEM_STAT_REG(beta,TYPE_VEC); + + Hfactor(tmp,diag,beta); + if ( Q ) + makeHQ(tmp,diag,beta,Q); + + for ( i = 0; i < A->m - 1; i++ ) + { + out->ve[i] = tmp->me[i][i]; + b->ve[i] = tmp->me[i][i+1]; + } + out->ve[i] = tmp->me[i][i]; + trieig(out,b,Q); + +#ifdef THREADSAFE + M_FREE(tmp); V_FREE(b); V_FREE(diag); V_FREE(beta); +#endif + return out; +} + diff --git a/torture.c b/torture.c new file mode 100644 index 0000000..44ade1d --- /dev/null +++ b/torture.c @@ -0,0 +1,1052 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + This file contains a series of tests for the Meschach matrix + library, parts 1 and 2 +*/ + +static char rcsid[] = "$Id: torture.c,v 1.6 1994/08/25 15:22:11 des Exp $"; + +#include +#include +#include "matrix2.h" +#include "matlab.h" + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + +static char *test_err_list[] = { + "unknown error", /* 0 */ + "testing error messages", /* 1 */ + "unexpected end-of-file" /* 2 */ +}; + + +#define MAX_TEST_ERR (sizeof(test_err_list)/sizeof(char *)) + +/* extern int malloc_chain_check(); */ +/* #define MEMCHK() if ( malloc_chain_check(0) ) \ +{ printf("Error in malloc chain: \"%s\", line %d\n", \ + __FILE__, __LINE__); exit(0); } */ +#define MEMCHK() + +/* cmp_perm -- returns 1 if pi1 == pi2, 0 otherwise */ +int cmp_perm(pi1, pi2) +PERM *pi1, *pi2; +{ + int i; + + if ( ! pi1 || ! pi2 ) + error(E_NULL,"cmp_perm"); + if ( pi1->size != pi2->size ) + return 0; + for ( i = 0; i < pi1->size; i++ ) + if ( pi1->pe[i] != pi2->pe[i] ) + return 0; + return 1; +} + +/* px_rand -- generates sort-of random permutation */ +PERM *px_rand(pi) +PERM *pi; +{ + int i, j, k; + + if ( ! pi ) + error(E_NULL,"px_rand"); + + for ( i = 0; i < 3*pi->size; i++ ) + { + j = (rand() >> 8) % pi->size; + k = (rand() >> 8) % pi->size; + px_transp(pi,j,k); + } + + return pi; +} + +#define SAVE_FILE "asx5213a.mat" +#define MATLAB_NAME "alpha" +char name[81] = MATLAB_NAME; + +int main(argc, argv) +int argc; +char *argv[]; +{ + VEC *x = VNULL, *y = VNULL, *z = VNULL, *u = VNULL, *v = VNULL, + *w = VNULL; + VEC *diag = VNULL, *beta = VNULL; + PERM *pi1 = PNULL, *pi2 = PNULL, *pi3 = PNULL, *pivot = PNULL, + *blocks = PNULL; + MAT *A = MNULL, *B = MNULL, *C = MNULL, *D = MNULL, *Q = MNULL, + *U = MNULL; + BAND *bA, *bB, *bC; + Real cond_est, s1, s2, s3; + int i, j, seed; + FILE *fp; + char *cp; + + + mem_info_on(TRUE); + + setbuf(stdout,(char *)NULL); + + seed = 1111; + if ( argc > 2 ) + { + printf("usage: %s [seed]\n",argv[0]); + exit(0); + } + else if ( argc == 2 ) + sscanf(argv[1], "%d", &seed); + + /* set seed for rand() */ + smrand(seed); + + mem_stat_mark(1); + + /* print version information */ + m_version(); + + printf("# grep \"^Error\" the output for a listing of errors\n"); + printf("# Don't panic if you see \"Error\" appearing; \n"); + printf("# Also check the reported size of error\n"); + printf("# This program uses randomly generated problems and therefore\n"); + printf("# may occasionally produce ill-conditioned problems\n"); + printf("# Therefore check the size of the error compared with MACHEPS\n"); + printf("# If the error is within 1000*MACHEPS then don't worry\n"); + printf("# If you get an error of size 0.1 or larger there is \n"); + printf("# probably a bug in the code or the compilation procedure\n\n"); + printf("# seed = %d\n",seed); + + printf("# Check: MACHEPS = %g\n",MACHEPS); + /* allocate, initialise, copy and resize operations */ + /* VEC */ + notice("vector initialise, copy & resize"); + x = v_get(12); + y = v_get(15); + z = v_get(12); + v_rand(x); + v_rand(y); + z = v_copy(x,z); + if ( v_norm2(v_sub(x,z,z)) >= MACHEPS ) + errmesg("VEC copy"); + v_copy(x,y); + x = v_resize(x,10); + y = v_resize(y,10); + if ( v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("VEC copy/resize"); + x = v_resize(x,15); + y = v_resize(y,15); + if ( v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("VEC resize"); + + /* MAT */ + notice("matrix initialise, copy & resize"); + A = m_get(8,5); + B = m_get(3,9); + C = m_get(8,5); + m_rand(A); + m_rand(B); + C = m_copy(A,C); + if ( m_norm_inf(m_sub(A,C,C)) >= MACHEPS ) + errmesg("MAT copy"); + m_copy(A,B); + A = m_resize(A,3,5); + B = m_resize(B,3,5); + if ( m_norm_inf(m_sub(A,B,C)) >= MACHEPS ) + errmesg("MAT copy/resize"); + A = m_resize(A,10,10); + B = m_resize(B,10,10); + if ( m_norm_inf(m_sub(A,B,C)) >= MACHEPS ) + errmesg("MAT resize"); + + MEMCHK(); + + /* PERM */ + notice("permutation initialise, inverting & permuting vectors"); + pi1 = px_get(15); + pi2 = px_get(12); + px_rand(pi1); + v_rand(x); + px_vec(pi1,x,z); + y = v_resize(y,x->dim); + pxinv_vec(pi1,z,y); + if ( v_norm2(v_sub(x,y,z)) >= MACHEPS ) + errmesg("PERMute vector"); + pi2 = px_inv(pi1,pi2); + pi3 = px_mlt(pi1,pi2,PNULL); + for ( i = 0; i < pi3->size; i++ ) + if ( pi3->pe[i] != i ) + errmesg("PERM inverse/multiply"); + + /* testing catch() etc */ + notice("error handling routines"); + catch(E_NULL, + catchall(v_add(VNULL,VNULL,VNULL); + errmesg("tracecatch() failure"), + printf("# tracecatch() caught error\n"); + error(E_NULL,"main")); + errmesg("catch() failure"), + printf("# catch() caught E_NULL error\n")); + + /* testing attaching a new error list (error list 2) */ + + notice("attaching error lists"); + printf("# IT IS NOT A REAL WARNING ... \n"); + err_list_attach(2,MAX_TEST_ERR,test_err_list,TRUE); + if (!err_is_list_attached(2)) + errmesg("attaching the error list 2"); + ev_err(__FILE__,1,__LINE__,"main",2); + err_list_free(2); + if (err_is_list_attached(2)) + errmesg("detaching the error list 2"); + + /* testing inner products and v_mltadd() etc */ + notice("inner products and linear combinations"); + u = v_get(x->dim); + v_rand(u); + v_rand(x); + v_resize(y,x->dim); + v_rand(y); + v_mltadd(y,x,-in_prod(x,y)/in_prod(x,x),z); + if ( fabs(in_prod(x,z)) >= MACHEPS*x->dim ) + errmesg("v_mltadd()/in_prod()"); + s1 = -in_prod(x,y)/(v_norm2(x)*v_norm2(x)); + sv_mlt(s1,x,u); + v_add(y,u,u); + if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim ) + errmesg("sv_mlt()/v_norm2()"); + +#ifdef ANSI_C + v_linlist(u,x,s1,y,1.0,VNULL); + if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim ) + errmesg("v_linlist()"); +#endif +#ifdef VARARGS + v_linlist(u,x,s1,y,1.0,VNULL); + if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim ) + errmesg("v_linlist()"); +#endif + + + MEMCHK(); + + /* vector norms */ + notice("vector norms"); + x = v_resize(x,12); + v_rand(x); + for ( i = 0; i < x->dim; i++ ) + if ( v_entry(x,i) >= 0.5 ) + v_set_val(x,i,1.0); + else + v_set_val(x,i,-1.0); + s1 = v_norm1(x); + s2 = v_norm2(x); + s3 = v_norm_inf(x); + if ( fabs(s1 - x->dim) >= MACHEPS*x->dim || + fabs(s2 - sqrt((Real)(x->dim))) >= MACHEPS*x->dim || + fabs(s3 - 1.0) >= MACHEPS ) + errmesg("v_norm1/2/_inf()"); + + /* test matrix multiply etc */ + notice("matrix multiply and invert"); + A = m_resize(A,10,10); + B = m_resize(B,10,10); + m_rand(A); + m_inverse(A,B); + m_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + m_set_val(C,i,i,m_entry(C,i,i)-1.0); + if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("m_inverse()/m_mlt()"); + + MEMCHK(); + + /* ... and transposes */ + notice("transposes and transpose-multiplies"); + m_transp(A,A); /* can do square matrices in situ */ + mtrm_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + m_set_val(C,i,i,m_entry(C,i,i)-1.0); + if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("m_transp()/mtrm_mlt()"); + m_transp(A,A); + m_transp(B,B); + mmtr_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + m_set_val(C,i,i,m_entry(C,i,i)-1.0); + if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("m_transp()/mmtr_mlt()"); + sm_mlt(3.71,B,B); + mmtr_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + m_set_val(C,i,i,m_entry(C,i,i)-3.71); + if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("sm_mlt()/mmtr_mlt()"); + m_transp(B,B); + sm_mlt(1.0/3.71,B,B); + + MEMCHK(); + + /* ... and matrix-vector multiplies */ + notice("matrix-vector multiplies"); + x = v_resize(x,A->n); + y = v_resize(y,A->m); + z = v_resize(z,A->m); + u = v_resize(u,A->n); + v_rand(x); + v_rand(y); + mv_mlt(A,x,z); + s1 = in_prod(y,z); + vm_mlt(A,y,u); + s2 = in_prod(u,x); + if ( fabs(s1 - s2) >= (MACHEPS*x->dim)*x->dim ) + errmesg("mv_mlt()/vm_mlt()"); + mv_mlt(B,z,u); + if ( v_norm2(v_sub(u,x,u)) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("mv_mlt()/m_inverse()"); + + MEMCHK(); + + /* get/set row/col */ + notice("getting and setting rows and cols"); + x = v_resize(x,A->n); + y = v_resize(y,B->m); + x = get_row(A,3,x); + y = get_col(B,3,y); + if ( fabs(in_prod(x,y) - 1.0) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("get_row()/get_col()"); + sv_mlt(-1.0,x,x); + sv_mlt(-1.0,y,y); + set_row(A,3,x); + set_col(B,3,y); + m_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + m_set_val(C,i,i,m_entry(C,i,i)-1.0); + if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 ) + errmesg("set_row()/set_col()"); + + MEMCHK(); + + /* matrix norms */ + notice("matrix norms"); + A = m_resize(A,11,15); + m_rand(A); + s1 = m_norm_inf(A); + B = m_transp(A,B); + s2 = m_norm1(B); + if ( fabs(s1 - s2) >= MACHEPS*A->m ) + errmesg("m_norm1()/m_norm_inf()"); + C = mtrm_mlt(A,A,C); + s1 = 0.0; + for ( i = 0; i < C->m && i < C->n; i++ ) + s1 += m_entry(C,i,i); + if ( fabs(sqrt(s1) - m_norm_frob(A)) >= MACHEPS*A->m*A->n ) + errmesg("m_norm_frob"); + + MEMCHK(); + + /* permuting rows and columns */ + notice("permuting rows & cols"); + A = m_resize(A,11,15); + B = m_resize(B,11,15); + pi1 = px_resize(pi1,A->m); + px_rand(pi1); + x = v_resize(x,A->n); + y = mv_mlt(A,x,y); + px_rows(pi1,A,B); + px_vec(pi1,y,z); + mv_mlt(B,x,u); + if ( v_norm2(v_sub(z,u,u)) >= MACHEPS*A->m ) + errmesg("px_rows()"); + pi1 = px_resize(pi1,A->n); + px_rand(pi1); + px_cols(pi1,A,B); + pxinv_vec(pi1,x,z); + mv_mlt(B,z,u); + if ( v_norm2(v_sub(y,u,u)) >= MACHEPS*A->n ) + errmesg("px_cols()"); + + MEMCHK(); + + /* MATLAB save/load */ + notice("MATLAB save/load"); + A = m_resize(A,12,11); + if ( (fp=fopen(SAVE_FILE,"w")) == (FILE *)NULL ) + printf("Cannot perform MATLAB save/load test\n"); + else + { + m_rand(A); + m_save(fp, A, name); + fclose(fp); + if ( (fp=fopen(SAVE_FILE,"r")) == (FILE *)NULL ) + printf("Cannot open save file \"%s\"\n",SAVE_FILE); + else + { + M_FREE(B); + B = m_load(fp,&cp); + if ( strcmp(name,cp) || m_norm1(m_sub(A,B,B)) >= MACHEPS*A->m ) + errmesg("mload()/m_save()"); + } + } + + MEMCHK(); + + /* Now, onto matrix factorisations */ + A = m_resize(A,10,10); + B = m_resize(B,A->m,A->n); + m_copy(A,B); + x = v_resize(x,A->n); + y = v_resize(y,A->m); + z = v_resize(z,A->n); + u = v_resize(u,A->m); + v_rand(x); + mv_mlt(B,x,y); + z = v_copy(x,z); + + notice("LU factor/solve"); + pivot = px_get(A->m); + LUfactor(A,pivot); + tracecatch(LUsolve(A,pivot,y,x),"main"); + tracecatch(cond_est = LUcondest(A,pivot),"main"); + printf("# cond(A) approx= %g\n", cond_est); + if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est) + { + errmesg("LUfactor()/LUsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + v_norm2(v_sub(x,z,u)), MACHEPS); + } + + v_copy(y,x); + tracecatch(LUsolve(A,pivot,x,x),"main"); + tracecatch(cond_est = LUcondest(A,pivot),"main"); + if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est) + { + errmesg("LUfactor()/LUsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + v_norm2(v_sub(x,z,u)), MACHEPS); + } + + vm_mlt(B,z,y); + v_copy(y,x); + tracecatch(LUTsolve(A,pivot,x,x),"main"); + if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est) + { + errmesg("LUfactor()/LUTsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + v_norm2(v_sub(x,z,u)), MACHEPS); + } + + MEMCHK(); + + /* QR factorisation */ + m_copy(B,A); + mv_mlt(B,z,y); + notice("QR factor/solve:"); + diag = v_get(A->m); + beta = v_get(A->m); + QRfactor(A,diag); + QRsolve(A,diag,y,x); + if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est ) + { + errmesg("QRfactor()/QRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + v_norm2(v_sub(x,z,u)), MACHEPS); + } + Q = m_get(A->m,A->m); + makeQ(A,diag,Q); + makeR(A,A); + m_mlt(Q,A,C); + m_sub(B,C,C); + if ( m_norm1(C) >= MACHEPS*m_norm1(Q)*m_norm1(B) ) + { + errmesg("QRfactor()/makeQ()/makeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(C), MACHEPS); + } + + MEMCHK(); + + /* now try with a non-square matrix */ + A = m_resize(A,15,7); + m_rand(A); + B = m_copy(A,B); + diag = v_resize(diag,A->n); + beta = v_resize(beta,A->n); + x = v_resize(x,A->n); + y = v_resize(y,A->m); + v_rand(y); + QRfactor(A,diag); + x = QRsolve(A,diag,y,x); + /* z is the residual vector */ + mv_mlt(B,x,z); v_sub(z,y,z); + /* check B^T.z = 0 */ + vm_mlt(B,z,u); + if ( v_norm2(u) >= MACHEPS*m_norm1(B)*v_norm2(y) ) + { + errmesg("QRfactor()/QRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + v_norm2(u), MACHEPS); + } + Q = m_resize(Q,A->m,A->m); + makeQ(A,diag,Q); + makeR(A,A); + m_mlt(Q,A,C); + m_sub(B,C,C); + if ( m_norm1(C) >= MACHEPS*m_norm1(Q)*m_norm1(B) ) + { + errmesg("QRfactor()/makeQ()/makeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(C), MACHEPS); + } + D = m_get(A->m,Q->m); + mtrm_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q) ) + { + errmesg("QRfactor()/makeQ()/makeR()"); + printf("# QR orthogonality error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* QRCP factorisation */ + m_copy(B,A); + notice("QR factor/solve with column pivoting"); + pivot = px_resize(pivot,A->n); + QRCPfactor(A,diag,pivot); + z = v_resize(z,A->n); + QRCPsolve(A,diag,pivot,y,z); + /* pxinv_vec(pivot,z,x); */ + /* now compute residual (z) vector */ + mv_mlt(B,x,z); v_sub(z,y,z); + /* check B^T.z = 0 */ + vm_mlt(B,z,u); + if ( v_norm2(u) >= MACHEPS*m_norm1(B)*v_norm2(y) ) + { + errmesg("QRCPfactor()/QRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + v_norm2(u), MACHEPS); + } + + Q = m_resize(Q,A->m,A->m); + makeQ(A,diag,Q); + makeR(A,A); + m_mlt(Q,A,C); + M_FREE(D); + D = m_get(B->m,B->n); + px_cols(pivot,C,D); + m_sub(B,D,D); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm1(B) ) + { + errmesg("QRCPfactor()/makeQ()/makeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* Cholesky and LDL^T factorisation */ + /* Use these for normal equations approach */ + notice("Cholesky factor/solve"); + mtrm_mlt(B,B,A); + CHfactor(A); + u = v_resize(u,B->n); + vm_mlt(B,y,u); + z = v_resize(z,B->n); + CHsolve(A,u,z); + v_sub(x,z,z); + if ( v_norm2(z) >= MACHEPS*v_norm2(x)*100 ) + { + errmesg("CHfactor()/CHsolve()"); + printf("# Cholesky solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + /* modified Cholesky factorisation should be identical with Cholesky + factorisation provided the matrix is "sufficiently positive definite" */ + mtrm_mlt(B,B,C); + MCHfactor(C,MACHEPS); + m_sub(A,C,C); + if ( m_norm1(C) >= MACHEPS*m_norm1(A) ) + { + errmesg("MCHfactor()"); + printf("# Modified Cholesky error = %g [cf MACHEPS = %g]\n", + m_norm1(C), MACHEPS); + } + /* now test the LDL^T factorisation -- using a negative def. matrix */ + mtrm_mlt(B,B,A); + sm_mlt(-1.0,A,A); + m_copy(A,C); + LDLfactor(A); + LDLsolve(A,u,z); + w = v_get(A->m); + mv_mlt(C,z,w); + v_sub(w,u,w); + if ( v_norm2(w) >= MACHEPS*v_norm2(u)*m_norm1(C) ) + { + errmesg("LDLfactor()/LDLsolve()"); + printf("# LDL^T residual = %g [cf MACHEPS = %g]\n", + v_norm2(w), MACHEPS); + } + v_add(x,z,z); + if ( v_norm2(z) >= MACHEPS*v_norm2(x)*100 ) + { + errmesg("LDLfactor()/LDLsolve()"); + printf("# LDL^T solution error = %g [cf MACHEPS = %g]\n", + v_norm2(z), MACHEPS); + } + + MEMCHK(); + + /* and now the Bunch-Kaufman-Parlett method */ + /* set up D to be an indefinite diagonal matrix */ + notice("Bunch-Kaufman-Parlett factor/solve"); + + D = m_resize(D,B->m,B->m); + m_zero(D); + w = v_resize(w,B->m); + v_rand(w); + for ( i = 0; i < w->dim; i++ ) + if ( v_entry(w,i) >= 0.5 ) + m_set_val(D,i,i,1.0); + else + m_set_val(D,i,i,-1.0); + /* set A <- B^T.D.B */ + C = m_resize(C,B->n,B->n); + C = mtrm_mlt(B,D,C); + A = m_mlt(C,B,A); + C = m_resize(C,B->n,B->n); + C = m_copy(A,C); + /* ... and use BKPfactor() */ + blocks = px_get(A->m); + pivot = px_resize(pivot,A->m); + x = v_resize(x,A->m); + y = v_resize(y,A->m); + z = v_resize(z,A->m); + v_rand(x); + mv_mlt(A,x,y); + BKPfactor(A,pivot,blocks); + printf("# BKP pivot =\n"); px_output(pivot); + printf("# BKP blocks =\n"); px_output(blocks); + BKPsolve(A,pivot,blocks,y,z); + /* compute & check residual */ + mv_mlt(C,z,w); + v_sub(w,y,w); + if ( v_norm2(w) >= MACHEPS*m_norm1(C)*v_norm2(z) ) + { + errmesg("BKPfactor()/BKPsolve()"); + printf("# BKP residual size = %g [cf MACHEPS = %g]\n", + v_norm2(w), MACHEPS); + } + + /* check update routines */ + /* check LDLupdate() first */ + notice("update L.D.L^T routine"); + A = mtrm_mlt(B,B,A); + m_resize(C,A->m,A->n); + C = m_copy(A,C); + LDLfactor(A); + s1 = 3.7; + w = v_resize(w,A->m); + v_rand(w); + for ( i = 0; i < C->m; i++ ) + for ( j = 0; j < C->n; j++ ) + m_set_val(C,i,j,m_entry(C,i,j)+s1*v_entry(w,i)*v_entry(w,j)); + LDLfactor(C); + LDLupdate(A,w,s1); + /* zero out strictly upper triangular parts of A and C */ + for ( i = 0; i < A->m; i++ ) + for ( j = i+1; j < A->n; j++ ) + { + m_set_val(A,i,j,0.0); + m_set_val(C,i,j,0.0); + } + if ( m_norm1(m_sub(A,C,C)) >= sqrt(MACHEPS)*m_norm1(A) ) + { + errmesg("LDLupdate()"); + printf("# LDL update matrix error = %g [cf MACHEPS = %g]\n", + m_norm1(C), MACHEPS); + } + + + /* BAND MATRICES */ + +#define COL 40 +#define UDIAG 5 +#define LDIAG 2 + + smrand(101); + bA = bd_get(LDIAG,UDIAG,COL); + bB = bd_get(LDIAG,UDIAG,COL); + bC = bd_get(LDIAG,UDIAG,COL); + A = m_resize(A,COL,COL); + B = m_resize(B,COL,COL); + pivot = px_resize(pivot,COL); + x = v_resize(x,COL); + w = v_resize(w,COL); + z = v_resize(z,COL); + + m_rand(A); + /* generate band matrix */ + mat2band(A,LDIAG,UDIAG,bA); + band2mat(bA,A); /* now A is banded */ + bB = bd_copy(bA,bB); + + v_rand(x); + mv_mlt(A,x,w); + /* test of bd_mv_mlt */ + notice("bd_mv_mlt"); + bd_mv_mlt(bA,x,z); + v_sub(z,w,z); + if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) { + errmesg("incorrect vector (bd_mv_mlt)"); + printf(" ||exact vector. - computed vector.|| = %g [MACHEPS = %g]\n", + v_norm2(z),MACHEPS); + } + + z = v_copy(w,z); + + notice("band LU factorization"); + bdLUfactor(bA,pivot); + + /* pivot will be changed */ + bdLUsolve(bA,pivot,z,z); + v_sub(x,z,z); + if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) { + errmesg("incorrect solution (band LU factorization)"); + printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n", + v_norm2(z),MACHEPS); + } + + /* solve transpose system */ + + notice("band LU factorization for transpose system"); + m_transp(A,B); + mv_mlt(B,x,w); + + bd_copy(bB,bA); + bd_transp(bA,bA); + /* transposition in situ */ + bd_transp(bA,bB); + bd_transp(bB,bB); + + bdLUfactor(bB,pivot); + + bdLUsolve(bB,pivot,w,z); + v_sub(x,z,z); + if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) { + errmesg("incorrect solution (band transposed LU factorization)"); + printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n", + v_norm2(z),MACHEPS); + } + + + /* Cholesky factorization */ + + notice("band Choleski LDL' factorization"); + m_add(A,B,A); /* symmetric matrix */ + for (i=0; i < COL; i++) /* positive definite */ + A->me[i][i] += 2*LDIAG; + + mat2band(A,LDIAG,LDIAG,bA); + band2mat(bA,A); /* corresponding matrix A */ + + v_rand(x); + mv_mlt(A,x,w); + z = v_copy(w,z); + + bdLDLfactor(bA); + + z = bdLDLsolve(bA,z,z); + v_sub(x,z,z); + if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) { + errmesg("incorrect solution (band LDL' factorization)"); + printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n", + v_norm2(z),MACHEPS); + } + + /* new bandwidths */ + m_rand(A); + bA = bd_resize(bA,UDIAG,LDIAG,COL); + bB = bd_resize(bB,UDIAG,LDIAG,COL); + mat2band(A,UDIAG,LDIAG,bA); + band2mat(bA,A); + bd_copy(bA,bB); + + mv_mlt(A,x,w); + + notice("band LU factorization (resized)"); + bdLUfactor(bA,pivot); + + /* pivot will be changed */ + bdLUsolve(bA,pivot,w,z); + v_sub(x,z,z); + if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) { + errmesg("incorrect solution (band LU factorization)"); + printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n", + v_norm2(z),MACHEPS); + } + + /* testing transposition */ + + notice("band matrix transposition"); + m_zero(bA->mat); + bd_copy(bB,bA); + m_zero(bB->mat); + bd_copy(bA,bB); + + bd_transp(bB,bB); + bd_transp(bB,bB); + + m_zero(bC->mat); + bd_copy(bB,bC); + + m_sub(bA->mat,bC->mat,bC->mat); + if (m_norm_inf(bC->mat) > MACHEPS*bC->mat->n) { + errmesg("band transposition"); + printf(" difference ||A - (A')'|| = %g\n",m_norm_inf(bC->mat)); + } + + bd_free(bA); + bd_free(bB); + bd_free(bC); + + + MEMCHK(); + + /* now check QRupdate() routine */ + notice("update QR routine"); + + B = m_resize(B,15,7); + A = m_resize(A,B->m,B->n); + m_copy(B,A); + diag = v_resize(diag,A->n); + beta = v_resize(beta,A->n); + QRfactor(A,diag); + Q = m_resize(Q,A->m,A->m); + makeQ(A,diag,Q); + makeR(A,A); + m_resize(C,A->m,A->n); + w = v_resize(w,A->m); + v = v_resize(v,A->n); + u = v_resize(u,A->m); + v_rand(w); + v_rand(v); + vm_mlt(Q,w,u); + QRupdate(Q,A,u,v); + m_mlt(Q,A,C); + for ( i = 0; i < B->m; i++ ) + for ( j = 0; j < B->n; j++ ) + m_set_val(B,i,j,m_entry(B,i,j)+v_entry(w,i)*v_entry(v,j)); + m_sub(B,C,C); + if ( m_norm1(C) >= MACHEPS*m_norm1(A)*m_norm1(Q)*2 ) + { + errmesg("QRupdate()"); + printf("# Reconstruction error in QR update = %g [cf MACHEPS = %g]\n", + m_norm1(C), MACHEPS); + } + m_resize(D,Q->m,Q->n); + mtrm_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= 10*MACHEPS*m_norm1(Q)*m_norm_inf(Q) ) + { + errmesg("QRupdate()"); + printf("# QR update orthogonality error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + /* Now check eigenvalue/SVD routines */ + notice("eigenvalue and SVD routines"); + A = m_resize(A,11,11); + B = m_resize(B,A->m,A->n); + C = m_resize(C,A->m,A->n); + D = m_resize(D,A->m,A->n); + Q = m_resize(Q,A->m,A->n); + + m_rand(A); + /* A <- A + A^T for symmetric case */ + m_add(A,m_transp(A,C),A); + u = v_resize(u,A->m); + u = symmeig(A,Q,u); + m_zero(B); + for ( i = 0; i < B->m; i++ ) + m_set_val(B,i,i,v_entry(u,i)); + m_mlt(Q,B,C); + mmtr_mlt(C,Q,D); + m_sub(A,D,D); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*v_norm_inf(u)*3 ) + { + errmesg("symmeig()"); + printf("# Reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + mtrm_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*3 ) + { + errmesg("symmeig()"); + printf("# symmeig() orthogonality error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* now test (real) Schur decomposition */ + /* m_copy(A,B); */ + M_FREE(A); + A = m_get(11,11); + m_rand(A); + B = m_copy(A,B); + MEMCHK(); + + B = schur(B,Q); + MEMCHK(); + + m_mlt(Q,B,C); + mmtr_mlt(C,Q,D); + MEMCHK(); + m_sub(A,D,D); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*m_norm1(B)*5 ) + { + errmesg("schur()"); + printf("# Schur reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + /* orthogonality check */ + mmtr_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*10 ) + { + errmesg("schur()"); + printf("# Schur orthogonality error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* now test SVD */ + A = m_resize(A,11,7); + m_rand(A); + U = m_get(A->n,A->n); + Q = m_resize(Q,A->m,A->m); + u = v_resize(u,max(A->m,A->n)); + svd(A,Q,U,u); + /* check reconstruction of A */ + D = m_resize(D,A->m,A->n); + C = m_resize(C,A->m,A->n); + m_zero(D); + for ( i = 0; i < min(A->m,A->n); i++ ) + m_set_val(D,i,i,v_entry(u,i)); + mtrm_mlt(Q,D,C); + m_mlt(C,U,D); + m_sub(A,D,D); + if ( m_norm1(D) >= MACHEPS*m_norm1(U)*m_norm_inf(Q)*m_norm1(A) ) + { + errmesg("svd()"); + printf("# SVD reconstruction error = %g [cf MACHEPS = %g]\n", + m_norm1(D), MACHEPS); + } + /* check orthogonality of Q and U */ + D = m_resize(D,Q->n,Q->n); + mtrm_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*5 ) + { + errmesg("svd()"); + printf("# SVD orthognality error (Q) = %g [cf MACHEPS = %g\n", + m_norm1(D), MACHEPS); + } + D = m_resize(D,U->n,U->n); + mtrm_mlt(U,U,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( m_norm1(D) >= MACHEPS*m_norm1(U)*m_norm_inf(U)*5 ) + { + errmesg("svd()"); + printf("# SVD orthognality error (U) = %g [cf MACHEPS = %g\n", + m_norm1(D), MACHEPS); + } + for ( i = 0; i < u->dim; i++ ) + if ( v_entry(u,i) < 0 || (i < u->dim-1 && + v_entry(u,i+1) > v_entry(u,i)) ) + break; + if ( i < u->dim ) + { + errmesg("svd()"); + printf("# SVD sorting error\n"); + } + + + /* test of long vectors */ + notice("Long vectors"); + x = v_resize(x,100000); + y = v_resize(y,100000); + z = v_resize(z,100000); + v_rand(x); + v_rand(y); + v_mltadd(x,y,3.0,z); + sv_mlt(1.0/3.0,z,z); + v_mltadd(z,x,-1.0/3.0,z); + v_sub(z,y,x); + if (v_norm2(x) >= MACHEPS*(x->dim)) { + errmesg("long vectors"); + printf(" norm = %g\n",v_norm2(x)); + } + + mem_stat_free(1); + + MEMCHK(); + + /************************************************** + VEC *x, *y, *z, *u, *v, *w; + VEC *diag, *beta; + PERM *pi1, *pi2, *pi3, *pivot, *blocks; + MAT *A, *B, *C, *D, *Q, *U; + **************************************************/ + V_FREE(x); V_FREE(y); V_FREE(z); + V_FREE(u); V_FREE(v); V_FREE(w); + V_FREE(diag); V_FREE(beta); + PX_FREE(pi1); PX_FREE(pi2); PX_FREE(pi3); + PX_FREE(pivot); PX_FREE(blocks); + M_FREE(A); M_FREE(B); M_FREE(C); + M_FREE(D); M_FREE(Q); M_FREE(U); + + MEMCHK(); + printf("# Finished torture test\n"); + mem_info(); + + return 0; +} + + diff --git a/tutadv.c b/tutadv.c new file mode 100644 index 0000000..26d7f9d --- /dev/null +++ b/tutadv.c @@ -0,0 +1,192 @@ + +/* routines from the section 8 of tutorial.txt */ + +#include "matrix.h" + +#define M3D_LIST 3 /* list number */ +#define TYPE_MAT3D 0 /* the number of a type */ + +/* type for 3 dimensional matrices */ +typedef struct { + int l,m,n; /* actual dimensions */ + int max_l, max_m, max_n; /* maximal dimensions */ + Real ***me; /* pointer to matrix elements */ + /* we do not consider segmented memory */ + Real *base, **me2d; /* me and me2d are additional pointers + to base */ +} MAT3D; + + +/* function for creating a variable of MAT3D type */ + +MAT3D *m3d_get(l,m,n) +int l,m,n; +{ + MAT3D *mat; + int i,j,k; + + /* check if arguments are positive */ + if (l <= 0 || m <= 0 || n <= 0) + error(E_NEG,"m3d_get"); + + /* new structure */ + if ((mat = NEW(MAT3D)) == (MAT3D *)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) { + /* record how many bytes is allocated */ + mem_bytes_list(TYPE_MAT3D,0,sizeof(MAT3D),M3D_LIST); + /* record a new allocated variable */ + mem_numvar_list(TYPE_MAT3D,1,M3D_LIST); + } + + mat->l = mat->max_l = l; + mat->m = mat->max_m = m; + mat->n = mat->max_n = n; + + /* allocate memory for 3D array */ + if ((mat->base = NEW_A(l*m*n,Real)) == (Real *)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_MAT3D,0,l*m*n*sizeof(Real),M3D_LIST); + + /* allocate memory for 2D pointers */ + if ((mat->me2d = NEW_A(l*m,Real *)) == (Real **)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_MAT3D,0,l*m*sizeof(Real *),M3D_LIST); + + /* allocate memory for 1D pointers */ + if ((mat->me = NEW_A(l,Real **)) == (Real ***)NULL) + error(E_MEM,"m3d_get"); + else if (mem_info_is_on()) + mem_bytes_list(TYPE_MAT3D,0,l*sizeof(Real **),M3D_LIST); + + /* pointers to 2D matrices */ + for (i=0,k=0; i < l; i++) + for (j=0; j < m; j++) + mat->me2d[k++] = &mat->base[(i*m+j)*n]; + + /* pointers to rows */ + for (i=0; i < l; i++) + mat->me[i] = &mat->me2d[i*m]; + + return mat; +} + + +/* deallocate a variable of type MAT3D */ + +int m3d_free(mat) +MAT3D *mat; +{ + /* do not try to deallocate the NULL pointer */ + if (mat == (MAT3D *)NULL) + return -1; + + /* first deallocate base */ + if (mat->base != (Real *)NULL) { + if (mem_info_is_on()) + /* record how many bytes is deallocated */ + mem_bytes_list(TYPE_MAT3D,mat->max_l*mat->max_m*mat->max_n*sizeof(Real), + 0,M3D_LIST); + free((char *)mat->base); + } + + /* deallocate array of 2D pointers */ + if (mat->me2d != (Real **)NULL) { + if (mem_info_is_on()) + /* record how many bytes is deallocated */ + mem_bytes_list(TYPE_MAT3D,mat->max_l*mat->max_m*sizeof(Real *), + 0,M3D_LIST); + free((char *)mat->me2d); + } + + /* deallocate array of 1D pointers */ + if (mat->me != (Real ***)NULL) { + if (mem_info_is_on()) + /* record how many bytes is deallocated */ + mem_bytes_list(TYPE_MAT3D,mat->max_l*sizeof(Real **),0,M3D_LIST); + free((char *)mat->me); + } + + /* deallocate MAT3D structure */ + if (mem_info_is_on()) { + mem_bytes_list(TYPE_MAT3D,sizeof(MAT3D),0,M3D_LIST); + mem_numvar_list(TYPE_MAT3D,-1,M3D_LIST); + } + free((char *)mat); + + return 0; +} + +/*=============================================*/ + +char *m3d_names[] = { + "MAT3D" +}; + + +#define M3D_NUM (sizeof(m3d_names)/sizeof(*m3d_names)) + +int (*m3d_free_funcs[M3D_NUM])() = { + m3d_free +}; + +static MEM_ARRAY m3d_sum[M3D_NUM]; + + +/* test routing for allocating/deallocating static variables */ +void test_stat(k) +int k; +{ + static MAT3D *work; + + if (!work) { + work = m3d_get(10,10,10); + mem_stat_reg_list((void **)&work,TYPE_MAT3D,M3D_LIST); + work->me[9][9][9] = -3.14; + } + + if (k == 9) + printf(" work[9][9][9] = %g\n",work->me[9][9][9]); +} + + +void main() +{ + MAT3D *M; + int i,j,k; + + mem_info_on(TRUE); + /* can be the first command */ + mem_attach_list(M3D_LIST,M3D_NUM,m3d_names,m3d_free_funcs,m3d_sum); + + M = m3d_get(3,4,5); + mem_info_file(stdout,M3D_LIST); + + /* make use of M->me[i][j][k], where i,j,k are non-negative and + i < 3, j < 4, k < 5 */ + + mem_stat_mark(1); + for (i=0; i < 3; i++) + for (j=0; j < 4; j++) + for (k=0; k < 5; k++) { + test_stat(i+j+k); + M->me[i][j][k] = i+j+k; + } + mem_stat_free_list(1,M3D_LIST); + mem_info_file(stdout,M3D_LIST); + + printf(" M[%d][%d][%d] = %g\n",2,3,4,M->me[2][3][4]); + + mem_stat_mark(2); + test_stat(9); + mem_stat_free_list(2,M3D_LIST); + + m3d_free(M); /* if M is not necessary */ + mem_info_file(stdout,M3D_LIST); + +} + + + diff --git a/tutorial.c b/tutorial.c new file mode 100644 index 0000000..1ae258d --- /dev/null +++ b/tutorial.c @@ -0,0 +1,321 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* tutorial.c 10/12/1993 */ + +/* routines from Chapter 1 of Meschach */ + +static char rcsid[] = "$Id: tutorial.c,v 1.3 1994/01/16 22:53:09 des Exp $"; + +#include +#include "matrix.h" + +/* rk4 -- 4th order Runge--Kutta method */ +double rk4(f,t,x,h) +double t, h; +VEC *(*f)(), *x; +{ + static VEC *v1=VNULL, *v2=VNULL, *v3=VNULL, *v4=VNULL; + static VEC *temp=VNULL; + + /* do not work with NULL initial vector */ + if ( x == VNULL ) + error(E_NULL,"rk4"); + + /* ensure that v1, ..., v4, temp are of the correct size */ + v1 = v_resize(v1,x->dim); + v2 = v_resize(v2,x->dim); + v3 = v_resize(v3,x->dim); + v4 = v_resize(v4,x->dim); + temp = v_resize(temp,x->dim); + + /* register workspace variables */ + MEM_STAT_REG(v1,TYPE_VEC); + MEM_STAT_REG(v2,TYPE_VEC); + MEM_STAT_REG(v3,TYPE_VEC); + MEM_STAT_REG(v4,TYPE_VEC); + MEM_STAT_REG(temp,TYPE_VEC); + /* end of memory allocation */ + + (*f)(t,x,v1); /* most compilers allow: "f(t,x,v1);" */ + v_mltadd(x,v1,0.5*h,temp); /* temp = x+.5*h*v1 */ + (*f)(t+0.5*h,temp,v2); + v_mltadd(x,v2,0.5*h,temp); /* temp = x+.5*h*v2 */ + (*f)(t+0.5*h,temp,v3); + v_mltadd(x,v3,h,temp); /* temp = x+h*v3 */ + (*f)(t+h,temp,v4); + + /* now add: v1+2*v2+2*v3+v4 */ + v_copy(v1,temp); /* temp = v1 */ + v_mltadd(temp,v2,2.0,temp); /* temp = v1+2*v2 */ + v_mltadd(temp,v3,2.0,temp); /* temp = v1+2*v2+2*v3 */ + v_add(temp,v4,temp); /* temp = v1+2*v2+2*v3+v4 */ + + /* adjust x */ + v_mltadd(x,temp,h/6.0,x); /* x = x+(h/6)*temp */ + + return t+h; /* return the new time */ +} + + + +/* rk4 -- 4th order Runge-Kutta method */ +/* another variant */ +double rk4_var(f,t,x,h) +double t, h; +VEC *(*f)(), *x; +{ + static VEC *v1, *v2, *v3, *v4, *temp; + + /* do not work with NULL initial vector */ + if ( x == VNULL ) error(E_NULL,"rk4"); + + /* ensure that v1, ..., v4, temp are of the correct size */ + v_resize_vars(x->dim, &v1, &v2, &v3, &v4, &temp, NULL); + + /* register workspace variables */ + mem_stat_reg_vars(0, TYPE_VEC, __FILE__, __LINE__, + &v1, &v2, &v3, &v4, &temp, NULL); + /* end of memory allocation */ + + (*f)(t,x,v1); v_mltadd(x,v1,0.5*h,temp); + (*f)(t+0.5*h,temp,v2); v_mltadd(x,v2,0.5*h,temp); + (*f)(t+0.5*h,temp,v3); v_mltadd(x,v3,h,temp); + (*f)(t+h,temp,v4); + + /* now add: temp = v1+2*v2+2*v3+v4 */ + v_linlist(temp, v1, 1.0, v2, 2.0, v3, 2.0, v4, 1.0, VNULL); + /* adjust x */ + v_mltadd(x,temp,h/6.0,x); /* x = x+(h/6)*temp */ + + return t+h; /* return the new time */ +} + + +/* f -- right-hand side of ODE solver */ +VEC *f(t,x,out) +VEC *x, *out; +double t; +{ + if ( x == VNULL || out == VNULL ) + error(E_NULL,"f"); + if ( x->dim != 2 || out->dim != 2 ) + error(E_SIZES,"f"); + + out->ve[0] = x->ve[1]; + out->ve[1] = - x->ve[0]; + + return out; +} + + +void tutor_rk4() +{ + VEC *x; + VEC *f(); + double h, t, t_fin; + double rk4(); + + input("Input initial time: ","%lf",&t); + input("Input final time: ", "%lf",&t_fin); + x = v_get(2); /* this is the size needed by f() */ + prompter("Input initial state:\n"); x = v_input(VNULL); + input("Input step size: ", "%lf",&h); + + printf("# At time %g, the state is\n",t); + v_output(x); + while (t < t_fin) + { + /* you can use t = rk4_var(f,t,x,min(h,t_fin-t)); */ + t = rk4(f,t,x,min(h,t_fin-t)); /* new t is returned */ + printf("# At time %g, the state is\n",t); + v_output(x); + } +} + + + + +#include "matrix2.h" + +void tutor_ls() +{ + MAT *A, *QR; + VEC *b, *x, *diag; + + /* read in A matrix */ + printf("Input A matrix:\n"); + + A = m_input(MNULL); /* A has whatever size is input */ + + if ( A->m < A->n ) + { + printf("Need m >= n to obtain least squares fit\n"); + exit(0); + } + printf("# A =\n"); m_output(A); + diag = v_get(A->m); + /* QR is to be the QR factorisation of A */ + QR = m_copy(A,MNULL); + QRfactor(QR,diag); + /* read in b vector */ + printf("Input b vector:\n"); + b = v_get(A->m); + b = v_input(b); + printf("# b =\n"); v_output(b); + + /* solve for x */ + x = QRsolve(QR,diag,b,VNULL); + printf("Vector of best fit parameters is\n"); + v_output(x); + /* ... and work out norm of errors... */ + printf("||A*x-b|| = %g\n", + v_norm2(v_sub(mv_mlt(A,x,VNULL),b,VNULL))); +} + + +#include "iter.h" + + +#define N 50 +#define VEC2MAT(v,m) vm_move((v),0,(m),0,0,N,N); + +#define PI 3.141592653589793116 +#define index(i,j) (N*((i)-1)+(j)-1) + +/* right hand side function (for generating b) */ +double f1(x,y) +double x,y; +{ + /* return 2.0*PI*PI*sin(PI*x)*sin(PI*y); */ + return exp(x*y); +} + +/* discrete laplacian */ +SPMAT *laplacian(A) +SPMAT *A; +{ + Real h; + int i,j; + + if (!A) + A = sp_get(N*N,N*N,5); + + for ( i = 1; i <= N; i++ ) + for ( j = 1; j <= N; j++ ) + { + if ( i < N ) + sp_set_val(A,index(i,j),index(i+1,j),-1.0); + if ( i > 1 ) + sp_set_val(A,index(i,j),index(i-1,j),-1.0); + if ( j < N ) + sp_set_val(A,index(i,j),index(i,j+1),-1.0); + if ( j > 1 ) + sp_set_val(A,index(i,j),index(i,j-1),-1.0); + sp_set_val(A,index(i,j),index(i,j),4.0); + } + return A; +} + +/* generating right hand side */ +VEC *rhs_lap(b) +VEC *b; +{ + Real h,h2,x,y; + int i,j; + + if (!b) + b = v_get(N*N); + + h = 1.0/(N+1); /* for a unit square */ + h2 = h*h; + x = 0.0; + for ( i = 1; i <= N; i++ ) { + x += h; + y = 0.0; + for ( j = 1; j <= N; j++ ) { + y += h; + b->ve[index(i,j)] = h2*f1(x,y); + } + } + return b; +} + +void tut_lap() +{ + SPMAT *A, *LLT; + VEC *b, *out, *x; + MAT *B; + int num_steps; + FILE *fp; + + A = sp_get(N*N,N*N,5); + b = v_get(N*N); + + laplacian(A); + LLT = sp_copy(A); + spICHfactor(LLT); + + out = v_get(A->m); + x = v_get(A->m); + + rhs_lap(b); /* new rhs */ + iter_spcg(A,LLT,b,1e-6,out,1000,&num_steps); + printf("Number of iterations = %d\n",num_steps); + + /* save b as a MATLAB matrix */ + + fp = fopen("laplace.mat","w"); /* b will be saved in laplace.mat */ + if (fp == NULL) { + printf("Cannot open %s\n","laplace.mat"); + exit(1); + } + + /* b must be transformed to a matrix */ + + B = m_get(N,N); + VEC2MAT(out,B); + m_save(fp,B,"sol"); /* sol is an internal name in MATLAB */ + +} + + +void main() +{ + int i; + + input("Choose the problem (1=Runge-Kutta, 2=least squares,3=laplace): ", + "%d",&i); + switch (i) { + case 1: tutor_rk4(); break; + case 2: tutor_ls(); break; + case 3: tut_lap(); break; + default: + printf(" Wrong value of i (only 1, 2 or 3)\n\n"); + break; + } + +} + diff --git a/update.c b/update.c new file mode 100644 index 0000000..347270c --- /dev/null +++ b/update.c @@ -0,0 +1,139 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. +*/ + +/* update.c 1.3 11/25/87 */ +static char rcsid[] = "$Id: update.c,v 1.2 1994/01/13 05:26:06 des Exp $"; + +#include +#include +#include "matrix.h" +#include "matrix2.h" + + + + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* LDLupdate -- updates a CHolesky factorisation, replacing LDL' by + MD~M' = LDL' + alpha.w.w' Note: w is overwritten + Ref: Gill et al Math Comp 28, p516 Algorithm C1 */ +#ifndef ANSI_C +MAT *LDLupdate(CHmat,w,alpha) +MAT *CHmat; +VEC *w; +double alpha; +#else +MAT *LDLupdate(MAT *CHmat, VEC *w, double alpha) +#endif +{ + unsigned int i,j; + Real diag,new_diag,beta,p; + + if ( CHmat==(MAT *)NULL || w==(VEC *)NULL ) + error(E_NULL,"LDLupdate"); + if ( CHmat->m != CHmat->n || w->dim != CHmat->m ) + error(E_SIZES,"LDLupdate"); + + for ( j=0; j < w->dim; j++ ) + { + p = w->ve[j]; + diag = CHmat->me[j][j]; + new_diag = CHmat->me[j][j] = diag + alpha*p*p; + if ( new_diag <= 0.0 ) + error(E_POSDEF,"LDLupdate"); + beta = p*alpha/new_diag; + alpha *= diag/new_diag; + + for ( i=j+1; i < w->dim; i++ ) + { + w->ve[i] -= p*CHmat->me[i][j]; + CHmat->me[i][j] += beta*w->ve[i]; + CHmat->me[j][i] = CHmat->me[i][j]; + } + } + + return (CHmat); +} + + +/* QRupdate -- updates QR factorisation in expanded form (seperate matrices) + Finds Q+, R+ s.t. Q+.R+ = Q.(R+u.v') and Q+ orthogonal, R+ upper triang + Ref: Golub & van Loan Matrix Computations pp437-443 + -- does not update Q if it is NULL */ +#ifndef ANSI_C +MAT *QRupdate(Q,R,u,v) +MAT *Q,*R; +VEC *u,*v; +#else +MAT *QRupdate(MAT *Q, MAT *R, VEC *u, VEC *v) +#endif +{ + int i,j,k; + Real c,s,temp; + + if ( ! R || ! u || ! v ) + error(E_NULL,"QRupdate"); + if ( ( Q && ( Q->m != Q->n || R->m != Q->n ) ) || + u->dim != R->m || v->dim != R->n ) + error(E_SIZES,"QRupdate"); + + /* find largest k s.t. u[k] != 0 */ + for ( k=R->m-1; k>=0; k-- ) + if ( u->ve[k] != 0.0 ) + break; + + /* transform R+u.v' to Hessenberg form */ + for ( i=k-1; i>=0; i-- ) + { + /* get Givens rotation */ + givens(u->ve[i],u->ve[i+1],&c,&s); + rot_rows(R,i,i+1,c,s,R); + if ( Q ) + rot_cols(Q,i,i+1,c,s,Q); + rot_vec(u,i,i+1,c,s,u); + } + + /* add into R */ + temp = u->ve[0]; + for ( j=0; jn; j++ ) + R->me[0][j] += temp*v->ve[j]; + + /* transform Hessenberg to upper triangular */ + for ( i=0; ime[i][i],R->me[i+1][i],&c,&s); + rot_rows(R,i,i+1,c,s,R); + if ( Q ) + rot_cols(Q,i,i+1,c,s,Q); + } + + return R; +} + diff --git a/vecop.c b/vecop.c new file mode 100644 index 0000000..3d729eb --- /dev/null +++ b/vecop.c @@ -0,0 +1,673 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* vecop.c 1.3 8/18/87 */ + +#include +#include "matrix.h" + +static char rcsid[] = "$Id: vecop.c,v 1.5 1996/08/20 18:18:10 stewart Exp $"; + + +/* _in_prod -- inner product of two vectors from i0 downwards + -- that is, returns a(i0:dim)^T.b(i0:dim) */ +#ifndef ANSI_C +double _in_prod(a,b,i0) +VEC *a,*b; +unsigned int i0; +#else +double _in_prod(const VEC *a, const VEC *b, unsigned int i0) +#endif +{ + unsigned int limit; + /* Real *a_v, *b_v; */ + /* register Real sum; */ + + if ( a==(VEC *)NULL || b==(VEC *)NULL ) + error(E_NULL,"_in_prod"); + limit = min(a->dim,b->dim); + if ( i0 > limit ) + error(E_BOUNDS,"_in_prod"); + + return __ip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0)); + /***************************************** + a_v = &(a->ve[i0]); b_v = &(b->ve[i0]); + for ( i=i0; idim != vector->dim ) + out = v_resize(out,vector->dim); + if ( scalar == 0.0 ) + return v_zero(out); + if ( scalar == 1.0 ) + return v_copy(vector,out); + + __smlt__(vector->ve,(double)scalar,out->ve,(int)(vector->dim)); + /************************************************** + dim = vector->dim; + out_ve = out->ve; vec_ve = vector->ve; + for ( i=0; ive[i] = scalar*vector->ve[i]; + (*out_ve++) = scalar*(*vec_ve++); + **************************************************/ + return (out); +} + +/* v_add -- vector addition -- out <- v1+v2 -- may be in-situ */ +#ifndef ANSI_C +VEC *v_add(vec1,vec2,out) +VEC *vec1,*vec2,*out; +#else +VEC *v_add(const VEC *vec1, const VEC *vec2, VEC *out) +#endif +{ + unsigned int dim; + /* Real *out_ve, *vec1_ve, *vec2_ve; */ + + if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL ) + error(E_NULL,"v_add"); + if ( vec1->dim != vec2->dim ) + error(E_SIZES,"v_add"); + if ( out==(VEC *)NULL || out->dim != vec1->dim ) + out = v_resize(out,vec1->dim); + dim = vec1->dim; + __add__(vec1->ve,vec2->ve,out->ve,(int)dim); + /************************************************************ + out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve; + for ( i=0; ive[i] = vec1->ve[i]+vec2->ve[i]; + (*out_ve++) = (*vec1_ve++) + (*vec2_ve++); + ************************************************************/ + + return (out); +} + +/* v_mltadd -- scalar/vector multiplication and addition + -- out = v1 + scale.v2 */ +#ifndef ANSI_C +VEC *v_mltadd(v1,v2,scale,out) +VEC *v1,*v2,*out; +double scale; +#else +VEC *v_mltadd(const VEC *v1, const VEC *v2, double scale, VEC *out) +#endif +{ + /* register unsigned int dim, i; */ + /* Real *out_ve, *v1_ve, *v2_ve; */ + + if ( v1==(VEC *)NULL || v2==(VEC *)NULL ) + error(E_NULL,"v_mltadd"); + if ( v1->dim != v2->dim ) + error(E_SIZES,"v_mltadd"); + if ( scale == 0.0 ) + return v_copy(v1,out); + if ( scale == 1.0 ) + return v_add(v1,v2,out); + + if ( v2 != out ) + { + tracecatch(out = v_copy(v1,out),"v_mltadd"); + + /* dim = v1->dim; */ + __mltadd__(out->ve,v2->ve,scale,(int)(v1->dim)); + } + else + { + tracecatch(out = sv_mlt(scale,v2,out),"v_mltadd"); + out = v_add(v1,out,out); + } + /************************************************************ + out_ve = out->ve; v1_ve = v1->ve; v2_ve = v2->ve; + for ( i=0; i < dim ; i++ ) + out->ve[i] = v1->ve[i] + scale*v2->ve[i]; + (*out_ve++) = (*v1_ve++) + scale*(*v2_ve++); + ************************************************************/ + + return (out); +} + +/* v_sub -- vector subtraction -- may be in-situ */ +#ifndef ANSI_C +VEC *v_sub(vec1,vec2,out) +VEC *vec1,*vec2,*out; +#else +VEC *v_sub(const VEC *vec1, const VEC *vec2, VEC *out) +#endif +{ + /* unsigned int i, dim; */ + /* Real *out_ve, *vec1_ve, *vec2_ve; */ + + if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL ) + error(E_NULL,"v_sub"); + if ( vec1->dim != vec2->dim ) + error(E_SIZES,"v_sub"); + if ( out==(VEC *)NULL || out->dim != vec1->dim ) + out = v_resize(out,vec1->dim); + + __sub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim)); + /************************************************************ + dim = vec1->dim; + out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve; + for ( i=0; ive[i] = vec1->ve[i]-vec2->ve[i]; + (*out_ve++) = (*vec1_ve++) - (*vec2_ve++); + ************************************************************/ + + return (out); +} + +/* v_map -- maps function f over components of x: out[i] = f(x[i]) + -- v_map sets out[i] = f(params,x[i]) */ +#ifndef ANSI_C +VEC *v_map(f,x,out) +double (*f)(); +VEC *x, *out; +#else +#ifdef PROTOTYPES_IN_STRUCT +VEC *v_map(double (*f)(double), const VEC *x, VEC *out) +#else +VEC *v_map(double (*f)(), const VEC *x, VEC *out) +#endif +#endif +{ + Real *x_ve, *out_ve; + int i, dim; + + if ( ! x || ! f ) + error(E_NULL,"v_map"); + if ( ! out || out->dim != x->dim ) + out = v_resize(out,x->dim); + + dim = x->dim; x_ve = x->ve; out_ve = out->ve; + for ( i = 0; i < dim; i++ ) + *out_ve++ = (*f)(*x_ve++); + + return out; +} + +/* _v_map -- sets out[i] <- f(params, x[i]), i = 0, 1, .., dim-1 */ +#ifndef ANSI_C +VEC *_v_map(f,params,x,out) +double (*f)(); +void *params; +VEC *x, *out; +#else +#ifdef PROTOTYPES_IN_STRUCT +VEC *_v_map(double (*f)(void *,double), void *params, const VEC *x, VEC *out) +#else +VEC *_v_map(double (*f)(), void *params, const VEC *x, VEC *out) +#endif +#endif +{ + Real *x_ve, *out_ve; + int i, dim; + + if ( ! x || ! f ) + error(E_NULL,"_v_map"); + if ( ! out || out->dim != x->dim ) + out = v_resize(out,x->dim); + + dim = x->dim; x_ve = x->ve; out_ve = out->ve; + for ( i = 0; i < dim; i++ ) + *out_ve++ = (*f)(params,*x_ve++); + + return out; +} + +/* v_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */ +#ifndef ANSI_C +VEC *v_lincomb(n,v,a,out) +int n; /* number of a's and v's */ +Real a[]; +VEC *v[], *out; +#else +VEC *v_lincomb(int n, const VEC *v[], const Real a[], VEC *out) +#endif +{ + int i; + + if ( ! a || ! v ) + error(E_NULL,"v_lincomb"); + if ( n <= 0 ) + return VNULL; + + for ( i = 1; i < n; i++ ) + if ( out == v[i] ) + error(E_INSITU,"v_lincomb"); + + out = sv_mlt(a[0],v[0],out); + for ( i = 1; i < n; i++ ) + { + if ( ! v[i] ) + error(E_NULL,"v_lincomb"); + if ( v[i]->dim != out->dim ) + error(E_SIZES,"v_lincomb"); + out = v_mltadd(out,v[i],a[i],out); + } + + return out; +} + + + +#ifdef ANSI_C + +/* v_linlist -- linear combinations taken from a list of arguments; + calling: + v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL); + where vi are vectors (VEC *) and ai are numbers (double) +*/ +VEC *v_linlist(VEC *out,VEC *v1,double a1,...) +{ + va_list ap; + VEC *par; + double a_par; + + if ( ! v1 ) + return VNULL; + + va_start(ap, a1); + out = sv_mlt(a1,v1,out); + + while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/ + a_par = va_arg(ap,double); + if (a_par == 0.0) continue; + if ( out == par ) + error(E_INSITU,"v_linlist"); + if ( out->dim != par->dim ) + error(E_SIZES,"v_linlist"); + + if (a_par == 1.0) + out = v_add(out,par,out); + else if (a_par == -1.0) + out = v_sub(out,par,out); + else + out = v_mltadd(out,par,a_par,out); + } + + va_end(ap); + return out; +} + +#elif VARARGS + + +/* v_linlist -- linear combinations taken from a list of arguments; + calling: + v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL); + where vi are vectors (VEC *) and ai are numbers (double) +*/ +VEC *v_linlist(va_alist) va_dcl +{ + va_list ap; + VEC *par, *out; + double a_par; + + va_start(ap); + out = va_arg(ap,VEC *); + par = va_arg(ap,VEC *); + if ( ! par ) { + va_end(ap); + return VNULL; + } + + a_par = va_arg(ap,double); + out = sv_mlt(a_par,par,out); + + while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/ + a_par = va_arg(ap,double); + if (a_par == 0.0) continue; + if ( out == par ) + error(E_INSITU,"v_linlist"); + if ( out->dim != par->dim ) + error(E_SIZES,"v_linlist"); + + if (a_par == 1.0) + out = v_add(out,par,out); + else if (a_par == -1.0) + out = v_sub(out,par,out); + else + out = v_mltadd(out,par,a_par,out); + } + + va_end(ap); + return out; +} + +#endif + + + + + +/* v_star -- computes componentwise (Hadamard) product of x1 and x2 + -- result out is returned */ +#ifndef ANSI_C +VEC *v_star(x1, x2, out) +VEC *x1, *x2, *out; +#else +VEC *v_star(const VEC *x1, const VEC *x2, VEC *out) +#endif +{ + int i; + + if ( ! x1 || ! x2 ) + error(E_NULL,"v_star"); + if ( x1->dim != x2->dim ) + error(E_SIZES,"v_star"); + out = v_resize(out,x1->dim); + + for ( i = 0; i < x1->dim; i++ ) + out->ve[i] = x1->ve[i] * x2->ve[i]; + + return out; +} + +/* v_slash -- computes componentwise ratio of x2 and x1 + -- out[i] = x2[i] / x1[i] + -- if x1[i] == 0 for some i, then raise E_SING error + -- result out is returned */ +#ifndef ANSI_C +VEC *v_slash(x1, x2, out) +VEC *x1, *x2, *out; +#else +VEC *v_slash(const VEC *x1, const VEC *x2, VEC *out) +#endif +{ + int i; + Real tmp; + + if ( ! x1 || ! x2 ) + error(E_NULL,"v_slash"); + if ( x1->dim != x2->dim ) + error(E_SIZES,"v_slash"); + out = v_resize(out,x1->dim); + + for ( i = 0; i < x1->dim; i++ ) + { + tmp = x1->ve[i]; + if ( tmp == 0.0 ) + error(E_SING,"v_slash"); + out->ve[i] = x2->ve[i] / tmp; + } + + return out; +} + +/* v_min -- computes minimum component of x, which is returned + -- also sets min_idx to the index of this minimum */ +#ifndef ANSI_C +double v_min(x, min_idx) +VEC *x; +int *min_idx; +#else +double v_min(const VEC *x, int *min_idx) +#endif +{ + int i, i_min; + Real min_val, tmp; + + if ( ! x ) + error(E_NULL,"v_min"); + if ( x->dim <= 0 ) + error(E_SIZES,"v_min"); + i_min = 0; + min_val = x->ve[0]; + for ( i = 1; i < x->dim; i++ ) + { + tmp = x->ve[i]; + if ( tmp < min_val ) + { + min_val = tmp; + i_min = i; + } + } + + if ( min_idx != NULL ) + *min_idx = i_min; + return min_val; +} + +/* v_max -- computes maximum component of x, which is returned + -- also sets max_idx to the index of this maximum */ +#ifndef ANSI_C +double v_max(x, max_idx) +VEC *x; +int *max_idx; +#else +double v_max(const VEC *x, int *max_idx) +#endif +{ + int i, i_max; + Real max_val, tmp; + + if ( ! x ) + error(E_NULL,"v_max"); + if ( x->dim <= 0 ) + error(E_SIZES,"v_max"); + i_max = 0; + max_val = x->ve[0]; + for ( i = 1; i < x->dim; i++ ) + { + tmp = x->ve[i]; + if ( tmp > max_val ) + { + max_val = tmp; + i_max = i; + } + } + + if ( max_idx != NULL ) + *max_idx = i_max; + return max_val; +} + +#define MAX_STACK 60 + + +/* v_sort -- sorts vector x, and generates permutation that gives the order + of the components; x = [1.3, 3.7, 0.5] -> [0.5, 1.3, 3.7] and + the permutation is order = [2, 0, 1]. + -- if order is NULL on entry then it is ignored + -- the sorted vector x is returned */ +#ifndef ANSI_C +VEC *v_sort(x, order) +VEC *x; +PERM *order; +#else +VEC *v_sort(VEC *x, PERM *order) +#endif +{ + Real *x_ve, tmp, v; + /* int *order_pe; */ + int dim, i, j, l, r, tmp_i; + int stack[MAX_STACK], sp; + + if ( ! x ) + error(E_NULL,"v_sort"); + if ( order != PNULL && order->size != x->dim ) + order = px_resize(order, x->dim); + + x_ve = x->ve; + dim = x->dim; + if ( order != PNULL ) + px_ident(order); + + if ( dim <= 1 ) + return x; + + /* using quicksort algorithm in Sedgewick, + "Algorithms in C", Ch. 9, pp. 118--122 (1990) */ + sp = 0; + l = 0; r = dim-1; v = x_ve[0]; + for ( ; ; ) + { + while ( r > l ) + { + /* "i = partition(x_ve,l,r);" */ + v = x_ve[r]; + i = l-1; + j = r; + for ( ; ; ) + { + while ( x_ve[++i] < v ) + ; + --j; + while ( x_ve[j] > v && j != 0 ) + --j; + if ( i >= j ) break; + + tmp = x_ve[i]; + x_ve[i] = x_ve[j]; + x_ve[j] = tmp; + if ( order != PNULL ) + { + tmp_i = order->pe[i]; + order->pe[i] = order->pe[j]; + order->pe[j] = tmp_i; + } + } + tmp = x_ve[i]; + x_ve[i] = x_ve[r]; + x_ve[r] = tmp; + if ( order != PNULL ) + { + tmp_i = order->pe[i]; + order->pe[i] = order->pe[r]; + order->pe[r] = tmp_i; + } + + if ( i-l > r-i ) + { stack[sp++] = l; stack[sp++] = i-1; l = i+1; } + else + { stack[sp++] = i+1; stack[sp++] = r; r = i-1; } + } + + /* recursion elimination */ + if ( sp == 0 ) + break; + r = stack[--sp]; + l = stack[--sp]; + } + + return x; +} + +/* v_sum -- returns sum of entries of a vector */ +#ifndef ANSI_C +double v_sum(x) +VEC *x; +#else +double v_sum(const VEC *x) +#endif +{ + int i; + Real sum; + + if ( ! x ) + error(E_NULL,"v_sum"); + + sum = 0.0; + for ( i = 0; i < x->dim; i++ ) + sum += x->ve[i]; + + return sum; +} + +/* v_conv -- computes convolution product of two vectors */ +#ifndef ANSI_C +VEC *v_conv(x1, x2, out) +VEC *x1, *x2, *out; +#else +VEC *v_conv(const VEC *x1, const VEC *x2, VEC *out) +#endif +{ + int i; + + if ( ! x1 || ! x2 ) + error(E_NULL,"v_conv"); + if ( x1 == out || x2 == out ) + error(E_INSITU,"v_conv"); + if ( x1->dim == 0 || x2->dim == 0 ) + return out = v_resize(out,0); + + out = v_resize(out,x1->dim + x2->dim - 1); + v_zero(out); + for ( i = 0; i < x1->dim; i++ ) + __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim); + + return out; +} + +/* v_pconv -- computes a periodic convolution product + -- the period is the dimension of x2 */ +#ifndef ANSI_C +VEC *v_pconv(x1, x2, out) +VEC *x1, *x2, *out; +#else +VEC *v_pconv(const VEC *x1, const VEC *x2, VEC *out) +#endif +{ + int i; + + if ( ! x1 || ! x2 ) + error(E_NULL,"v_pconv"); + if ( x1 == out || x2 == out ) + error(E_INSITU,"v_pconv"); + out = v_resize(out,x2->dim); + if ( x2->dim == 0 ) + return out; + + v_zero(out); + for ( i = 0; i < x1->dim; i++ ) + { + __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim - i); + if ( i > 0 ) + __mltadd__(out->ve,&(x2->ve[x2->dim - i]),x1->ve[i],i); + } + + return out; +} diff --git a/version.c b/version.c new file mode 100644 index 0000000..905c016 --- /dev/null +++ b/version.c @@ -0,0 +1,72 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* Version routine */ +/* This routine must be modified whenever modifications are made to + Meschach by persons other than the original authors + (David E. Stewart & Zbigniew Leyk); + when new releases of Meschach are made the + version number will also be updated +*/ + +#include + +void m_version() +{ + static char rcsid[] = "$Id: version.c,v 1.9 1994/03/24 00:04:05 des Exp $"; + + printf("Meshach matrix library version 1.2b\n"); + printf("RCS id: %s\n",rcsid); + printf("Changes since 1.2a:\n"); + printf("\t Fixed bug in schur() for 2x2 blocks with real e-vals\n"); + printf("\t Fixed bug in schur() reading beyond end of array\n"); + printf("\t Fixed some installation bugs\n"); + printf("\t Fixed bugs & improved efficiency in spILUfactor()\n"); + printf("\t px_inv() doesn't crash inverting non-permutations\n"); + printf("\t Fixed bug in ifft()\n"); + /**** List of modifications ****/ + /* Example below is for illustration only */ + /* printf("Modified by %s, routine(s) %s, file %s on date %s\n", + "Joe Bloggs", + "m_version", + "version.c", + "Fri Apr 5 16:00:38 EST 1994"); */ + /* printf("Purpose: %s\n", + "To update the version number"); */ +} + +/* $Log: version.c,v $ + * Revision 1.9 1994/03/24 00:04:05 des + * Added notes on changes to spILUfactor() and px_inv(). + * + * Revision 1.8 1994/02/21 04:32:25 des + * Set version to 1.2b with bug fixes in schur() and installation. + * + * Revision 1.7 1994/01/13 05:43:57 des + * Version 1.2 update + * + + * */ diff --git a/zcopy.c b/zcopy.c new file mode 100644 index 0000000..7aea24a --- /dev/null +++ b/zcopy.c @@ -0,0 +1,220 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +static char rcsid[] = "$Id: zcopy.c,v 1.1 1994/01/13 04:28:42 des Exp $"; +#include +#include "zmatrix.h" + + + +/* _zm_copy -- copies matrix into new area */ +#ifndef ANSI_C +ZMAT *_zm_copy(in,out,i0,j0) +ZMAT *in,*out; +unsigned int i0,j0; +#else +ZMAT *_zm_copy(const ZMAT *in, ZMAT *out, int i0, int j0) +#endif +{ + unsigned int i /* ,j */; + + if ( in==ZMNULL ) + error(E_NULL,"_zm_copy"); + if ( in==out ) + return (out); + if ( out==ZMNULL || out->m < in->m || out->n < in->n ) + out = zm_resize(out,in->m,in->n); + + for ( i=i0; i < in->m; i++ ) + MEM_COPY(&(in->me[i][j0]),&(out->me[i][j0]), + (in->n - j0)*sizeof(complex)); + /* for ( j=j0; j < in->n; j++ ) + out->me[i][j] = in->me[i][j]; */ + + return (out); +} + +/* _zv_copy -- copies vector into new area */ +#ifndef ANSI_C +ZVEC *_zv_copy(in,out,i0) +ZVEC *in,*out; +unsigned int i0; +#else +ZVEC *_zv_copy(const ZVEC *in, ZVEC *out, int i0) +#endif +{ + /* unsigned int i,j; */ + + if ( in==ZVNULL ) + error(E_NULL,"_zv_copy"); + if ( in==out ) + return (out); + if ( out==ZVNULL || out->dim < in->dim ) + out = zv_resize(out,in->dim); + + MEM_COPY(&(in->ve[i0]),&(out->ve[i0]),(in->dim - i0)*sizeof(complex)); + /* for ( i=i0; i < in->dim; i++ ) + out->ve[i] = in->ve[i]; */ + + return (out); +} + + +/* + The z._move() routines are for moving blocks of memory around + within Meschach data structures and for re-arranging matrices, + vectors etc. +*/ + +/* zm_move -- copies selected pieces of a matrix + -- moves the m0 x n0 submatrix with top-left cor-ordinates (i0,j0) + to the corresponding submatrix of out with top-left co-ordinates + (i1,j1) + -- out is resized (& created) if necessary */ +#ifndef ANSI_C +ZMAT *zm_move(in,i0,j0,m0,n0,out,i1,j1) +ZMAT *in, *out; +int i0, j0, m0, n0, i1, j1; +#else +ZMAT *zm_move(const ZMAT *in, int i0, int j0, int m0, int n0, + ZMAT *out, int i1, int j1) +#endif +{ + int i; + + if ( ! in ) + error(E_NULL,"zm_move"); + if ( i0 < 0 || j0 < 0 || i1 < 0 || j1 < 0 || m0 < 0 || n0 < 0 || + i0+m0 > in->m || j0+n0 > in->n ) + error(E_BOUNDS,"zm_move"); + + if ( ! out ) + out = zm_resize(out,i1+m0,j1+n0); + else if ( i1+m0 > out->m || j1+n0 > out->n ) + out = zm_resize(out,max(out->m,i1+m0),max(out->n,j1+n0)); + + for ( i = 0; i < m0; i++ ) + MEM_COPY(&(in->me[i0+i][j0]),&(out->me[i1+i][j1]), + n0*sizeof(complex)); + + return out; +} + +/* zv_move -- copies selected pieces of a vector + -- moves the length dim0 subvector with initial index i0 + to the corresponding subvector of out with initial index i1 + -- out is resized if necessary */ +#ifndef ANSI_C +ZVEC *zv_move(in,i0,dim0,out,i1) +ZVEC *in, *out; +int i0, dim0, i1; +#else +ZVEC *zv_move(const ZVEC *in, int i0, int dim0, + ZVEC *out, int i1) +#endif +{ + if ( ! in ) + error(E_NULL,"zv_move"); + if ( i0 < 0 || dim0 < 0 || i1 < 0 || + i0+dim0 > in->dim ) + error(E_BOUNDS,"zv_move"); + + if ( (! out) || i1+dim0 > out->dim ) + out = zv_resize(out,i1+dim0); + + MEM_COPY(&(in->ve[i0]),&(out->ve[i1]),dim0*sizeof(complex)); + + return out; +} + + +/* zmv_move -- copies selected piece of matrix to a vector + -- moves the m0 x n0 submatrix with top-left co-ordinate (i0,j0) to + the subvector with initial index i1 (and length m0*n0) + -- rows are copied contiguously + -- out is resized if necessary */ +#ifndef ANSI_C +ZVEC *zmv_move(in,i0,j0,m0,n0,out,i1) +ZMAT *in; +ZVEC *out; +int i0, j0, m0, n0, i1; +#else +ZVEC *zmv_move(const ZMAT *in, int i0, int j0, int m0, int n0, + ZVEC *out, int i1) +#endif +{ + int dim1, i; + + if ( ! in ) + error(E_NULL,"zmv_move"); + if ( i0 < 0 || j0 < 0 || m0 < 0 || n0 < 0 || i1 < 0 || + i0+m0 > in->m || j0+n0 > in->n ) + error(E_BOUNDS,"zmv_move"); + + dim1 = m0*n0; + if ( (! out) || i1+dim1 > out->dim ) + out = zv_resize(out,i1+dim1); + + for ( i = 0; i < m0; i++ ) + MEM_COPY(&(in->me[i0+i][j0]),&(out->ve[i1+i*n0]),n0*sizeof(complex)); + + return out; +} + +/* zvm_move -- copies selected piece of vector to a matrix + -- moves the subvector with initial index i0 and length m1*n1 to + the m1 x n1 submatrix with top-left co-ordinate (i1,j1) + -- copying is done by rows + -- out is resized if necessary */ +#ifndef ANSI_C +ZMAT *zvm_move(in,i0,out,i1,j1,m1,n1) +ZVEC *in; +ZMAT *out; +int i0, i1, j1, m1, n1; +#else +ZMAT *zvm_move(const ZVEC *in, int i0, + ZMAT *out, int i1, int j1, int m1, int n1) +#endif +{ + int dim0, i; + + if ( ! in ) + error(E_NULL,"zvm_move"); + if ( i0 < 0 || i1 < 0 || j1 < 0 || m1 < 0 || n1 < 0 || + i0+m1*n1 > in->dim ) + error(E_BOUNDS,"zvm_move"); + + if ( ! out ) + out = zm_resize(out,i1+m1,j1+n1); + else + out = zm_resize(out,max(i1+m1,out->m),max(j1+n1,out->n)); + + dim0 = m1*n1; + for ( i = 0; i < m1; i++ ) + MEM_COPY(&(in->ve[i0+i*n1]),&(out->me[i1+i][j1]),n1*sizeof(complex)); + + return out; +} diff --git a/zfunc.c b/zfunc.c new file mode 100644 index 0000000..6ecba69 --- /dev/null +++ b/zfunc.c @@ -0,0 +1,244 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + Elementary functions for complex numbers + -- if not already defined +*/ + +#include +#include "zmatrix.h" + +static char rcsid[] = "$Id: zfunc.c,v 1.3 1995/04/07 16:27:25 des Exp $"; + +#ifndef COMPLEX_H + +#ifndef zmake +/* zmake -- create complex number real + i*imag */ +complex zmake(real,imag) +double real, imag; +{ + complex w; /* == real + i*imag */ + + w.re = real; w.im = imag; + return w; +} +#endif + +#ifndef zneg +/* zneg -- returns negative of z */ +complex zneg(z) +complex z; +{ + z.re = - z.re; + z.im = - z.im; + + return z; +} +#endif + +#ifndef zabs +/* zabs -- returns |z| */ +double zabs(z) +complex z; +{ + Real x, y, tmp; + int x_expt, y_expt; + + /* Note: we must ensure that overflow does not occur! */ + x = ( z.re >= 0.0 ) ? z.re : -z.re; + y = ( z.im >= 0.0 ) ? z.im : -z.im; + if ( x < y ) + { + tmp = x; + x = y; + y = tmp; + } + if ( x == 0.0 ) /* then y == 0.0 as well */ + return 0.0; + x = frexp(x,&x_expt); + y = frexp(y,&y_expt); + y = ldexp(y,y_expt-x_expt); + tmp = sqrt(x*x+y*y); + + return ldexp(tmp,x_expt); +} +#endif + +#ifndef zadd +/* zadd -- returns z1+z2 */ +complex zadd(z1,z2) +complex z1, z2; +{ + complex z; + + z.re = z1.re + z2.re; + z.im = z1.im + z2.im; + + return z; +} +#endif + +#ifndef zsub +/* zsub -- returns z1-z2 */ +complex zsub(z1,z2) +complex z1, z2; +{ + complex z; + + z.re = z1.re - z2.re; + z.im = z1.im - z2.im; + + return z; +} +#endif + +#ifndef zmlt +/* zmlt -- returns z1*z2 */ +complex zmlt(z1,z2) +complex z1, z2; +{ + complex z; + + z.re = z1.re * z2.re - z1.im * z2.im; + z.im = z1.re * z2.im + z1.im * z2.re; + + return z; +} +#endif + +#ifndef zinv +/* zmlt -- returns 1/z */ +complex zinv(z) +complex z; +{ + Real x, y, tmp; + int x_expt, y_expt; + + if ( z.re == 0.0 && z.im == 0.0 ) + error(E_SING,"zinv"); + /* Note: we must ensure that overflow does not occur! */ + x = ( z.re >= 0.0 ) ? z.re : -z.re; + y = ( z.im >= 0.0 ) ? z.im : -z.im; + if ( x < y ) + { + tmp = x; + x = y; + y = tmp; + } + x = frexp(x,&x_expt); + y = frexp(y,&y_expt); + y = ldexp(y,y_expt-x_expt); + + tmp = 1.0/(x*x + y*y); + z.re = z.re*tmp*ldexp(1.0,-2*x_expt); + z.im = -z.im*tmp*ldexp(1.0,-2*x_expt); + + return z; +} +#endif + +#ifndef zdiv +/* zdiv -- returns z1/z2 */ +complex zdiv(z1,z2) +complex z1, z2; +{ + return zmlt(z1,zinv(z2)); +} +#endif + +#ifndef zsqrt +/* zsqrt -- returns sqrt(z); uses branch with Re sqrt(z) >= 0 */ +complex zsqrt(z) +complex z; +{ + complex w; /* == sqrt(z) at end */ + Real alpha; + + alpha = sqrt(0.5*(fabs(z.re) + zabs(z))); + if (alpha!=0) + { + if (z.re>=0.0) + { + w.re = alpha; + w.im = z.im / (2.0*alpha); + } + else + { + w.re = fabs(z.im)/(2.0*alpha); + w.im = ( z.im >= 0 ) ? alpha : - alpha; + } + } + else + w.re = w.im = 0.0; + + return w; +} +#endif + +#ifndef zexp +/* zexp -- returns exp(z) */ +complex zexp(z) +complex z; +{ + complex w; /* == exp(z) at end */ + Real r; + + r = exp(z.re); + w.re = r*cos(z.im); + w.im = r*sin(z.im); + + return w; +} +#endif + +#ifndef zlog +/* zlog -- returns log(z); uses principal branch with -pi <= Im log(z) <= pi */ +complex zlog(z) +complex z; +{ + complex w; /* == log(z) at end */ + + w.re = log(zabs(z)); + w.im = atan2(z.im,z.re); + + return w; +} +#endif + +#ifndef zconj +complex zconj(z) +complex z; +{ + complex w; /* == conj(z) */ + + w.re = z.re; + w.im = - z.im; + return w; +} +#endif + +#endif + diff --git a/zgivens.c b/zgivens.c new file mode 100644 index 0000000..e42792f --- /dev/null +++ b/zgivens.c @@ -0,0 +1,184 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Givens operations file. Contains routines for calculating and + applying givens rotations for/to vectors and also to matrices by + row and by column. + + Complex version. +*/ + +static char rcsid[] = "$Id: "; + +#include +#include +#include "zmatrix.h" +#include "zmatrix2.h" + +/* + (Complex) Givens rotation matrix: + [ c -s ] + [ s* c ] + Note that c is real and s is complex +*/ + +/* zgivens -- returns c,s parameters for Givens rotation to + eliminate y in the **column** vector [ x y ] */ +void zgivens(x,y,c,s) +complex x,y,*s; +Real *c; +{ + Real inv_norm, norm; + complex tmp; + + /* this is a safe way of computing sqrt(|x|^2+|y|^2) */ + tmp.re = zabs(x); tmp.im = zabs(y); + norm = zabs(tmp); + + if ( norm == 0.0 ) + { *c = 1.0; s->re = s->im = 0.0; } /* identity */ + else + { + inv_norm = 1.0 / tmp.re; /* inv_norm = 1/|x| */ + x.re *= inv_norm; + x.im *= inv_norm; /* normalise x */ + inv_norm = 1.0/norm; /* inv_norm = 1/||[x,y]||2 */ + *c = tmp.re * inv_norm; + /* now compute - conj(normalised x).y/||[x,y]||2 */ + s->re = - inv_norm*(x.re*y.re + x.im*y.im); + s->im = inv_norm*(x.re*y.im - x.im*y.re); + } +} + +/* rot_zvec -- apply Givens rotation to x's i & k components */ +ZVEC *rot_zvec(x,i,k,c,s,out) +ZVEC *x,*out; +int i,k; +double c; +complex s; +{ + + complex temp1, temp2; + + if ( x==ZVNULL ) + error(E_NULL,"rot_zvec"); + if ( i < 0 || i >= x->dim || k < 0 || k >= x->dim ) + error(E_RANGE,"rot_zvec"); + if ( x != out ) + out = zv_copy(x,out); + + /* temp1 = c*out->ve[i] - s*out->ve[k]; */ + temp1.re = c*out->ve[i].re + - s.re*out->ve[k].re + s.im*out->ve[k].im; + temp1.im = c*out->ve[i].im + - s.re*out->ve[k].im - s.im*out->ve[k].re; + + /* temp2 = c*out->ve[k] + zconj(s)*out->ve[i]; */ + temp2.re = c*out->ve[k].re + + s.re*out->ve[i].re + s.im*out->ve[i].im; + temp2.im = c*out->ve[k].im + + s.re*out->ve[i].im - s.im*out->ve[i].re; + + out->ve[i] = temp1; + out->ve[k] = temp2; + + return (out); +} + +/* zrot_rows -- premultiply mat by givens rotation described by c,s */ +ZMAT *zrot_rows(mat,i,k,c,s,out) +ZMAT *mat,*out; +int i,k; +double c; +complex s; +{ + unsigned int j; + complex temp1, temp2; + + if ( mat==ZMNULL ) + error(E_NULL,"zrot_rows"); + if ( i < 0 || i >= mat->m || k < 0 || k >= mat->m ) + error(E_RANGE,"zrot_rows"); + + if ( mat != out ) + out = zm_copy(mat,zm_resize(out,mat->m,mat->n)); + + /* temp1 = c*out->me[i][j] - s*out->me[k][j]; */ + for ( j=0; jn; j++ ) + { + /* temp1 = c*out->me[i][j] - s*out->me[k][j]; */ + temp1.re = c*out->me[i][j].re + - s.re*out->me[k][j].re + s.im*out->me[k][j].im; + temp1.im = c*out->me[i][j].im + - s.re*out->me[k][j].im - s.im*out->me[k][j].re; + + /* temp2 = c*out->me[k][j] + conj(s)*out->me[i][j]; */ + temp2.re = c*out->me[k][j].re + + s.re*out->me[i][j].re + s.im*out->me[i][j].im; + temp2.im = c*out->me[k][j].im + + s.re*out->me[i][j].im - s.im*out->me[i][j].re; + + out->me[i][j] = temp1; + out->me[k][j] = temp2; + } + + return (out); +} + +/* zrot_cols -- postmultiply mat by adjoint Givens rotation described by c,s */ +ZMAT *zrot_cols(mat,i,k,c,s,out) +ZMAT *mat,*out; +int i,k; +double c; +complex s; +{ + unsigned int j; + complex x, y; + + if ( mat==ZMNULL ) + error(E_NULL,"zrot_cols"); + if ( i < 0 || i >= mat->n || k < 0 || k >= mat->n ) + error(E_RANGE,"zrot_cols"); + + if ( mat != out ) + out = zm_copy(mat,zm_resize(out,mat->m,mat->n)); + + for ( j=0; jm; j++ ) + { + x = out->me[j][i]; y = out->me[j][k]; + /* out->me[j][i] = c*x - conj(s)*y; */ + out->me[j][i].re = c*x.re - s.re*y.re - s.im*y.im; + out->me[j][i].im = c*x.im - s.re*y.im + s.im*y.re; + + /* out->me[j][k] = c*y + s*x; */ + out->me[j][k].re = c*y.re + s.re*x.re - s.im*x.im; + out->me[j][k].im = c*y.im + s.re*x.im + s.im*x.re; + } + + return (out); +} + diff --git a/zhessen.c b/zhessen.c new file mode 100644 index 0000000..0a5b68e --- /dev/null +++ b/zhessen.c @@ -0,0 +1,162 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + File containing routines for determining Hessenberg + factorisations. + + Complex version +*/ + +static char rcsid[] = "$Id: zhessen.c,v 1.2 1995/03/27 15:47:50 des Exp $"; + +#include +#include "zmatrix.h" +#include "zmatrix2.h" + + +/* zHfactor -- compute Hessenberg factorisation in compact form. + -- factorisation performed in situ + -- for details of the compact form see zQRfactor.c and zmatrix2.doc */ +ZMAT *zHfactor(A, diag) +ZMAT *A; +ZVEC *diag; +{ + STATIC ZVEC *tmp1 = ZVNULL, *w = ZVNULL; + Real beta; + int k, limit; + + if ( ! A || ! diag ) + error(E_NULL,"zHfactor"); + if ( diag->dim < A->m - 1 ) + error(E_SIZES,"zHfactor"); + if ( A->m != A->n ) + error(E_SQUARE,"zHfactor"); + limit = A->m - 1; + + tmp1 = zv_resize(tmp1,A->m); + w = zv_resize(w, A->n); + MEM_STAT_REG(tmp1,TYPE_ZVEC); + MEM_STAT_REG(w, TYPE_ZVEC); + + for ( k = 0; k < limit; k++ ) + { + zget_col(A,k,tmp1); + zhhvec(tmp1,k+1,&beta,tmp1,&A->me[k+1][k]); + diag->ve[k] = tmp1->ve[k+1]; + /* printf("zHfactor: k = %d, beta = %g, tmp1 =\n",k,beta); + zv_output(tmp1); */ + + _zhhtrcols(A,k+1,k+1,tmp1,beta,w); + zhhtrrows(A,0 ,k+1,tmp1,beta); + /* printf("# at stage k = %d, A =\n",k); zm_output(A); */ + } + +#ifdef THREADSAFE + ZV_FREE(tmp1); ZV_FREE(w); +#endif + + return (A); +} + +/* zHQunpack -- unpack the compact representation of H and Q of a + Hessenberg factorisation + -- if either H or Q is NULL, then it is not unpacked + -- it can be in situ with HQ == H + -- returns HQ +*/ +ZMAT *zHQunpack(HQ,diag,Q,H) +ZMAT *HQ, *Q, *H; +ZVEC *diag; +{ + int i, j, limit; + Real beta, r_ii, tmp_val; + STATIC ZVEC *tmp1 = ZVNULL, *tmp2 = ZVNULL; + + if ( HQ==ZMNULL || diag==ZVNULL ) + error(E_NULL,"zHQunpack"); + if ( HQ == Q || H == Q ) + error(E_INSITU,"zHQunpack"); + limit = HQ->m - 1; + if ( diag->dim < limit ) + error(E_SIZES,"zHQunpack"); + if ( HQ->m != HQ->n ) + error(E_SQUARE,"zHQunpack"); + + + if ( Q != ZMNULL ) + { + Q = zm_resize(Q,HQ->m,HQ->m); + tmp1 = zv_resize(tmp1,H->m); + tmp2 = zv_resize(tmp2,H->m); + MEM_STAT_REG(tmp1,TYPE_ZVEC); + MEM_STAT_REG(tmp2,TYPE_ZVEC); + + for ( i = 0; i < H->m; i++ ) + { + /* tmp1 = i'th basis vector */ + for ( j = 0; j < H->m; j++ ) + tmp1->ve[j].re = tmp1->ve[j].im = 0.0; + tmp1->ve[i].re = 1.0; + + /* apply H/h transforms in reverse order */ + for ( j = limit-1; j >= 0; j-- ) + { + zget_col(HQ,j,tmp2); + r_ii = zabs(tmp2->ve[j+1]); + tmp2->ve[j+1] = diag->ve[j]; + tmp_val = (r_ii*zabs(diag->ve[j])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + /* printf("zHQunpack: j = %d, beta = %g, tmp2 =\n", + j,beta); + zv_output(tmp2); */ + zhhtrvec(tmp2,beta,j+1,tmp1,tmp1); + } + + /* insert into Q */ + zset_col(Q,i,tmp1); + } + } + + if ( H != ZMNULL ) + { + H = zm_copy(HQ,zm_resize(H,HQ->m,HQ->n)); + + limit = H->m; + for ( i = 1; i < limit; i++ ) + for ( j = 0; j < i-1; j++ ) + H->me[i][j].re = H->me[i][j].im = 0.0; + } + +#ifdef THREADSAFE + ZV_FREE(tmp1); ZV_FREE(tmp2); +#endif + + return HQ; +} + + + diff --git a/zhsehldr.c b/zhsehldr.c new file mode 100644 index 0000000..ebb35d7 --- /dev/null +++ b/zhsehldr.c @@ -0,0 +1,255 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Files for matrix computations + + Householder transformation file. Contains routines for calculating + householder transformations, applying them to vectors and matrices + by both row & column. + + Complex version +*/ + +static char rcsid[] = "$Id: zhsehldr.c,v 1.2 1994/04/07 01:43:47 des Exp $"; + +#include +#include +#include "zmatrix.h" +#include "zmatrix2.h" + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0) + +/* zhhvec -- calulates Householder vector to eliminate all entries after the + i0 entry of the vector vec. It is returned as out. May be in-situ */ +ZVEC *zhhvec(vec,i0,beta,out,newval) +ZVEC *vec,*out; +int i0; +Real *beta; +complex *newval; +{ + complex tmp; + Real norm, abs_val; + + if ( i0 < 0 || i0 >= vec->dim ) + error(E_BOUNDS,"zhhvec"); + out = _zv_copy(vec,out,i0); + tmp = _zin_prod(out,out,i0,Z_CONJ); + if ( tmp.re <= 0.0 ) + { + *beta = 0.0; + *newval = out->ve[i0]; + return (out); + } + norm = sqrt(tmp.re); + abs_val = zabs(out->ve[i0]); + *beta = 1.0/(norm * (norm+abs_val)); + if ( abs_val == 0.0 ) + { + newval->re = norm; + newval->im = 0.0; + } + else + { + abs_val = -norm / abs_val; + newval->re = abs_val*out->ve[i0].re; + newval->im = abs_val*out->ve[i0].im; + } abs_val = -norm / abs_val; + out->ve[i0].re -= newval->re; + out->ve[i0].im -= newval->im; + + return (out); +} + +/* zhhtrvec -- apply Householder transformation to vector -- may be in-situ */ +ZVEC *zhhtrvec(hh,beta,i0,in,out) +ZVEC *hh,*in,*out; /* hh = Householder vector */ +int i0; +double beta; +{ + complex scale, tmp; + /* unsigned int i; */ + + if ( hh==ZVNULL || in==ZVNULL ) + error(E_NULL,"zhhtrvec"); + if ( in->dim != hh->dim ) + error(E_SIZES,"zhhtrvec"); + if ( i0 < 0 || i0 > in->dim ) + error(E_BOUNDS,"zhhvec"); + + tmp = _zin_prod(hh,in,i0,Z_CONJ); + scale.re = -beta*tmp.re; + scale.im = -beta*tmp.im; + out = zv_copy(in,out); + __zmltadd__(&(out->ve[i0]),&(hh->ve[i0]),scale, + (int)(in->dim-i0),Z_NOCONJ); + /************************************************************ + for ( i=i0; idim; i++ ) + out->ve[i] = in->ve[i] - scale*hh->ve[i]; + ************************************************************/ + + return (out); +} + +/* zhhtrrows -- transform a matrix by a Householder vector by rows + starting at row i0 from column j0 + -- in-situ + -- that is, M(i0:m,j0:n) <- M(i0:m,j0:n)(I-beta.hh(j0:n).hh(j0:n)^T) */ +ZMAT *zhhtrrows(M,i0,j0,hh,beta) +ZMAT *M; +int i0, j0; +ZVEC *hh; +double beta; +{ + complex ip, scale; + int i /*, j */; + + if ( M==ZMNULL || hh==ZVNULL ) + error(E_NULL,"zhhtrrows"); + if ( M->n != hh->dim ) + error(E_RANGE,"zhhtrrows"); + if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n ) + error(E_BOUNDS,"zhhtrrows"); + + if ( beta == 0.0 ) return (M); + + /* for each row ... */ + for ( i = i0; i < M->m; i++ ) + { /* compute inner product */ + ip = __zip__(&(M->me[i][j0]),&(hh->ve[j0]), + (int)(M->n-j0),Z_NOCONJ); + /************************************************** + ip = 0.0; + for ( j = j0; j < M->n; j++ ) + ip += M->me[i][j]*hh->ve[j]; + **************************************************/ + scale.re = -beta*ip.re; + scale.im = -beta*ip.im; + /* if ( scale == 0.0 ) */ + if ( is_zero(scale) ) + continue; + + /* do operation */ + __zmltadd__(&(M->me[i][j0]),&(hh->ve[j0]),scale, + (int)(M->n-j0),Z_CONJ); + /************************************************** + for ( j = j0; j < M->n; j++ ) + M->me[i][j] -= scale*hh->ve[j]; + **************************************************/ + } + + return (M); +} + +/* zhhtrcols -- transform a matrix by a Householder vector by columns + starting at row i0 from column j0 + -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n) + -- in-situ + -- calls _zhhtrcols() with the scratch vector w + -- Meschach internal routines should call _zhhtrcols() to + avoid excessive memory allocation/de-allocation +*/ +ZMAT *zhhtrcols(M,i0,j0,hh,beta) +ZMAT *M; +int i0, j0; +ZVEC *hh; +double beta; +{ + /* Real ip, scale; */ + complex scale; + int i /*, k */; + STATIC ZVEC *w = ZVNULL; + + if ( M==ZMNULL || hh==ZVNULL ) + error(E_NULL,"zhhtrcols"); + if ( M->m != hh->dim ) + error(E_SIZES,"zhhtrcols"); + if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n ) + error(E_BOUNDS,"zhhtrcols"); + + if ( beta == 0.0 ) return (M); + + if ( ! w || w->dim < M->n ) + w = zv_resize(w,M->n); + MEM_STAT_REG(w,TYPE_ZVEC); + + M = _zhhtrcols(M,i0,j0,hh,beta,w); + +#ifdef THREADSAFE + ZV_FREE(w); +#endif + + return M; +} + +/* _zhhtrcols -- transform a matrix by a Householder vector by columns + starting at row i0 from column j0 + -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n) + -- in-situ + -- scratch vector w passed as argument + -- raises error if w == NULL */ +ZMAT *_zhhtrcols(M,i0,j0,hh,beta,w) +ZMAT *M; +int i0, j0; +ZVEC *hh; +double beta; +ZVEC *w; +{ + /* Real ip, scale; */ + complex scale; + int i /*, k */; + + if ( M==ZMNULL || hh==ZVNULL ) + error(E_NULL,"zhhtrcols"); + if ( M->m != hh->dim ) + error(E_SIZES,"zhhtrcols"); + if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n ) + error(E_BOUNDS,"zhhtrcols"); + + if ( beta == 0.0 ) return (M); + + if ( w->dim < M->n ) + w = zv_resize(w,M->n); + zv_zero(w); + + for ( i = i0; i < M->m; i++ ) + /* if ( hh->ve[i] != 0.0 ) */ + if ( ! is_zero(hh->ve[i]) ) + __zmltadd__(&(w->ve[j0]),&(M->me[i][j0]),hh->ve[i], + (int)(M->n-j0),Z_CONJ); + for ( i = i0; i < M->m; i++ ) + /* if ( hh->ve[i] != 0.0 ) */ + if ( ! is_zero(hh->ve[i]) ) + { + scale.re = -beta*hh->ve[i].re; + scale.im = -beta*hh->ve[i].im; + __zmltadd__(&(M->me[i][j0]),&(w->ve[j0]),scale, + (int)(M->n-j0),Z_CONJ); + } + + return (M); +} + diff --git a/zlufctr.c b/zlufctr.c new file mode 100644 index 0000000..86d73d8 --- /dev/null +++ b/zlufctr.c @@ -0,0 +1,291 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + Matrix factorisation routines to work with the other matrix files. + Complex version +*/ + +static char rcsid[] = "$Id: zlufctr.c,v 1.3 1996/08/20 20:07:09 stewart Exp $"; + +#include +#include +#include "zmatrix.h" +#include "zmatrix2.h" + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0) + + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* zLUfactor -- Gaussian elimination with scaled partial pivoting + -- Note: returns LU matrix which is A */ +ZMAT *zLUfactor(A,pivot) +ZMAT *A; +PERM *pivot; +{ + unsigned int i, j, m, n; + int i_max, k, k_max; + Real dtemp, max1; + complex **A_v, *A_piv, *A_row, temp; + STATIC VEC *scale = VNULL; + + if ( A==ZMNULL || pivot==PNULL ) + error(E_NULL,"zLUfactor"); + if ( pivot->size != A->m ) + error(E_SIZES,"zLUfactor"); + m = A->m; n = A->n; + scale = v_resize(scale,A->m); + MEM_STAT_REG(scale,TYPE_VEC); + A_v = A->me; + + /* initialise pivot with identity permutation */ + for ( i=0; ipe[i] = i; + + /* set scale parameters */ + for ( i=0; ive[i] = max1; + } + + /* main loop */ + k_max = min(m,n)-1; + for ( k=0; kve[i] > 0.0 ) + { + dtemp = zabs(A_v[i][k])/scale->ve[i]; + if ( dtemp > max1 ) + { max1 = dtemp; i_max = i; } + } + + /* if no pivot then ignore column k... */ + if ( i_max == -1 ) + continue; + + /* do we pivot ? */ + if ( i_max != k ) /* yes we do... */ + { + px_transp(pivot,i_max,k); + for ( j=0; jm != A->n || A->n != b->dim ) + error(E_SIZES,"zLUsolve"); + + x = px_zvec(pivot,b,x); /* x := P.b */ + zLsolve(A,x,x,1.0); /* implicit diagonal = 1 */ + zUsolve(A,x,x,0.0); /* explicit diagonal */ + + return (x); +} + +/* zLUAsolve -- given an LU factorisation in A, solve A^*.x=b */ +ZVEC *zLUAsolve(LU,pivot,b,x) +ZMAT *LU; +PERM *pivot; +ZVEC *b,*x; +{ + if ( ! LU || ! b || ! pivot ) + error(E_NULL,"zLUAsolve"); + if ( LU->m != LU->n || LU->n != b->dim ) + error(E_SIZES,"zLUAsolve"); + + x = zv_copy(b,x); + zUAsolve(LU,x,x,0.0); /* explicit diagonal */ + zLAsolve(LU,x,x,1.0); /* implicit diagonal = 1 */ + pxinv_zvec(pivot,x,x); /* x := P^*.x */ + + return (x); +} + +/* zm_inverse -- returns inverse of A, provided A is not too rank deficient + -- uses LU factorisation */ +ZMAT *zm_inverse(A,out) +ZMAT *A, *out; +{ + int i; + STATIC ZVEC *tmp=ZVNULL, *tmp2=ZVNULL; + STATIC ZMAT *A_cp=ZMNULL; + STATIC PERM *pivot=PNULL; + + if ( ! A ) + error(E_NULL,"zm_inverse"); + if ( A->m != A->n ) + error(E_SQUARE,"zm_inverse"); + if ( ! out || out->m < A->m || out->n < A->n ) + out = zm_resize(out,A->m,A->n); + + A_cp = zm_resize(A_cp,A->m,A->n); + A_cp = zm_copy(A,A_cp); + tmp = zv_resize(tmp,A->m); + tmp2 = zv_resize(tmp2,A->m); + pivot = px_resize(pivot,A->m); + MEM_STAT_REG(A_cp,TYPE_ZMAT); + MEM_STAT_REG(tmp, TYPE_ZVEC); + MEM_STAT_REG(tmp2,TYPE_ZVEC); + MEM_STAT_REG(pivot,TYPE_PERM); + tracecatch(zLUfactor(A_cp,pivot),"zm_inverse"); + for ( i = 0; i < A->n; i++ ) + { + zv_zero(tmp); + tmp->ve[i].re = 1.0; + tmp->ve[i].im = 0.0; + tracecatch(zLUsolve(A_cp,pivot,tmp,tmp2),"zm_inverse"); + zset_col(out,i,tmp2); + } + +#ifdef THREADSAFE + ZV_FREE(tmp); ZV_FREE(tmp2); + ZM_FREE(A_cp); PX_FREE(pivot); +#endif + + return out; +} + +/* zLUcondest -- returns an estimate of the condition number of LU given the + LU factorisation in compact form */ +double zLUcondest(LU,pivot) +ZMAT *LU; +PERM *pivot; +{ + STATIC ZVEC *y = ZVNULL, *z = ZVNULL; + Real cond_est, L_norm, U_norm, norm, sn_inv; + complex sum; + int i, j, n; + + if ( ! LU || ! pivot ) + error(E_NULL,"zLUcondest"); + if ( LU->m != LU->n ) + error(E_SQUARE,"zLUcondest"); + if ( LU->n != pivot->size ) + error(E_SIZES,"zLUcondest"); + + n = LU->n; + y = zv_resize(y,n); + z = zv_resize(z,n); + MEM_STAT_REG(y,TYPE_ZVEC); + MEM_STAT_REG(z,TYPE_ZVEC); + + cond_est = 0.0; /* should never be returned */ + + for ( i = 0; i < n; i++ ) + { + sum.re = 1.0; + sum.im = 0.0; + for ( j = 0; j < i; j++ ) + /* sum -= LU->me[j][i]*y->ve[j]; */ + sum = zsub(sum,zmlt(LU->me[j][i],y->ve[j])); + /* sum -= (sum < 0.0) ? 1.0 : -1.0; */ + sn_inv = 1.0 / zabs(sum); + sum.re += sum.re * sn_inv; + sum.im += sum.im * sn_inv; + if ( is_zero(LU->me[i][i]) ) + return HUGE_VAL; + /* y->ve[i] = sum / LU->me[i][i]; */ + y->ve[i] = zdiv(sum,LU->me[i][i]); + } + + zLAsolve(LU,y,y,1.0); + zLUsolve(LU,pivot,y,z); + + /* now estimate norm of A (even though it is not directly available) */ + /* actually computes ||L||_inf.||U||_inf */ + U_norm = 0.0; + for ( i = 0; i < n; i++ ) + { + norm = 0.0; + for ( j = i; j < n; j++ ) + norm += zabs(LU->me[i][j]); + if ( norm > U_norm ) + U_norm = norm; + } + L_norm = 0.0; + for ( i = 0; i < n; i++ ) + { + norm = 1.0; + for ( j = 0; j < i; j++ ) + norm += zabs(LU->me[i][j]); + if ( norm > L_norm ) + L_norm = norm; + } + + tracecatch(cond_est = U_norm*L_norm*zv_norm_inf(z)/zv_norm_inf(y), + "zLUcondest"); +#ifdef THREADSAFE + ZV_FREE(y); ZV_FREE(z); +#endif + + return cond_est; +} diff --git a/zmachine.c b/zmachine.c new file mode 100644 index 0000000..e9508de --- /dev/null +++ b/zmachine.c @@ -0,0 +1,203 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains basic routines which are used by the functions + involving complex vectors. + These are the routines that should be modified in order to take + full advantage of specialised architectures (pipelining, vector + processors etc). + */ +static char *rcsid = "$Id: zmachine.c,v 1.1 1994/01/13 04:25:41 des Exp $"; + +#include +#include "machine.h" +#include "zmatrix.h" + + +/* __zconj__ -- complex conjugate */ +#ifndef ANSI_C +void __zconj__(zp,len) +complex *zp; +int len; +#else +void __zconj__(complex zp[], int len) +#endif +{ + int i; + + for ( i = 0; i < len; i++ ) + zp[i].im = - zp[i].im; +} + +/* __zip__ -- inner product + -- computes sum_i zp1[i].zp2[i] if flag == 0 + sum_i zp1[i]*.zp2[i] if flag != 0 */ +#ifndef ANSI_C +complex __zip__(zp1,zp2,len,flag) +complex *zp1, *zp2; +int flag, len; +#else +complex __zip__(const complex *zp1, const complex *zp2, int len, int flag) +#endif +{ + complex sum; + int i; + + sum.re = sum.im = 0.0; + if ( flag ) + { + for ( i = 0; i < len; i++ ) + { + sum.re += zp1[i].re*zp2[i].re + zp1[i].im*zp2[i].im; + sum.im += zp1[i].re*zp2[i].im - zp1[i].im*zp2[i].re; + } + } + else + { + for ( i = 0; i < len; i++ ) + { + sum.re += zp1[i].re*zp2[i].re - zp1[i].im*zp2[i].im; + sum.im += zp1[i].re*zp2[i].im + zp1[i].im*zp2[i].re; + } + } + + return sum; +} + +/* __zmltadd__ -- scalar multiply and add i.e. complex saxpy + -- computes zp1[i] += s.zp2[i] if flag == 0 + -- computes zp1[i] += s.zp2[i]* if flag != 0 */ +#ifndef ANSI_C +void __zmltadd__(zp1,zp2,s,len,flag) +complex *zp1, *zp2, s; +int flag, len; +#else +void __zmltadd__(complex *zp1, const complex *zp2, complex s, + int len, int flag) +#endif +{ + int i; + LongReal t_re, t_im; + + if ( ! flag ) + { + for ( i = 0; i < len; i++ ) + { + t_re = zp1[i].re + s.re*zp2[i].re - s.im*zp2[i].im; + t_im = zp1[i].im + s.re*zp2[i].im + s.im*zp2[i].re; + zp1[i].re = t_re; + zp1[i].im = t_im; + } + } + else + { + for ( i = 0; i < len; i++ ) + { + t_re = zp1[i].re + s.re*zp2[i].re + s.im*zp2[i].im; + t_im = zp1[i].im - s.re*zp2[i].im + s.im*zp2[i].re; + zp1[i].re = t_re; + zp1[i].im = t_im; + } + } +} + +/* __zmlt__ scalar complex multiply array c.f. sv_mlt() */ +#ifndef ANSI_C +void __zmlt__(zp,s,out,len) +complex *zp, s, *out; +register int len; +#else +void __zmlt__(const complex *zp, complex s, complex *out, int len) +#endif +{ + int i; + LongReal t_re, t_im; + + for ( i = 0; i < len; i++ ) + { + t_re = s.re*zp[i].re - s.im*zp[i].im; + t_im = s.re*zp[i].im + s.im*zp[i].re; + out[i].re = t_re; + out[i].im = t_im; + } +} + +/* __zadd__ -- add complex arrays c.f. v_add() */ +#ifndef ANSI_C +void __zadd__(zp1,zp2,out,len) +complex *zp1, *zp2, *out; +int len; +#else +void __zadd__(const complex *zp1, const complex *zp2, complex *out, int len) +#endif +{ + int i; + for ( i = 0; i < len; i++ ) + { + out[i].re = zp1[i].re + zp2[i].re; + out[i].im = zp1[i].im + zp2[i].im; + } +} + +/* __zsub__ -- subtract complex arrays c.f. v_sub() */ +#ifndef ANSI_C +void __zsub__(zp1,zp2,out,len) +complex *zp1, *zp2, *out; +int len; +#else +void __zsub__(const complex *zp1, const complex *zp2, complex *out, int len) +#endif +{ + int i; + for ( i = 0; i < len; i++ ) + { + out[i].re = zp1[i].re - zp2[i].re; + out[i].im = zp1[i].im - zp2[i].im; + } +} + +/* __zzero__ -- zeros an array of complex numbers */ +#ifndef ANSI_C +void __zzero__(zp,len) +complex *zp; +int len; +#else +void __zzero__(complex *zp, int len) +#endif +{ + /* if a Real precision zero is equivalent to a string of nulls */ + MEM_ZERO((char *)zp,len*sizeof(complex)); + /* else, need to zero the array entry by entry */ + /****************************** + while ( len-- ) + { + zp->re = zp->im = 0.0; + zp++; + } + ******************************/ +} + diff --git a/zmatio.c b/zmatio.c new file mode 100644 index 0000000..6fa2c2a --- /dev/null +++ b/zmatio.c @@ -0,0 +1,449 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + + +#include +#include +#include "zmatrix.h" + +static char rcsid[] = "$Id: zmatio.c,v 1.1 1994/01/13 04:25:18 des Exp $"; + + + +/* local variables */ +static char line[MAXLINE]; + +/************************************************************************** + Input routines + **************************************************************************/ + +#ifndef ANSI_C +complex z_finput(fp) +FILE *fp; +#else +complex z_finput(FILE *fp) +#endif +{ + int io_code; + complex z; + + skipjunk(fp); + if ( isatty(fileno(fp)) ) + { + do { + fprintf(stderr,"real and imag parts: "); + if ( fgets(line,MAXLINE,fp) == NULL ) + error(E_EOF,"z_finput"); +#if REAL == DOUBLE + io_code = sscanf(line,"%lf%lf",&z.re,&z.im); +#elif REAL == FLOAT + io_code = sscanf(line,"%f%f",&z.re,&z.im); +#endif + + } while ( io_code != 2 ); + } + else +#if REAL == DOUBLE + if ( (io_code=fscanf(fp," (%lf,%lf)",&z.re,&z.im)) < 2 ) +#elif REAL == FLOAT + if ( (io_code=fscanf(fp," (%f,%f)",&z.re,&z.im)) < 2 ) +#endif + error((io_code == EOF) ? E_EOF : E_FORMAT,"z_finput"); + + return z; +} + +#ifndef ANSI_C +ZMAT *zm_finput(fp,a) +FILE *fp; +ZMAT *a; +#else +ZMAT *zm_finput(FILE *fp,ZMAT *a) +#endif +{ + ZMAT *izm_finput(),*bzm_finput(); + + if ( isatty(fileno(fp)) ) + return izm_finput(fp,a); + else + return bzm_finput(fp,a); +} + +/* izm_finput -- interactive input of matrix */ +#ifndef ANSI_C +ZMAT *izm_finput(fp,mat) +FILE *fp; +ZMAT *mat; +#else +ZMAT *izm_finput(FILE *fp, ZMAT *mat) +#endif +{ + char c; + unsigned int i, j, m, n, dynamic; + /* dynamic set to TRUE if memory allocated here */ + + /* get matrix size */ + if ( mat != ZMNULL && mat->mnm; n = mat->n; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"ComplexMatrix: rows cols:"); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"izm_finput"); + } while ( sscanf(line,"%u%u",&m,&n)<2 || m>MAXDIM || n>MAXDIM ); + mat = zm_get(m,n); + } + + /* input elements */ + for ( i=0; ime[i][j].re,mat->me[i][j].im); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"izm_finput"); + if ( (*line == 'b' || *line == 'B') && j > 0 ) + { j--; dynamic = FALSE; goto redo2; } + if ( (*line == 'f' || *line == 'F') && j < n-1 ) + { j++; dynamic = FALSE; goto redo2; } + } while ( *line=='\0' || +#if REAL == DOUBLE + sscanf(line,"%lf%lf", +#elif REAL == FLOAT + sscanf(line,"%f%f", +#endif + &mat->me[i][j].re,&mat->me[i][j].im)<1 ); + fprintf(stderr,"Continue: "); + fscanf(fp,"%c",&c); + if ( c == 'n' || c == 'N' ) + { dynamic = FALSE; goto redo; } + if ( (c == 'b' || c == 'B') /* && i > 0 */ ) + { if ( i > 0 ) + i--; + dynamic = FALSE; goto redo; + } + } + + return (mat); +} + +/* bzm_finput -- batch-file input of matrix */ +#ifndef ANSI_C +ZMAT *bzm_finput(fp,mat) +FILE *fp; +ZMAT *mat; +#else +ZMAT *bzm_finput(FILE *fp,ZMAT *mat) +#endif +{ + unsigned int i,j,m,n,dummy; + int io_code; + + /* get dimension */ + skipjunk(fp); + if ((io_code=fscanf(fp," ComplexMatrix: %u by %u",&m,&n)) < 2 || + m>MAXDIM || n>MAXDIM ) + error(io_code==EOF ? E_EOF : E_FORMAT,"bzm_finput"); + + /* allocate memory if necessary */ + if ( mat==ZMNULL || mat->mnme[i][j].re,&mat->me[i][j].im)) < 2 ) + error(io_code==EOF ? E_EOF : E_FORMAT,"bzm_finput"); + } + } + + return (mat); +} + +#ifndef ANSI_C +ZVEC *zv_finput(fp,x) +FILE *fp; +ZVEC *x; +#else +ZVEC *zv_finput(FILE *fp,ZVEC *x) +#endif +{ + ZVEC *izv_finput(),*bzv_finput(); + + if ( isatty(fileno(fp)) ) + return izv_finput(fp,x); + else + return bzv_finput(fp,x); +} + +/* izv_finput -- interactive input of vector */ +#ifndef ANSI_C +ZVEC *izv_finput(fp,vec) +FILE *fp; +ZVEC *vec; +#else +ZVEC *izv_finput(FILE *fp,ZVEC *vec) +#endif +{ + unsigned int i,dim,dynamic; /* dynamic set if memory allocated here */ + + /* get vector dimension */ + if ( vec != ZVNULL && vec->dimdim; dynamic = FALSE; } + else + { + dynamic = TRUE; + do + { + fprintf(stderr,"ComplexVector: dim: "); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"izv_finput"); + } while ( sscanf(line,"%u",&dim)<1 || dim>MAXDIM ); + vec = zv_get(dim); + } + + /* input elements */ + for ( i=0; ive[i].re,vec->ve[i].im); + if ( fgets(line,MAXLINE,fp)==NULL ) + error(E_INPUT,"izv_finput"); + if ( (*line == 'b' || *line == 'B') && i > 0 ) + { i--; dynamic = FALSE; goto redo; } + if ( (*line == 'f' || *line == 'F') && i < dim-1 ) + { i++; dynamic = FALSE; goto redo; } + } while ( *line=='\0' || +#if REAL == DOUBLE + sscanf(line,"%lf%lf", +#elif REAL == FLOAT + sscanf(line,"%f%f", +#endif + &vec->ve[i].re,&vec->ve[i].im) < 2 ); + + return (vec); +} + +/* bzv_finput -- batch-file input of vector */ +#ifndef ANSI_C +ZVEC *bzv_finput(fp,vec) +FILE *fp; +ZVEC *vec; +#else +ZVEC *bzv_finput(FILE *fp, ZVEC *vec) +#endif +{ + unsigned int i,dim; + int io_code; + + /* get dimension */ + skipjunk(fp); + if ((io_code=fscanf(fp," ComplexVector: dim:%u",&dim)) < 1 || + dim>MAXDIM ) + error(io_code==EOF ? 7 : 6,"bzv_finput"); + + + /* allocate memory if necessary */ + if ( vec==ZVNULL || vec->dimve[i].re,&vec->ve[i].im)) < 2 ) + error(io_code==EOF ? 7 : 6,"bzv_finput"); + + return (vec); +} + +/************************************************************************** + Output routines + **************************************************************************/ +static const char *zformat = " (%14.9g, %14.9g) "; + +#ifndef ANSI_C +char *setzformat(f_string) +char *f_string; +#else +const char *setzformat(const char *f_string) +#endif +{ + const char *old_f_string; + old_f_string = zformat; + if ( f_string != (char *)NULL && *f_string != '\0' ) + zformat = f_string; + + return old_f_string; +} + +#ifndef ANSI_C +void z_foutput(fp,z) +FILE *fp; +complex z; +#else +void z_foutput(FILE *fp,complex z) +#endif +{ + fprintf(fp,zformat,z.re,z.im); + putc('\n',fp); +} + +#ifndef ANSI_C +void zm_foutput(fp,a) +FILE *fp; +ZMAT *a; +#else +void zm_foutput(FILE *fp,ZMAT *a) +#endif +{ + unsigned int i, j, tmp; + + if ( a == ZMNULL ) + { fprintf(fp,"ComplexMatrix: NULL\n"); return; } + fprintf(fp,"ComplexMatrix: %d by %d\n",a->m,a->n); + if ( a->me == (complex **)NULL ) + { fprintf(fp,"NULL\n"); return; } + for ( i=0; im; i++ ) /* for each row... */ + { + fprintf(fp,"row %u: ",i); + for ( j=0, tmp=1; jn; j++, tmp++ ) + { /* for each col in row... */ + fprintf(fp,zformat,a->me[i][j].re,a->me[i][j].im); + if ( ! (tmp % 2) ) putc('\n',fp); + } + if ( tmp % 2 != 1 ) putc('\n',fp); + } +} + +#ifndef ANSI_C +void zv_foutput(fp,x) +FILE *fp; +ZVEC *x; +#else +void zv_foutput(FILE *fp,ZVEC *x) +#endif +{ + unsigned int i, tmp; + + if ( x == ZVNULL ) + { fprintf(fp,"ComplexVector: NULL\n"); return; } + fprintf(fp,"ComplexVector: dim: %d\n",x->dim); + if ( x->ve == (complex *)NULL ) + { fprintf(fp,"NULL\n"); return; } + for ( i=0, tmp=0; idim; i++, tmp++ ) + { + fprintf(fp,zformat,x->ve[i].re,x->ve[i].im); + if ( (tmp % 2) == 1 ) putc('\n',fp); + } + if ( (tmp % 2) != 0 ) putc('\n',fp); +} + +#ifndef ANSI_C +void zm_dump(fp,a) +FILE *fp; +ZMAT *a; +#else +void zm_dump(FILE *fp, ZMAT *a) +#endif +{ + unsigned int i, j, tmp; + + if ( a == ZMNULL ) + { fprintf(fp,"ComplexMatrix: NULL\n"); return; } + fprintf(fp,"ComplexMatrix: %d by %d @ 0x%lx\n",a->m,a->n,(long)a); + fprintf(fp,"\tmax_m = %d, max_n = %d, max_size = %d\n", + a->max_m, a->max_n, a->max_size); + if ( a->me == (complex **)NULL ) + { fprintf(fp,"NULL\n"); return; } + fprintf(fp,"a->me @ 0x%lx\n",(long)(a->me)); + fprintf(fp,"a->base @ 0x%lx\n",(long)(a->base)); + for ( i=0; im; i++ ) /* for each row... */ + { + fprintf(fp,"row %u: @ 0x%lx ",i,(long)(a->me[i])); + for ( j=0, tmp=1; jn; j++, tmp++ ) + { /* for each col in row... */ + fprintf(fp,zformat,a->me[i][j].re,a->me[i][j].im); + if ( ! (tmp % 2) ) putc('\n',fp); + } + if ( tmp % 2 != 1 ) putc('\n',fp); + } +} + + +#ifndef ANSI_C +void zv_dump(fp,x) +FILE *fp; +ZVEC *x; +#else +void zv_dump(FILE *fp,ZVEC *x) +#endif +{ + unsigned int i, tmp; + + if ( ! x ) + { fprintf(fp,"ComplexVector: NULL\n"); return; } + fprintf(fp,"ComplexVector: dim: %d @ 0x%lx\n",x->dim,(long)(x)); + if ( ! x->ve ) + { fprintf(fp,"NULL\n"); return; } + fprintf(fp,"x->ve @ 0x%lx\n",(long)(x->ve)); + for ( i=0, tmp=0; idim; i++, tmp++ ) + { + fprintf(fp,zformat,x->ve[i].re,x->ve[i].im); + if ( tmp % 2 == 1 ) putc('\n',fp); + } + if ( tmp % 2 != 0 ) putc('\n',fp); +} + diff --git a/zmatlab.c b/zmatlab.c new file mode 100644 index 0000000..17a9840 --- /dev/null +++ b/zmatlab.c @@ -0,0 +1,223 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains routines for import/exporting complex data + to/from MATLAB. The main routines are: + ZMAT *zm_save(FILE *fp,ZMAT *A,char *name) + ZVEC *zv_save(FILE *fp,ZVEC *x,char *name) + complex z_save(FILE *fp,complex z,char *name) + ZMAT *zm_load(FILE *fp,char **name) +*/ + +#include +#include "zmatrix.h" +#include "matlab.h" + +static char rcsid[] = "$Id: zmatlab.c,v 1.2 1995/02/14 20:13:27 des Exp $"; + +/* zm_save -- save matrix in ".mat" file for MATLAB + -- returns matrix to be saved */ +ZMAT *zm_save(fp,A,name) +FILE *fp; +ZMAT *A; +char *name; +{ + int i, j; + matlab mat; + + if ( ! A ) + error(E_NULL,"zm_save"); + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = A->m; + mat.n = A->n; + mat.imag = TRUE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ +#if ORDER == ROW_ORDER + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < A->n; j++ ) + fwrite(&(A->me[i][j].re),sizeof(Real),1,fp); + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < A->n; j++ ) + fwrite(&(A->me[i][j].im),sizeof(Real),1,fp); +#else /* column major order: ORDER == COL_ORDER */ + for ( j = 0; j < A->n; j++ ) + for ( i = 0; i < A->m; i++ ) + fwrite(&(A->me[i][j].re),sizeof(Real),1,fp); + for ( j = 0; j < A->n; j++ ) + for ( i = 0; i < A->m; i++ ) + fwrite(&(A->me[i][j].im),sizeof(Real),1,fp); +#endif + + return A; +} + + +/* zv_save -- save vector in ".mat" file for MATLAB + -- saves it as a row vector + -- returns vector to be saved */ +ZVEC *zv_save(fp,x,name) +FILE *fp; +ZVEC *x; +char *name; +{ + int i, j; + matlab mat; + + if ( ! x ) + error(E_NULL,"zv_save"); + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = x->dim; + mat.n = 1; + mat.imag = TRUE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ + for ( i = 0; i < x->dim; i++ ) + fwrite(&(x->ve[i].re),sizeof(Real),1,fp); + for ( i = 0; i < x->dim; i++ ) + fwrite(&(x->ve[i].im),sizeof(Real),1,fp); + + return x; +} + +/* z_save -- saves complex number in ".mat" file for MATLAB + -- returns complex number to be saved */ +complex z_save(fp,z,name) +FILE *fp; +complex z; +char *name; +{ + matlab mat; + + mat.type = 1000*MACH_ID + 100*ORDER + 10*PRECISION + 0; + mat.m = 1; + mat.n = 1; + mat.imag = TRUE; + mat.namlen = (name == (char *)NULL) ? 1 : strlen(name)+1; + + /* write header */ + fwrite(&mat,sizeof(matlab),1,fp); + /* write name */ + if ( name == (char *)NULL ) + fwrite("",sizeof(char),1,fp); + else + fwrite(name,sizeof(char),(int)(mat.namlen),fp); + /* write actual data */ + fwrite(&z,sizeof(complex),1,fp); + + return z; +} + + + +/* zm_load -- loads in a ".mat" file variable as produced by MATLAB + -- matrix returned; imaginary parts ignored */ +ZMAT *zm_load(fp,name) +FILE *fp; +char **name; +{ + ZMAT *A; + int i; + int m_flag, o_flag, p_flag, t_flag; + float f_temp; + double d_temp; + matlab mat; + + if ( fread(&mat,sizeof(matlab),1,fp) != 1 ) + error(E_FORMAT,"zm_load"); + if ( mat.type >= 10000 ) /* don't load a sparse matrix! */ + error(E_FORMAT,"zm_load"); + m_flag = (mat.type/1000) % 10; + o_flag = (mat.type/100) % 10; + p_flag = (mat.type/10) % 10; + t_flag = (mat.type) % 10; + if ( m_flag != MACH_ID ) + error(E_FORMAT,"zm_load"); + if ( t_flag != 0 ) + error(E_FORMAT,"zm_load"); + if ( p_flag != DOUBLE_PREC && p_flag != SINGLE_PREC ) + error(E_FORMAT,"zm_load"); + *name = (char *)malloc((unsigned)(mat.namlen)+1); + if ( fread(*name,sizeof(char),(unsigned)(mat.namlen),fp) == 0 ) + error(E_FORMAT,"zm_load"); + A = zm_get((unsigned)(mat.m),(unsigned)(mat.n)); + for ( i = 0; i < A->m*A->n; i++ ) + { + if ( p_flag == DOUBLE_PREC ) + fread(&d_temp,sizeof(double),1,fp); + else + { + fread(&f_temp,sizeof(float),1,fp); + d_temp = f_temp; + } + if ( o_flag == ROW_ORDER ) + A->me[i / A->n][i % A->n].re = d_temp; + else if ( o_flag == COL_ORDER ) + A->me[i % A->m][i / A->m].re = d_temp; + else + error(E_FORMAT,"zm_load"); + } + + if ( mat.imag ) /* skip imaginary part */ + for ( i = 0; i < A->m*A->n; i++ ) + { + if ( p_flag == DOUBLE_PREC ) + fread(&d_temp,sizeof(double),1,fp); + else + { + fread(&f_temp,sizeof(float),1,fp); + d_temp = f_temp; + } + if ( o_flag == ROW_ORDER ) + A->me[i / A->n][i % A->n].im = d_temp; + else if ( o_flag == COL_ORDER ) + A->me[i % A->m][i / A->m].im = d_temp; + else + error(E_FORMAT,"zm_load"); + } + + return A; +} + diff --git a/zmatop.c b/zmatop.c new file mode 100644 index 0000000..039b1d4 --- /dev/null +++ b/zmatop.c @@ -0,0 +1,615 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + + +#include +#include "zmatrix.h" + +static char rcsid[] = "$Id: zmatop.c,v 1.2 1995/03/27 15:49:03 des Exp $"; + + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0) + +/* zm_add -- matrix addition -- may be in-situ */ +ZMAT *zm_add(mat1,mat2,out) +ZMAT *mat1,*mat2,*out; +{ + unsigned int m,n,i; + + if ( mat1==ZMNULL || mat2==ZMNULL ) + error(E_NULL,"zm_add"); + if ( mat1->m != mat2->m || mat1->n != mat2->n ) + error(E_SIZES,"zm_add"); + if ( out==ZMNULL || out->m != mat1->m || out->n != mat1->n ) + out = zm_resize(out,mat1->m,mat1->n); + m = mat1->m; n = mat1->n; + for ( i=0; ime[i],mat2->me[i],out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = mat1->me[i][j]+mat2->me[i][j]; + **************************************************/ + } + + return (out); +} + +/* zm_sub -- matrix subtraction -- may be in-situ */ +ZMAT *zm_sub(mat1,mat2,out) +ZMAT *mat1,*mat2,*out; +{ + unsigned int m,n,i; + + if ( mat1==ZMNULL || mat2==ZMNULL ) + error(E_NULL,"zm_sub"); + if ( mat1->m != mat2->m || mat1->n != mat2->n ) + error(E_SIZES,"zm_sub"); + if ( out==ZMNULL || out->m != mat1->m || out->n != mat1->n ) + out = zm_resize(out,mat1->m,mat1->n); + m = mat1->m; n = mat1->n; + for ( i=0; ime[i],mat2->me[i],out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = mat1->me[i][j]-mat2->me[i][j]; + **************************************************/ + } + + return (out); +} + +/* + Note: In the following routines, "adjoint" means complex conjugate + transpose: + A* = conjugate(A^T) + */ + +/* zm_mlt -- matrix-matrix multiplication */ +ZMAT *zm_mlt(A,B,OUT) +ZMAT *A,*B,*OUT; +{ + unsigned int i, /* j, */ k, m, n, p; + complex **A_v, **B_v /*, *B_row, *OUT_row, sum, tmp */; + + if ( A==ZMNULL || B==ZMNULL ) + error(E_NULL,"zm_mlt"); + if ( A->n != B->m ) + error(E_SIZES,"zm_mlt"); + if ( A == OUT || B == OUT ) + error(E_INSITU,"zm_mlt"); + m = A->m; n = A->n; p = B->n; + A_v = A->me; B_v = B->me; + + if ( OUT==ZMNULL || OUT->m != A->m || OUT->n != B->n ) + OUT = zm_resize(OUT,A->m,B->n); + + /**************************************************************** + for ( i=0; ime[i][j] = sum; + } + ****************************************************************/ + zm_zero(OUT); + for ( i=0; ime[i],B_v[k],A_v[i][k],(int)p,Z_NOCONJ); + /************************************************** + B_row = B_v[k]; OUT_row = OUT->me[i]; + for ( j=0; jn != B->n ) + error(E_SIZES,"zmma_mlt"); + if ( ! OUT || OUT->m != A->m || OUT->n != B->m ) + OUT = zm_resize(OUT,A->m,B->m); + + limit = A->n; + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < B->m; j++ ) + { + OUT->me[i][j] = __zip__(B->me[j],A->me[i],(int)limit,Z_CONJ); + /************************************************** + sum = 0.0; + A_row = A->me[i]; + B_row = B->me[j]; + for ( k = 0; k < limit; k++ ) + sum += (*A_row++)*(*B_row++); + OUT->me[i][j] = sum; + **************************************************/ + } + + return OUT; +} + +/* zmam_mlt -- matrix adjoint-matrix multiplication + -- A*.B is returned, result stored in OUT */ +ZMAT *zmam_mlt(A,B,OUT) +ZMAT *A, *B, *OUT; +{ + int i, k, limit; + /* complex *B_row, *OUT_row, multiplier; */ + complex tmp; + + if ( ! A || ! B ) + error(E_NULL,"zmam_mlt"); + if ( A == OUT || B == OUT ) + error(E_INSITU,"zmam_mlt"); + if ( A->m != B->m ) + error(E_SIZES,"zmam_mlt"); + if ( ! OUT || OUT->m != A->n || OUT->n != B->n ) + OUT = zm_resize(OUT,A->n,B->n); + + limit = B->n; + zm_zero(OUT); + for ( k = 0; k < A->m; k++ ) + for ( i = 0; i < A->n; i++ ) + { + tmp.re = A->me[k][i].re; + tmp.im = - A->me[k][i].im; + if ( ! is_zero(tmp) ) + __zmltadd__(OUT->me[i],B->me[k],tmp,(int)limit,Z_NOCONJ); + } + + return OUT; +} + +/* zmv_mlt -- matrix-vector multiplication + -- Note: b is treated as a column vector */ +ZVEC *zmv_mlt(A,b,out) +ZMAT *A; +ZVEC *b,*out; +{ + unsigned int i, m, n; + complex **A_v, *b_v /*, *A_row */; + /* register complex sum; */ + + if ( A==ZMNULL || b==ZVNULL ) + error(E_NULL,"zmv_mlt"); + if ( A->n != b->dim ) + error(E_SIZES,"zmv_mlt"); + if ( b == out ) + error(E_INSITU,"zmv_mlt"); + if ( out == ZVNULL || out->dim != A->m ) + out = zv_resize(out,A->m); + + m = A->m; n = A->n; + A_v = A->me; b_v = b->ve; + for ( i=0; ive[i] = __zip__(A_v[i],b_v,(int)n,Z_NOCONJ); + /************************************************** + A_row = A_v[i]; b_v = b->ve; + for ( j=0; jve[i] = sum; + **************************************************/ + } + + return out; +} + +/* zsm_mlt -- scalar-matrix multiply -- may be in-situ */ +ZMAT *zsm_mlt(scalar,matrix,out) +complex scalar; +ZMAT *matrix,*out; +{ + unsigned int m,n,i; + + if ( matrix==ZMNULL ) + error(E_NULL,"zsm_mlt"); + if ( out==ZMNULL || out->m != matrix->m || out->n != matrix->n ) + out = zm_resize(out,matrix->m,matrix->n); + m = matrix->m; n = matrix->n; + for ( i=0; ime[i],scalar,out->me[i],(int)n); + /************************************************** + for ( j=0; jme[i][j] = scalar*matrix->me[i][j]; + **************************************************/ + return (out); +} + +/* zvm_mlt -- vector adjoint-matrix multiplication */ +ZVEC *zvm_mlt(A,b,out) +ZMAT *A; +ZVEC *b,*out; +{ + unsigned int j,m,n; + /* complex sum,**A_v,*b_v; */ + + if ( A==ZMNULL || b==ZVNULL ) + error(E_NULL,"zvm_mlt"); + if ( A->m != b->dim ) + error(E_SIZES,"zvm_mlt"); + if ( b == out ) + error(E_INSITU,"zvm_mlt"); + if ( out == ZVNULL || out->dim != A->n ) + out = zv_resize(out,A->n); + + m = A->m; n = A->n; + + zv_zero(out); + for ( j = 0; j < m; j++ ) + if ( b->ve[j].re != 0.0 || b->ve[j].im != 0.0 ) + __zmltadd__(out->ve,A->me[j],b->ve[j],(int)n,Z_CONJ); + /************************************************** + A_v = A->me; b_v = b->ve; + for ( j=0; jve[j] = sum; + } + **************************************************/ + + return out; +} + +/* zm_adjoint -- adjoint matrix */ +ZMAT *zm_adjoint(in,out) +ZMAT *in, *out; +{ + int i, j; + int in_situ; + complex tmp; + + if ( in == ZMNULL ) + error(E_NULL,"zm_adjoint"); + if ( in == out && in->n != in->m ) + error(E_INSITU2,"zm_adjoint"); + in_situ = ( in == out ); + if ( out == ZMNULL || out->m != in->n || out->n != in->m ) + out = zm_resize(out,in->n,in->m); + + if ( ! in_situ ) + { + for ( i = 0; i < in->m; i++ ) + for ( j = 0; j < in->n; j++ ) + { + out->me[j][i].re = in->me[i][j].re; + out->me[j][i].im = - in->me[i][j].im; + } + } + else + { + for ( i = 0 ; i < in->m; i++ ) + { + for ( j = 0; j < i; j++ ) + { + tmp.re = in->me[i][j].re; + tmp.im = in->me[i][j].im; + in->me[i][j].re = in->me[j][i].re; + in->me[i][j].im = - in->me[j][i].im; + in->me[j][i].re = tmp.re; + in->me[j][i].im = - tmp.im; + } + in->me[i][i].im = - in->me[i][i].im; + } + } + + return out; +} + +/* zswap_rows -- swaps rows i and j of matrix A upto column lim */ +ZMAT *zswap_rows(A,i,j,lo,hi) +ZMAT *A; +int i, j, lo, hi; +{ + int k; + complex **A_me, tmp; + + if ( ! A ) + error(E_NULL,"swap_rows"); + if ( i < 0 || j < 0 || i >= A->m || j >= A->m ) + error(E_SIZES,"swap_rows"); + lo = max(0,lo); + hi = min(hi,A->n-1); + A_me = A->me; + + for ( k = lo; k <= hi; k++ ) + { + tmp = A_me[k][i]; + A_me[k][i] = A_me[k][j]; + A_me[k][j] = tmp; + } + return A; +} + +/* zswap_cols -- swap columns i and j of matrix A upto row lim */ +ZMAT *zswap_cols(A,i,j,lo,hi) +ZMAT *A; +int i, j, lo, hi; +{ + int k; + complex **A_me, tmp; + + if ( ! A ) + error(E_NULL,"swap_cols"); + if ( i < 0 || j < 0 || i >= A->n || j >= A->n ) + error(E_SIZES,"swap_cols"); + lo = max(0,lo); + hi = min(hi,A->m-1); + A_me = A->me; + + for ( k = lo; k <= hi; k++ ) + { + tmp = A_me[i][k]; + A_me[i][k] = A_me[j][k]; + A_me[j][k] = tmp; + } + return A; +} + +/* mz_mltadd -- matrix-scalar multiply and add + -- may be in situ + -- returns out == A1 + s*A2 */ +ZMAT *mz_mltadd(A1,A2,s,out) +ZMAT *A1, *A2, *out; +complex s; +{ + /* register complex *A1_e, *A2_e, *out_e; */ + /* register int j; */ + int i, m, n; + + if ( ! A1 || ! A2 ) + error(E_NULL,"mz_mltadd"); + if ( A1->m != A2->m || A1->n != A2->n ) + error(E_SIZES,"mz_mltadd"); + + if ( out != A1 && out != A2 ) + out = zm_resize(out,A1->m,A1->n); + + if ( s.re == 0.0 && s.im == 0.0 ) + return zm_copy(A1,out); + if ( s.re == 1.0 && s.im == 0.0 ) + return zm_add(A1,A2,out); + + out = zm_copy(A1,out); + + m = A1->m; n = A1->n; + for ( i = 0; i < m; i++ ) + { + __zmltadd__(out->me[i],A2->me[i],s,(int)n,Z_NOCONJ); + /************************************************** + A1_e = A1->me[i]; + A2_e = A2->me[i]; + out_e = out->me[i]; + for ( j = 0; j < n; j++ ) + out_e[j] = A1_e[j] + s*A2_e[j]; + **************************************************/ + } + + return out; +} + +/* zmv_mltadd -- matrix-vector multiply and add + -- may not be in situ + -- returns out == v1 + alpha*A*v2 */ +ZVEC *zmv_mltadd(v1,v2,A,alpha,out) +ZVEC *v1, *v2, *out; +ZMAT *A; +complex alpha; +{ + /* register int j; */ + int i, m, n; + complex tmp, *v2_ve, *out_ve; + + if ( ! v1 || ! v2 || ! A ) + error(E_NULL,"zmv_mltadd"); + if ( out == v2 ) + error(E_INSITU,"zmv_mltadd"); + if ( v1->dim != A->m || v2->dim != A-> n ) + error(E_SIZES,"zmv_mltadd"); + + tracecatch(out = zv_copy(v1,out),"zmv_mltadd"); + + v2_ve = v2->ve; out_ve = out->ve; + m = A->m; n = A->n; + + if ( alpha.re == 0.0 && alpha.im == 0.0 ) + return out; + + for ( i = 0; i < m; i++ ) + { + tmp = __zip__(A->me[i],v2_ve,(int)n,Z_NOCONJ); + out_ve[i].re += alpha.re*tmp.re - alpha.im*tmp.im; + out_ve[i].im += alpha.re*tmp.im + alpha.im*tmp.re; + /************************************************** + A_e = A->me[i]; + sum = 0.0; + for ( j = 0; j < n; j++ ) + sum += A_e[j]*v2_ve[j]; + out_ve[i] = v1->ve[i] + alpha*sum; + **************************************************/ + } + + return out; +} + +/* zvm_mltadd -- vector-matrix multiply and add a la zvm_mlt() + -- may not be in situ + -- returns out == v1 + v2*.A */ +ZVEC *zvm_mltadd(v1,v2,A,alpha,out) +ZVEC *v1, *v2, *out; +ZMAT *A; +complex alpha; +{ + int /* i, */ j, m, n; + complex tmp, /* *A_e, */ *out_ve; + + if ( ! v1 || ! v2 || ! A ) + error(E_NULL,"zvm_mltadd"); + if ( v2 == out ) + error(E_INSITU,"zvm_mltadd"); + if ( v1->dim != A->n || A->m != v2->dim ) + error(E_SIZES,"zvm_mltadd"); + + tracecatch(out = zv_copy(v1,out),"zvm_mltadd"); + + out_ve = out->ve; m = A->m; n = A->n; + for ( j = 0; j < m; j++ ) + { + /* tmp = zmlt(v2->ve[j],alpha); */ + tmp.re = v2->ve[j].re*alpha.re - v2->ve[j].im*alpha.im; + tmp.im = v2->ve[j].re*alpha.im + v2->ve[j].im*alpha.re; + if ( tmp.re != 0.0 || tmp.im != 0.0 ) + __zmltadd__(out_ve,A->me[j],tmp,(int)n,Z_CONJ); + /************************************************** + A_e = A->me[j]; + for ( i = 0; i < n; i++ ) + out_ve[i] += A_e[i]*tmp; + **************************************************/ + } + + return out; +} + +/* zget_col -- gets a specified column of a matrix; returned as a vector */ +ZVEC *zget_col(mat,col,vec) +int col; +ZMAT *mat; +ZVEC *vec; +{ + unsigned int i; + + if ( mat==ZMNULL ) + error(E_NULL,"zget_col"); + if ( col < 0 || col >= mat->n ) + error(E_RANGE,"zget_col"); + if ( vec==ZVNULL || vec->dimm ) + vec = zv_resize(vec,mat->m); + + for ( i=0; im; i++ ) + vec->ve[i] = mat->me[i][col]; + + return (vec); +} + +/* zget_row -- gets a specified row of a matrix and retruns it as a vector */ +ZVEC *zget_row(mat,row,vec) +int row; +ZMAT *mat; +ZVEC *vec; +{ + int /* i, */ lim; + + if ( mat==ZMNULL ) + error(E_NULL,"zget_row"); + if ( row < 0 || row >= mat->m ) + error(E_RANGE,"zget_row"); + if ( vec==ZVNULL || vec->dimn ) + vec = zv_resize(vec,mat->n); + + lim = min(mat->n,vec->dim); + + /* for ( i=0; in; i++ ) */ + /* vec->ve[i] = mat->me[row][i]; */ + MEMCOPY(mat->me[row],vec->ve,lim,complex); + + return (vec); +} + +/* zset_col -- sets column of matrix to values given in vec (in situ) */ +ZMAT *zset_col(mat,col,vec) +ZMAT *mat; +ZVEC *vec; +int col; +{ + unsigned int i,lim; + + if ( mat==ZMNULL || vec==ZVNULL ) + error(E_NULL,"zset_col"); + if ( col < 0 || col >= mat->n ) + error(E_RANGE,"zset_col"); + lim = min(mat->m,vec->dim); + for ( i=0; ime[i][col] = vec->ve[i]; + + return (mat); +} + +/* zset_row -- sets row of matrix to values given in vec (in situ) */ +ZMAT *zset_row(mat,row,vec) +ZMAT *mat; +ZVEC *vec; +int row; +{ + unsigned int /* j, */ lim; + + if ( mat==ZMNULL || vec==ZVNULL ) + error(E_NULL,"zset_row"); + if ( row < 0 || row >= mat->m ) + error(E_RANGE,"zset_row"); + lim = min(mat->n,vec->dim); + /* for ( j=j0; jme[row][j] = vec->ve[j]; */ + MEMCOPY(vec->ve,mat->me[row],lim,complex); + + return (mat); +} + +/* zm_rand -- randomise a complex matrix; uniform in [0,1)+[0,1)*i */ +ZMAT *zm_rand(A) +ZMAT *A; +{ + int i; + + if ( ! A ) + error(E_NULL,"zm_rand"); + + for ( i = 0; i < A->m; i++ ) + mrandlist((Real *)(A->me[i]),2*A->n); + + return A; +} diff --git a/zmatrix.h b/zmatrix.h new file mode 100644 index 0000000..1bd635c --- /dev/null +++ b/zmatrix.h @@ -0,0 +1,321 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* Main include file for zmeschach library -- complex vectors and matrices */ + +#ifndef ZMATRIXH +#define ZMATRIXH + +#include "matrix.h" + + + /* Type definitions for complex vectors and matrices */ + + +/* complex definition */ +typedef struct { + Real re,im; + } complex; + +/* complex vector definition */ +typedef struct { + unsigned int dim, max_dim; + complex *ve; + } ZVEC; + +/* complex matrix definition */ +typedef struct { + unsigned int m, n; + unsigned int max_m, max_n, max_size; + complex *base; /* base is base of alloc'd mem */ + complex **me; + } ZMAT; + +#define ZVNULL ((ZVEC *)NULL) +#define ZMNULL ((ZMAT *)NULL) + +#define Z_CONJ 1 +#define Z_NOCONJ 0 + + +#define zm_entry(A,i,j) zm_get_val(A,i,j) +#define zv_entry(x,i) zv_get_val(x,i) +#ifdef DEBUG +#define zm_set_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] = (val) : (error(E_BOUNDS,"zm_set_val"), zmake(0.0,0.0))) +#define zm_add_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] = zadd((A)->me[(i)][(j)],(val)) : \ + (error(E_BOUNDS,"zm_add_val"), zmake(0.0,0.0))) +#define zm_sub_val(A,i,j,val) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] = zsub((A)->me[(i)][(j)],(val)) : \ + (error(E_BOUNDS,"zm_sub_val"), zmake(0.0,0.0))) +#define zm_get_val(A,i,j) ( m_chk_idx(A,i,j) ? \ + (A)->me[(i)][(j)] : (error(E_BOUNDS,"zm_get_val"), zmake(0.0,0.0))) +#define zv_set_val(x,i,val) ( v_chk_idx(x,i) ? (x)->ve[(i)] = (val) : \ + (error(E_BOUNDS,"zv_set_val"), zmake(0.0,0.0))) +#define zv_add_val(x,i,val) ( v_chk_idx(x,i) ? \ + (x)->ve[(i)] = zadd((x)->ve[(i)],(val)) : \ + (error(E_BOUNDS,"zv_set_val"), zmake(0.0,0.0))) +#define zv_sub_val(x,i,val) ( v_chk_idx(x,i) ? \ + (x)->ve[(i)] = zsub((x)->ve[(i)],(val)) : \ + (error(E_BOUNDS,"zv_set_val"), zmake(0.0,0.0))) +#define zv_get_val(x,i) ( v_chk_idx(x,i) ? (x)->ve[(i)] : \ + (error(E_BOUNDS,"zv_get_val"), zmake(0.0,0.0))) +#else /* no DEBUG */ +#define zm_set_val(A,i,j,val) ((A)->me[(i)][(j)] = (val)) +#define zm_add_val(A,i,j,val) ((A)->me[(i)][(j)] = zadd((A)->me[(i)][(j)],(val))) +#define zm_sub_val(A,i,j,val) ((A)->me[(i)][(j)] = zsub((A)->me[(i)][(j)],(val))) +#define zm_get_val(A,i,j) ((A)->me[(i)][(j)]) +#define zv_set_val(x,i,val) ((x)->ve[(i)] = (val)) +#define zv_add_val(x,i,val) ((x)->ve[(i)] = zadd((x)->ve[(i)],(val))) +#define zv_sub_val(x,i,val) ((x)->ve[(i)] = zsub((x)->ve[(i)],(val))) +#define zv_get_val(x,i) ((x)->ve[(i)]) +#endif /* DEBUG */ + +/* memory functions */ + +#ifdef ANSI_C +int zv_get_vars(int dim,...); +int zm_get_vars(int m,int n,...); +int zv_resize_vars(int new_dim,...); +int zm_resize_vars(int m,int n,...); +int zv_free_vars(ZVEC **,...); +int zm_free_vars(ZMAT **,...); + +#elif VARARGS +int zv_get_vars(); +int zm_get_vars(); +int zv_resize_vars(); +int zm_resize_vars(); +int zv_free_vars(); +int zm_free_vars(); + +#endif + + + + +#ifdef ANSI_C +extern ZMAT *_zm_copy(const ZMAT *in,ZMAT *out, int i0, int j0); +extern ZMAT * zm_move(const ZMAT *, int, int, int, int, ZMAT *, int, int); +extern ZMAT *zvm_move(const ZVEC *, int, ZMAT *, int, int, int, int); +extern ZVEC *_zv_copy(const ZVEC *in,ZVEC *out,int i0); +extern ZVEC * zv_move(const ZVEC *, int, int, ZVEC *, int); +extern ZVEC *zmv_move(const ZMAT *, int, int, int, int, ZVEC *, int); +extern complex z_finput(FILE *fp); +extern ZMAT *zm_finput(FILE *fp,ZMAT *a); +extern ZVEC *zv_finput(FILE *fp,ZVEC *x); +extern ZMAT *zm_add(ZMAT *mat1,ZMAT *mat2,ZMAT *out); +extern ZMAT *zm_sub(ZMAT *mat1,ZMAT *mat2,ZMAT *out); +extern ZMAT *zm_mlt(ZMAT *A,ZMAT *B,ZMAT *OUT); +extern ZMAT *zmma_mlt(ZMAT *A,ZMAT *B,ZMAT *OUT); +extern ZMAT *zmam_mlt(ZMAT *A,ZMAT *B,ZMAT *OUT); +extern ZVEC *zmv_mlt(ZMAT *A,ZVEC *b,ZVEC *out); +extern ZMAT *zsm_mlt(complex scalar,ZMAT *matrix,ZMAT *out); +extern ZVEC *zvm_mlt(ZMAT *A,ZVEC *b,ZVEC *out); +extern ZMAT *zm_adjoint(ZMAT *in,ZMAT *out); +extern ZMAT *zswap_rows(ZMAT *A,int i,int j,int lo,int hi); +extern ZMAT *zswap_cols(ZMAT *A,int i,int j,int lo,int hi); +extern ZMAT *mz_mltadd(ZMAT *A1,ZMAT *A2,complex s,ZMAT *out); +extern ZVEC *zmv_mltadd(ZVEC *v1,ZVEC *v2,ZMAT *A,complex alpha,ZVEC *out); +extern ZVEC *zvm_mltadd(ZVEC *v1,ZVEC *v2,ZMAT *A,complex alpha,ZVEC *out); +extern ZVEC *zv_zero(ZVEC *x); +extern ZMAT *zm_zero(ZMAT *A); +extern ZMAT *zm_get(int m,int n); +extern ZVEC *zv_get(int dim); +extern ZMAT *zm_resize(ZMAT *A,int new_m,int new_n); +extern complex _zin_prod(const ZVEC *x, const ZVEC *y,unsigned int i0,unsigned int flag); +extern ZVEC *zv_resize(ZVEC *x,int new_dim); +extern ZVEC *zv_mlt(complex scalar,const ZVEC *vector,ZVEC *out); +extern ZVEC *zv_add(const ZVEC *vec1,const ZVEC *vec2,ZVEC *out); +extern ZVEC *zv_mltadd(const ZVEC *v1,const ZVEC *v2,complex scale,ZVEC *out); +extern ZVEC *zv_sub(const ZVEC *vec1,const ZVEC *vec2,ZVEC *out); +#ifdef PROTOTYPES_IN_STRUCT +extern ZVEC *zv_map(complex (*f)(),const ZVEC *x,ZVEC *out); +extern ZVEC *_zv_map(complex (*f)(),void *params,const ZVEC *x,ZVEC *out); +#else +extern ZVEC *zv_map(complex (*f)(complex),const ZVEC *x,ZVEC *out); +extern ZVEC *_zv_map(complex (*f)(void *,complex),void *params,const ZVEC *x,ZVEC *out); +#endif +extern ZVEC *zv_lincomb(int n,const ZVEC *v[],const complex a[],ZVEC *out); +extern ZVEC *zv_linlist(ZVEC *out,ZVEC *v1,complex a1,...); +extern ZVEC *zv_star(const ZVEC *x1, const ZVEC *x2, ZVEC *out); +extern ZVEC *zv_slash(const ZVEC *x1, const ZVEC *x2, ZVEC *out); +extern complex zv_sum(const ZVEC *x); +extern int zm_free(ZMAT *mat); +extern int zv_free(ZVEC *vec); + +extern ZVEC *zv_rand(ZVEC *x); +extern ZMAT *zm_rand(ZMAT *A); + +extern ZVEC *zget_row(ZMAT *A, int i, ZVEC *out); +extern ZVEC *zget_col(ZMAT *A, int j, ZVEC *out); +extern ZMAT *zset_row(ZMAT *A, int i, ZVEC *in); +extern ZMAT *zset_col(ZMAT *A, int j, ZVEC *in); + +extern ZVEC *px_zvec(PERM *pi, ZVEC *in, ZVEC *out); +extern ZVEC *pxinv_zvec(PERM *pi, ZVEC *in, ZVEC *out); + +extern void __zconj__(complex zp[], int len); +extern complex __zip__(const complex zp1[], const complex zp2[], + int len,int flag); +extern void __zmltadd__(complex zp1[], const complex zp2[], + complex s,int len,int flag); +extern void __zmlt__(const complex zp[],complex s,complex out[],int len); +extern void __zadd__(const complex zp1[],const complex zp2[], + complex out[],int len); +extern void __zsub__(const complex zp1[],const complex zp2[], + complex out[],int len); +extern void __zzero__(complex zp[],int len); +extern void z_foutput(FILE *fp,complex z); +extern void zm_foutput(FILE *fp,ZMAT *a); +extern void zv_foutput(FILE *fp,ZVEC *x); +extern void zm_dump(FILE *fp,ZMAT *a); +extern void zv_dump(FILE *fp,ZVEC *x); + +extern double _zv_norm1(ZVEC *x, VEC *scale); +extern double _zv_norm2(ZVEC *x, VEC *scale); +extern double _zv_norm_inf(ZVEC *x, VEC *scale); +extern double zm_norm1(ZMAT *A); +extern double zm_norm_inf(ZMAT *A); +extern double zm_norm_frob(ZMAT *A); + +complex zmake(double real, double imag); +double zabs(complex z); +complex zadd(complex z1,complex z2); +complex zsub(complex z1,complex z2); +complex zmlt(complex z1,complex z2); +complex zinv(complex z); +complex zdiv(complex z1,complex z2); +complex zsqrt(complex z); +complex zexp(complex z); +complex zlog(complex z); +complex zconj(complex z); +complex zneg(complex z); +#else +extern ZMAT *_zm_copy(); +extern ZVEC *_zv_copy(); +extern ZMAT *zm_finput(); +extern ZVEC *zv_finput(); +extern ZMAT *zm_add(); +extern ZMAT *zm_sub(); +extern ZMAT *zm_mlt(); +extern ZMAT *zmma_mlt(); +extern ZMAT *zmam_mlt(); +extern ZVEC *zmv_mlt(); +extern ZMAT *zsm_mlt(); +extern ZVEC *zvm_mlt(); +extern ZMAT *zm_adjoint(); +extern ZMAT *zswap_rows(); +extern ZMAT *zswap_cols(); +extern ZMAT *mz_mltadd(); +extern ZVEC *zmv_mltadd(); +extern ZVEC *zvm_mltadd(); +extern ZVEC *zv_zero(); +extern ZMAT *zm_zero(); +extern ZMAT *zm_get(); +extern ZVEC *zv_get(); +extern ZMAT *zm_resize(); +extern ZVEC *zv_resize(); +extern complex _zin_prod(); +extern ZVEC *zv_mlt(); +extern ZVEC *zv_add(); +extern ZVEC *zv_mltadd(); +extern ZVEC *zv_sub(); +extern ZVEC *zv_map(); +extern ZVEC *_zv_map(); +extern ZVEC *zv_lincomb(); +extern ZVEC *zv_linlist(); +extern ZVEC *zv_star(); +extern ZVEC *zv_slash(); + +extern ZVEC *px_zvec(); +extern ZVEC *pxinv_zvec(); + +extern ZVEC *zv_rand(); +extern ZMAT *zm_rand(); + +extern ZVEC *zget_row(); +extern ZVEC *zget_col(); +extern ZMAT *zset_row(); +extern ZMAT *zset_col(); + +extern int zm_free(); +extern int zv_free(); +extern void __zconj__(); +extern complex __zip__(); +extern void __zmltadd__(); +extern void __zmlt__(); +extern void __zadd__(); +extern void __zsub__(); +extern void __zzero__(); +extern void zm_foutput(); +extern void zv_foutput(); +extern void zm_dump(); +extern void zv_dump(); + +extern double _zv_norm1(); +extern double _zv_norm2(); +extern double _zv_norm_inf(); +extern double zm_norm1(); +extern double zm_norm_inf(); +extern double zm_norm_frob(); + +complex zmake(); +double zabs(); +complex zadd(); +complex zsub(); +complex zmlt(); +complex zinv(); +complex zdiv(); +complex zsqrt(); +complex zexp(); +complex zlog(); +complex zconj(); +complex zneg(); +#endif + +#define zv_copy(x,y) _zv_copy(x,y,0) +#define zm_copy(A,B) _zm_copy(A,B,0,0) + +#define z_input() z_finput(stdin) +#define zv_input(x) zv_finput(stdin,x) +#define zm_input(A) zm_finput(stdin,A) +#define z_output(z) z_foutput(stdout,z) +#define zv_output(x) zv_foutput(stdout,x) +#define zm_output(A) zm_foutput(stdout,A) + +#define ZV_FREE(x) ( zv_free(x), (x) = ZVNULL ) +#define ZM_FREE(A) ( zm_free(A), (A) = ZMNULL ) + +#define zin_prod(x,y) _zin_prod(x,y,0,Z_CONJ) + +#define zv_norm1(x) _zv_norm1(x,VNULL) +#define zv_norm2(x) _zv_norm2(x,VNULL) +#define zv_norm_inf(x) _zv_norm_inf(x,VNULL) + + +#endif diff --git a/zmatrix2.h b/zmatrix2.h new file mode 100644 index 0000000..f5f805b --- /dev/null +++ b/zmatrix2.h @@ -0,0 +1,120 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + 2nd header file for Meschach's complex routines. + This file contains declarations for complex factorisation/solve + routines. + +*/ + + +#ifndef ZMATRIX2H +#define ZMATRIX2H + +#include "zmatrix.h" + +#ifdef ANSI_C +extern ZVEC *zUsolve(ZMAT *matrix, ZVEC *b, ZVEC *out, double diag); +extern ZVEC *zLsolve(ZMAT *matrix, ZVEC *b, ZVEC *out, double diag); +extern ZVEC *zUAsolve(ZMAT *U, ZVEC *b, ZVEC *out, double diag); +extern ZVEC *zDsolve(ZMAT *A, ZVEC *b, ZVEC *x); +extern ZVEC *zLAsolve(ZMAT *L, ZVEC *b, ZVEC *out, double diag); + +extern ZVEC *zhhvec(ZVEC *,int,Real *,ZVEC *,complex *); +extern ZVEC *zhhtrvec(ZVEC *,double,int,ZVEC *,ZVEC *); +extern ZMAT *zhhtrrows(ZMAT *,int,int,ZVEC *,double); +extern ZMAT *zhhtrcols(ZMAT *,int,int,ZVEC *,double); +extern ZMAT *_zhhtrcols(ZMAT *,int,int,ZVEC *,double,ZVEC *); +extern ZMAT *zHfactor(ZMAT *,ZVEC *); +extern ZMAT *zHQunpack(ZMAT *,ZVEC *,ZMAT *,ZMAT *); + +extern ZMAT *zQRfactor(ZMAT *A, ZVEC *diag); +extern ZMAT *zQRCPfactor(ZMAT *A, ZVEC *diag, PERM *px); +extern ZVEC *_zQsolve(ZMAT *QR, ZVEC *diag, ZVEC *b, ZVEC *x, ZVEC *tmp); +extern ZMAT *zmakeQ(ZMAT *QR, ZVEC *diag, ZMAT *Qout); +extern ZMAT *zmakeR(ZMAT *QR, ZMAT *Rout); +extern ZVEC *zQRsolve(ZMAT *QR, ZVEC *diag, ZVEC *b, ZVEC *x); +extern ZVEC *zQRAsolve(ZMAT *QR, ZVEC *diag, ZVEC *b, ZVEC *x); +extern ZVEC *zQRCPsolve(ZMAT *QR,ZVEC *diag,PERM *pivot,ZVEC *b,ZVEC *x); +extern ZVEC *zUmlt(ZMAT *U, ZVEC *x, ZVEC *out); +extern ZVEC *zUAmlt(ZMAT *U, ZVEC *x, ZVEC *out); +extern double zQRcondest(ZMAT *QR); + +extern ZVEC *zLsolve(ZMAT *, ZVEC *, ZVEC *, double); +extern ZMAT *zset_col(ZMAT *, int, ZVEC *); + +extern ZMAT *zLUfactor(ZMAT *A, PERM *pivot); +extern ZVEC *zLUsolve(ZMAT *A, PERM *pivot, ZVEC *b, ZVEC *x); +extern ZVEC *zLUAsolve(ZMAT *LU, PERM *pivot, ZVEC *b, ZVEC *x); +extern ZMAT *zm_inverse(ZMAT *A, ZMAT *out); +extern double zLUcondest(ZMAT *LU, PERM *pivot); + +extern void zgivens(complex, complex, Real *, complex *); +extern ZMAT *zrot_rows(ZMAT *A, int i, int k, double c, complex s, + ZMAT *out); +extern ZMAT *zrot_cols(ZMAT *A, int i, int k, double c, complex s, + ZMAT *out); +extern ZVEC *rot_zvec(ZVEC *x, int i, int k, double c, complex s, + ZVEC *out); +extern ZMAT *zschur(ZMAT *A,ZMAT *Q); +/* extern ZMAT *schur_vecs(ZMAT *T,ZMAT *Q,X_re,X_im) */ +#else +extern ZVEC *zUsolve(), *zLsolve(), *zUAsolve(), *zDsolve(), *zLAsolve(); + +extern ZVEC *zhhvec(); +extern ZVEC *zhhtrvec(); +extern ZMAT *zhhtrrows(); +extern ZMAT *zhhtrcols(); +extern ZMAT *_zhhtrcols(); +extern ZMAT *zHfactor(); +extern ZMAT *zHQunpack(); + + +extern ZMAT *zQRfactor(), *zQRCPfactor(); +extern ZVEC *_zQsolve(); +extern ZMAT *zmakeQ(), *zmakeR(); +extern ZVEC *zQRsolve(), *zQRAsolve(), *zQRCPsolve(); +extern ZVEC *zUmlt(), *zUAmlt(); +extern double zQRcondest(); + +extern ZVEC *zLsolve(); +extern ZMAT *zset_col(); + +extern ZMAT *zLUfactor(); +extern ZVEC *zLUsolve(), *zLUAsolve(); +extern ZMAT *zm_inverse(); +extern double zLUcondest(); + +extern void zgivens(); +extern ZMAT *zrot_rows(), *zrot_cols(); +extern ZVEC *rot_zvec(); +extern ZMAT *zschur(); +/* extern ZMAT *schur_vecs(); */ +#endif /* ANSI_C */ + +#endif /* ZMATRIX2H */ + diff --git a/zmemory.c b/zmemory.c new file mode 100644 index 0000000..b16e65c --- /dev/null +++ b/zmemory.c @@ -0,0 +1,745 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* Memory allocation and de-allocation for complex matrices and vectors */ + +#include +#include "zmatrix.h" + +static char rcsid[] = "$Id: zmemory.c,v 1.2 1994/04/05 02:13:14 des Exp $"; + + + +/* zv_zero -- zeros all entries of a complex vector + -- uses __zzero__() */ +#ifndef ANSI_C +ZVEC *zv_zero(x) +ZVEC *x; +#else +ZVEC *zv_zero(ZVEC *x) +#endif +{ + if ( ! x ) + error(E_NULL,"zv_zero"); + __zzero__(x->ve,x->dim); + + return x; +} + +/* zm_zero -- zeros all entries of a complex matrix + -- uses __zzero__() */ +#ifndef ANSI_C +ZMAT *zm_zero(A) +ZMAT *A; +#else +ZMAT *zm_zero(ZMAT *A) +#endif +{ + int i; + + if ( ! A ) + error(E_NULL,"zm_zero"); + for ( i = 0; i < A->m; i++ ) + __zzero__(A->me[i],A->n); + + return A; +} + +/* zm_get -- gets an mxn complex matrix (in ZMAT form) */ +#ifndef ANSI_C +ZMAT *zm_get(m,n) +int m,n; +#else +ZMAT *zm_get(int m, int n) +#endif +{ + ZMAT *matrix; + unsigned int i; + + if (m < 0 || n < 0) + error(E_NEG,"zm_get"); + + if ((matrix=NEW(ZMAT)) == (ZMAT *)NULL ) + error(E_MEM,"zm_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,sizeof(ZMAT)); + mem_numvar(TYPE_ZMAT,1); + } + + matrix->m = m; matrix->n = matrix->max_n = n; + matrix->max_m = m; matrix->max_size = m*n; +#ifndef SEGMENTED + if ((matrix->base = NEW_A(m*n,complex)) == (complex *)NULL ) + { + free(matrix); + error(E_MEM,"zm_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,m*n*sizeof(complex)); + } +#else + matrix->base = (complex *)NULL; +#endif + if ((matrix->me = (complex **)calloc(m,sizeof(complex *))) == + (complex **)NULL ) + { free(matrix->base); free(matrix); + error(E_MEM,"zm_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,m*sizeof(complex *)); + } +#ifndef SEGMENTED + /* set up pointers */ + for ( i=0; ime[i] = &(matrix->base[i*n]); +#else + for ( i = 0; i < m; i++ ) + if ( (matrix->me[i]=NEW_A(n,complex)) == (complex *)NULL ) + error(E_MEM,"zm_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,n*sizeof(complex)); + } +#endif + + return (matrix); +} + + +/* zv_get -- gets a ZVEC of dimension 'dim' + -- Note: initialized to zero */ +#ifndef ANSI_C +ZVEC *zv_get(size) +int size; +#else +ZVEC *zv_get(int size) +#endif +{ + ZVEC *vector; + + if (size < 0) + error(E_NEG,"zv_get"); + + if ((vector=NEW(ZVEC)) == (ZVEC *)NULL ) + error(E_MEM,"zv_get"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZVEC,0,sizeof(ZVEC)); + mem_numvar(TYPE_ZVEC,1); + } + vector->dim = vector->max_dim = size; + if ((vector->ve=NEW_A(size,complex)) == (complex *)NULL ) + { + free(vector); + error(E_MEM,"zv_get"); + } + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZVEC,0,size*sizeof(complex)); + } + return (vector); +} + +/* zm_free -- returns ZMAT & asoociated memory back to memory heap */ +#ifndef ANSI_C +int zm_free(mat) +ZMAT *mat; +#else +int zm_free(ZMAT *mat) +#endif +{ +#ifdef SEGMENTED + int i; +#endif + + if ( mat==(ZMAT *)NULL || (int)(mat->m) < 0 || + (int)(mat->n) < 0 ) + /* don't trust it */ + return (-1); + +#ifndef SEGMENTED + if ( mat->base != (complex *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,mat->max_m*mat->max_n*sizeof(complex),0); + } + free((char *)(mat->base)); + } +#else + for ( i = 0; i < mat->max_m; i++ ) + if ( mat->me[i] != (complex *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,mat->max_n*sizeof(complex),0); + } + free((char *)(mat->me[i])); + } +#endif + if ( mat->me != (complex **)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,mat->max_m*sizeof(complex *),0); + } + free((char *)(mat->me)); + } + + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,sizeof(ZMAT),0); + mem_numvar(TYPE_ZMAT,-1); + } + free((char *)mat); + + return (0); +} + + +/* zv_free -- returns ZVEC & asoociated memory back to memory heap */ +#ifndef ANSI_C +int zv_free(vec) +ZVEC *vec; +#else +int zv_free(ZVEC *vec) +#endif +{ + if ( vec==(ZVEC *)NULL || (int)(vec->dim) < 0 ) + /* don't trust it */ + return (-1); + + if ( vec->ve == (complex *)NULL ) { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZVEC,sizeof(ZVEC),0); + mem_numvar(TYPE_ZVEC,-1); + } + free((char *)vec); + } + else + { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZVEC,vec->max_dim*sizeof(complex)+ + sizeof(ZVEC),0); + mem_numvar(TYPE_ZVEC,-1); + } + + free((char *)vec->ve); + free((char *)vec); + } + + return (0); +} + + +/* zm_resize -- returns the matrix A of size new_m x new_n; A is zeroed + -- if A == NULL on entry then the effect is equivalent to m_get() */ +#ifndef ANSI_C +ZMAT *zm_resize(A,new_m,new_n) +ZMAT *A; +int new_m, new_n; +#else +ZMAT *zm_resize(ZMAT *A, int new_m, int new_n) +#endif +{ + unsigned int i, new_max_m, new_max_n, new_size, old_m, old_n; + + if (new_m < 0 || new_n < 0) + error(E_NEG,"zm_resize"); + + if ( ! A ) + return zm_get(new_m,new_n); + + if (new_m == A->m && new_n == A->n) + return A; + + old_m = A->m; old_n = A->n; + if ( new_m > A->max_m ) + { /* re-allocate A->me */ + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,A->max_m*sizeof(complex *), + new_m*sizeof(complex *)); + } + + A->me = RENEW(A->me,new_m,complex *); + if ( ! A->me ) + error(E_MEM,"zm_resize"); + } + new_max_m = max(new_m,A->max_m); + new_max_n = max(new_n,A->max_n); + +#ifndef SEGMENTED + new_size = new_max_m*new_max_n; + if ( new_size > A->max_size ) + { /* re-allocate A->base */ + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,A->max_m*A->max_n*sizeof(complex), + new_size*sizeof(complex)); + } + + A->base = RENEW(A->base,new_size,complex); + if ( ! A->base ) + error(E_MEM,"zm_resize"); + A->max_size = new_size; + } + + /* now set up A->me[i] */ + for ( i = 0; i < new_m; i++ ) + A->me[i] = &(A->base[i*new_n]); + + /* now shift data in matrix */ + if ( old_n > new_n ) + { + for ( i = 1; i < min(old_m,new_m); i++ ) + MEM_COPY((char *)&(A->base[i*old_n]), + (char *)&(A->base[i*new_n]), + sizeof(complex)*new_n); + } + else if ( old_n < new_n ) + { + for ( i = min(old_m,new_m)-1; i > 0; i-- ) + { /* copy & then zero extra space */ + MEM_COPY((char *)&(A->base[i*old_n]), + (char *)&(A->base[i*new_n]), + sizeof(complex)*old_n); + __zzero__(&(A->base[i*new_n+old_n]),(new_n-old_n)); + } + __zzero__(&(A->base[old_n]),(new_n-old_n)); + A->max_n = new_n; + } + /* zero out the new rows.. */ + for ( i = old_m; i < new_m; i++ ) + __zzero__(&(A->base[i*new_n]),new_n); +#else + if ( A->max_n < new_n ) + { + complex *tmp; + + for ( i = 0; i < A->max_m; i++ ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,A->max_n*sizeof(complex), + new_max_n*sizeof(complex)); + } + + if ( (tmp = RENEW(A->me[i],new_max_n,complex)) == NULL ) + error(E_MEM,"zm_resize"); + else { + A->me[i] = tmp; + } + } + for ( i = A->max_m; i < new_max_m; i++ ) + { + if ( (tmp = NEW_A(new_max_n,complex)) == NULL ) + error(E_MEM,"zm_resize"); + else { + A->me[i] = tmp; + if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,new_max_n*sizeof(complex)); + } + } + } + } + else if ( A->max_m < new_m ) + { + for ( i = A->max_m; i < new_m; i++ ) + if ( (A->me[i] = NEW_A(new_max_n,complex)) == NULL ) + error(E_MEM,"zm_resize"); + else if (mem_info_is_on()) { + mem_bytes(TYPE_ZMAT,0,new_max_n*sizeof(complex)); + } + + } + + if ( old_n < new_n ) + { + for ( i = 0; i < old_m; i++ ) + __zzero__(&(A->me[i][old_n]),new_n-old_n); + } + + /* zero out the new rows.. */ + for ( i = old_m; i < new_m; i++ ) + __zzero__(A->me[i],new_n); +#endif + + A->max_m = new_max_m; + A->max_n = new_max_n; + A->max_size = A->max_m*A->max_n; + A->m = new_m; A->n = new_n; + + return A; +} + + +/* zv_resize -- returns the (complex) vector x with dim new_dim + -- x is set to the zero vector */ +#ifndef ANSI_C +ZVEC *zv_resize(x,new_dim) +ZVEC *x; +int new_dim; +#else +ZVEC *zv_resize(ZVEC *x, int new_dim) +#endif +{ + if (new_dim < 0) + error(E_NEG,"zv_resize"); + + if ( ! x ) + return zv_get(new_dim); + + if (new_dim == x->dim) + return x; + + if ( x->max_dim == 0 ) /* assume that it's from sub_zvec */ + return zv_get(new_dim); + + if ( new_dim > x->max_dim ) + { + if (mem_info_is_on()) { + mem_bytes(TYPE_ZVEC,x->max_dim*sizeof(complex), + new_dim*sizeof(complex)); + } + + x->ve = RENEW(x->ve,new_dim,complex); + if ( ! x->ve ) + error(E_MEM,"zv_resize"); + x->max_dim = new_dim; + } + + if ( new_dim > x->dim ) + __zzero__(&(x->ve[x->dim]),new_dim - x->dim); + x->dim = new_dim; + + return x; +} + + +/* varying arguments */ + +#ifdef ANSI_C + +#include + + +/* To allocate memory to many arguments. + The function should be called: + zv_get_vars(dim,&x,&y,&z,...,NULL); + where + int dim; + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + dim is the length of vectors x,y,z,... + returned value is equal to the number of allocated variables + Other gec_... functions are similar. +*/ + +int zv_get_vars(int dim,...) +{ + va_list ap; + int i=0; + ZVEC **par; + + va_start(ap, dim); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + *par = zv_get(dim); + i++; + } + + va_end(ap); + return i; +} + + + +int zm_get_vars(int m,int n,...) +{ + va_list ap; + int i=0; + ZMAT **par; + + va_start(ap, n); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + *par = zm_get(m,n); + i++; + } + + va_end(ap); + return i; +} + + + +/* To resize memory for many arguments. + The function should be called: + v_resize_vars(new_dim,&x,&y,&z,...,NULL); + where + int new_dim; + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + rdim is the resized length of vectors x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. + Other *_resize_list() functions are similar. +*/ + +int zv_resize_vars(int new_dim,...) +{ + va_list ap; + int i=0; + ZVEC **par; + + va_start(ap, new_dim); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + *par = zv_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + + + +int zm_resize_vars(int m,int n,...) +{ + va_list ap; + int i=0; + ZMAT **par; + + va_start(ap, n); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + *par = zm_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + + +/* To deallocate memory for many arguments. + The function should be called: + v_free_vars(&x,&y,&z,...,NULL); + where + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + There must be at least one not NULL argument. + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. + Other *_free_list() functions are similar. +*/ + +int zv_free_vars(ZVEC **pv,...) +{ + va_list ap; + int i=1; + ZVEC **par; + + zv_free(*pv); + *pv = ZVNULL; + va_start(ap, pv); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + zv_free(*par); + *par = ZVNULL; + i++; + } + + va_end(ap); + return i; +} + + + +int zm_free_vars(ZMAT **va,...) +{ + va_list ap; + int i=1; + ZMAT **par; + + zm_free(*va); + *va = ZMNULL; + va_start(ap, va); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + zm_free(*par); + *par = ZMNULL; + i++; + } + + va_end(ap); + return i; +} + + + +#elif VARARGS + +#include + +/* To allocate memory to many arguments. + The function should be called: + v_get_vars(dim,&x,&y,&z,...,NULL); + where + int dim; + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + dim is the length of vectors x,y,z,... + returned value is equal to the number of allocated variables + Other gec_... functions are similar. +*/ + +int zv_get_vars(va_alist) va_dcl +{ + va_list ap; + int dim,i=0; + ZVEC **par; + + va_start(ap); + dim = va_arg(ap,int); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + *par = zv_get(dim); + i++; + } + + va_end(ap); + return i; +} + + + +int zm_get_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, n, m; + ZMAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + *par = zm_get(m,n); + i++; + } + + va_end(ap); + return i; +} + + + +/* To resize memory for many arguments. + The function should be called: + v_resize_vars(new_dim,&x,&y,&z,...,NULL); + where + int new_dim; + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + rdim is the resized length of vectors x,y,z,... + returned value is equal to the number of allocated variables. + If one of x,y,z,.. arguments is NULL then memory is allocated to this + argument. + Other *_resize_list() functions are similar. +*/ + +int zv_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, new_dim; + ZVEC **par; + + va_start(ap); + new_dim = va_arg(ap,int); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + *par = zv_resize(*par,new_dim); + i++; + } + + va_end(ap); + return i; +} + + +int zm_resize_vars(va_alist) va_dcl +{ + va_list ap; + int i=0, m, n; + ZMAT **par; + + va_start(ap); + m = va_arg(ap,int); + n = va_arg(ap,int); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + *par = zm_resize(*par,m,n); + i++; + } + + va_end(ap); + return i; +} + + + +/* To deallocate memory for many arguments. + The function should be called: + v_free_vars(&x,&y,&z,...,NULL); + where + ZVEC *x, *y, *z,...; + The last argument should be NULL ! + There must be at least one not NULL argument. + returned value is equal to the number of allocated variables. + Returned value of x,y,z,.. is VNULL. + Other *_free_list() functions are similar. +*/ + +int zv_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + ZVEC **par; + + va_start(ap); + while (par = va_arg(ap,ZVEC **)) { /* NULL ends the list*/ + zv_free(*par); + *par = ZVNULL; + i++; + } + + va_end(ap); + return i; +} + + + +int zm_free_vars(va_alist) va_dcl +{ + va_list ap; + int i=0; + ZMAT **par; + + va_start(ap); + while (par = va_arg(ap,ZMAT **)) { /* NULL ends the list*/ + zm_free(*par); + *par = ZMNULL; + i++; + } + + va_end(ap); + return i; +} + + +#endif + diff --git a/znorm.c b/znorm.c new file mode 100644 index 0000000..82babe6 --- /dev/null +++ b/znorm.c @@ -0,0 +1,208 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + A collection of functions for computing norms: scaled and unscaled + Complex version +*/ +static char rcsid[] = "$Id: znorm.c,v 1.1 1994/01/13 04:21:31 des Exp $"; + +#include +#include +#include "zmatrix.h" + + + +/* _zv_norm1 -- computes (scaled) 1-norms of vectors */ +double _zv_norm1(x,scale) +ZVEC *x; +VEC *scale; +{ + int i, dim; + Real s, sum; + + if ( x == ZVNULL ) + error(E_NULL,"_zv_norm1"); + dim = x->dim; + + sum = 0.0; + if ( scale == VNULL ) + for ( i = 0; i < dim; i++ ) + sum += zabs(x->ve[i]); + else if ( scale->dim < dim ) + error(E_SIZES,"_zv_norm1"); + else + for ( i = 0; i < dim; i++ ) + { + s = scale->ve[i]; + sum += ( s== 0.0 ) ? zabs(x->ve[i]) : zabs(x->ve[i])/fabs(s); + } + + return sum; +} + +/* square -- returns x^2 */ +/****************************** +double square(x) +double x; +{ return x*x; } +******************************/ + +#define square(x) ((x)*(x)) + +/* _zv_norm2 -- computes (scaled) 2-norm (Euclidean norm) of vectors */ +double _zv_norm2(x,scale) +ZVEC *x; +VEC *scale; +{ + int i, dim; + Real s, sum; + + if ( x == ZVNULL ) + error(E_NULL,"_zv_norm2"); + dim = x->dim; + + sum = 0.0; + if ( scale == VNULL ) + for ( i = 0; i < dim; i++ ) + sum += square(x->ve[i].re) + square(x->ve[i].im); + else if ( scale->dim < dim ) + error(E_SIZES,"_v_norm2"); + else + for ( i = 0; i < dim; i++ ) + { + s = scale->ve[i]; + sum += ( s== 0.0 ) ? square(x->ve[i].re) + square(x->ve[i].im) : + (square(x->ve[i].re) + square(x->ve[i].im))/square(s); + } + + return sqrt(sum); +} + +#define max(a,b) ((a) > (b) ? (a) : (b)) + +/* _zv_norm_inf -- computes (scaled) infinity-norm (supremum norm) of vectors */ +double _zv_norm_inf(x,scale) +ZVEC *x; +VEC *scale; +{ + int i, dim; + Real s, maxval, tmp; + + if ( x == ZVNULL ) + error(E_NULL,"_zv_norm_inf"); + dim = x->dim; + + maxval = 0.0; + if ( scale == VNULL ) + for ( i = 0; i < dim; i++ ) + { + tmp = zabs(x->ve[i]); + maxval = max(maxval,tmp); + } + else if ( scale->dim < dim ) + error(E_SIZES,"_zv_norm_inf"); + else + for ( i = 0; i < dim; i++ ) + { + s = scale->ve[i]; + tmp = ( s == 0.0 ) ? zabs(x->ve[i]) : zabs(x->ve[i])/fabs(s); + maxval = max(maxval,tmp); + } + + return maxval; +} + +/* zm_norm1 -- compute matrix 1-norm -- unscaled + -- complex version */ +double zm_norm1(A) +ZMAT *A; +{ + int i, j, m, n; + Real maxval, sum; + + if ( A == ZMNULL ) + error(E_NULL,"zm_norm1"); + + m = A->m; n = A->n; + maxval = 0.0; + + for ( j = 0; j < n; j++ ) + { + sum = 0.0; + for ( i = 0; i < m; i ++ ) + sum += zabs(A->me[i][j]); + maxval = max(maxval,sum); + } + + return maxval; +} + +/* zm_norm_inf -- compute matrix infinity-norm -- unscaled + -- complex version */ +double zm_norm_inf(A) +ZMAT *A; +{ + int i, j, m, n; + Real maxval, sum; + + if ( A == ZMNULL ) + error(E_NULL,"zm_norm_inf"); + + m = A->m; n = A->n; + maxval = 0.0; + + for ( i = 0; i < m; i++ ) + { + sum = 0.0; + for ( j = 0; j < n; j ++ ) + sum += zabs(A->me[i][j]); + maxval = max(maxval,sum); + } + + return maxval; +} + +/* zm_norm_frob -- compute matrix frobenius-norm -- unscaled */ +double zm_norm_frob(A) +ZMAT *A; +{ + int i, j, m, n; + Real sum; + + if ( A == ZMNULL ) + error(E_NULL,"zm_norm_frob"); + + m = A->m; n = A->n; + sum = 0.0; + + for ( i = 0; i < m; i++ ) + for ( j = 0; j < n; j ++ ) + sum += square(A->me[i][j].re) + square(A->me[i][j].im); + + return sqrt(sum); +} + diff --git a/zqrfctr.c b/zqrfctr.c new file mode 100644 index 0000000..08f85ef --- /dev/null +++ b/zqrfctr.c @@ -0,0 +1,548 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + This file contains the routines needed to perform QR factorisation + of matrices, as well as Householder transformations. + The internal "factored form" of a matrix A is not quite standard. + The diagonal of A is replaced by the diagonal of R -- not by the 1st non-zero + entries of the Householder vectors. The 1st non-zero entries are held in + the diag parameter of QRfactor(). The reason for this non-standard + representation is that it enables direct use of the Usolve() function + rather than requiring that a seperate function be written just for this case. + See, e.g., QRsolve() below for more details. + + Complex version + +*/ + +static char rcsid[] = "$Id: zqrfctr.c,v 1.1 1994/01/13 04:21:22 des Exp $"; + +#include +#include +#include "zmatrix.h" +#include "zmatrix2.h" + + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0) + + +#define sign(x) ((x) > 0.0 ? 1 : ((x) < 0.0 ? -1 : 0 )) + +/* Note: The usual representation of a Householder transformation is taken + to be: + P = I - beta.u.u* + where beta = 2/(u*.u) and u is called the Householder vector + (u* is the conjugate transposed vector of u +*/ + +/* zQRfactor -- forms the QR factorisation of A + -- factorisation stored in compact form as described above + (not quite standard format) */ +ZMAT *zQRfactor(A,diag) +ZMAT *A; +ZVEC *diag; +{ + unsigned int k,limit; + Real beta; + STATIC ZVEC *tmp1=ZVNULL, *w=ZVNULL; + + if ( ! A || ! diag ) + error(E_NULL,"zQRfactor"); + limit = min(A->m,A->n); + if ( diag->dim < limit ) + error(E_SIZES,"zQRfactor"); + + tmp1 = zv_resize(tmp1,A->m); + w = zv_resize(w, A->n); + MEM_STAT_REG(tmp1,TYPE_ZVEC); + MEM_STAT_REG(w, TYPE_ZVEC); + + for ( k=0; kme[k][k]); + diag->ve[k] = tmp1->ve[k]; + + /* apply H/holder vector to remaining columns */ + tracecatch(_zhhtrcols(A,k,k+1,tmp1,beta,w),"zQRfactor"); + } + +#ifdef THREADSAFE + ZV_FREE(tmp1); ZV_FREE(w); +#endif + + return (A); +} + +/* zQRCPfactor -- forms the QR factorisation of A with column pivoting + -- factorisation stored in compact form as described above + ( not quite standard format ) */ +ZMAT *zQRCPfactor(A,diag,px) +ZMAT *A; +ZVEC *diag; +PERM *px; +{ + unsigned int i, i_max, j, k, limit; + STATIC ZVEC *tmp1=ZVNULL, *tmp2=ZVNULL, *w=ZVNULL; + STATIC VEC *gamma=VNULL; + Real beta; + Real maxgamma, sum, tmp; + complex ztmp; + + if ( ! A || ! diag || ! px ) + error(E_NULL,"QRCPfactor"); + limit = min(A->m,A->n); + if ( diag->dim < limit || px->size != A->n ) + error(E_SIZES,"QRCPfactor"); + + tmp1 = zv_resize(tmp1,A->m); + tmp2 = zv_resize(tmp2,A->m); + gamma = v_resize(gamma,A->n); + w = zv_resize(w,A->n); + MEM_STAT_REG(tmp1,TYPE_ZVEC); + MEM_STAT_REG(tmp2,TYPE_ZVEC); + MEM_STAT_REG(gamma,TYPE_VEC); + MEM_STAT_REG(w, TYPE_ZVEC); + + /* initialise gamma and px */ + for ( j=0; jn; j++ ) + { + px->pe[j] = j; + sum = 0.0; + for ( i=0; im; i++ ) + sum += square(A->me[i][j].re) + square(A->me[i][j].im); + gamma->ve[j] = sum; + } + + for ( k=0; kve[k]; + for ( i=k+1; in; i++ ) + /* Loop invariant:maxgamma=gamma[i_max] + >=gamma[l];l=k,...,i-1 */ + if ( gamma->ve[i] > maxgamma ) + { maxgamma = gamma->ve[i]; i_max = i; } + + /* swap columns if necessary */ + if ( i_max != k ) + { + /* swap gamma values */ + tmp = gamma->ve[k]; + gamma->ve[k] = gamma->ve[i_max]; + gamma->ve[i_max] = tmp; + + /* update column permutation */ + px_transp(px,k,i_max); + + /* swap columns of A */ + for ( i=0; im; i++ ) + { + ztmp = A->me[i][k]; + A->me[i][k] = A->me[i][i_max]; + A->me[i][i_max] = ztmp; + } + } + + /* get H/holder vector for the k-th column */ + zget_col(A,k,tmp1); + /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */ + zhhvec(tmp1,k,&beta,tmp1,&A->me[k][k]); + diag->ve[k] = tmp1->ve[k]; + + /* apply H/holder vector to remaining columns */ + _zhhtrcols(A,k,k+1,tmp1,beta,w); + + /* update gamma values */ + for ( j=k+1; jn; j++ ) + gamma->ve[j] -= square(A->me[k][j].re)+square(A->me[k][j].im); + } + +#ifdef THREADSAFE + ZV_FREE(tmp1); ZV_FREE(tmp2); V_FREE(gamma); ZV_FREE(w); +#endif + return (A); +} + +/* zQsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact + form a la QRfactor() + -- may be in-situ */ +ZVEC *_zQsolve(QR,diag,b,x,tmp) +ZMAT *QR; +ZVEC *diag, *b, *x, *tmp; +{ + unsigned int dynamic; + int k, limit; + Real beta, r_ii, tmp_val; + + limit = min(QR->m,QR->n); + dynamic = FALSE; + if ( ! QR || ! diag || ! b ) + error(E_NULL,"_zQsolve"); + if ( diag->dim < limit || b->dim != QR->m ) + error(E_SIZES,"_zQsolve"); + x = zv_resize(x,QR->m); + if ( tmp == ZVNULL ) + dynamic = TRUE; + tmp = zv_resize(tmp,QR->m); + + /* apply H/holder transforms in normal order */ + x = zv_copy(b,x); + for ( k = 0 ; k < limit ; k++ ) + { + zget_col(QR,k,tmp); + r_ii = zabs(tmp->ve[k]); + tmp->ve[k] = diag->ve[k]; + tmp_val = (r_ii*zabs(diag->ve[k])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + /* hhtrvec(tmp,beta->ve[k],k,x,x); */ + zhhtrvec(tmp,beta,k,x,x); + } + + if ( dynamic ) + ZV_FREE(tmp); + + return (x); +} + +/* zmakeQ -- constructs orthogonal matrix from Householder vectors stored in + compact QR form */ +ZMAT *zmakeQ(QR,diag,Qout) +ZMAT *QR,*Qout; +ZVEC *diag; +{ + STATIC ZVEC *tmp1=ZVNULL,*tmp2=ZVNULL; + unsigned int i, limit; + Real beta, r_ii, tmp_val; + int j; + + limit = min(QR->m,QR->n); + if ( ! QR || ! diag ) + error(E_NULL,"zmakeQ"); + if ( diag->dim < limit ) + error(E_SIZES,"zmakeQ"); + Qout = zm_resize(Qout,QR->m,QR->m); + + tmp1 = zv_resize(tmp1,QR->m); /* contains basis vec & columns of Q */ + tmp2 = zv_resize(tmp2,QR->m); /* contains H/holder vectors */ + MEM_STAT_REG(tmp1,TYPE_ZVEC); + MEM_STAT_REG(tmp2,TYPE_ZVEC); + + for ( i=0; im ; i++ ) + { /* get i-th column of Q */ + /* set up tmp1 as i-th basis vector */ + for ( j=0; jm ; j++ ) + tmp1->ve[j].re = tmp1->ve[j].im = 0.0; + tmp1->ve[i].re = 1.0; + + /* apply H/h transforms in reverse order */ + for ( j=limit-1; j>=0; j-- ) + { + zget_col(QR,j,tmp2); + r_ii = zabs(tmp2->ve[j]); + tmp2->ve[j] = diag->ve[j]; + tmp_val = (r_ii*zabs(diag->ve[j])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + /* hhtrvec(tmp2,beta->ve[j],j,tmp1,tmp1); */ + zhhtrvec(tmp2,beta,j,tmp1,tmp1); + } + + /* insert into Q */ + zset_col(Qout,i,tmp1); + } + +#ifdef THREADSAFE + ZV_FREE(tmp1); ZV_FREE(tmp2); +#endif + + return (Qout); +} + +/* zmakeR -- constructs upper triangular matrix from QR (compact form) + -- may be in-situ (all it does is zero the lower 1/2) */ +ZMAT *zmakeR(QR,Rout) +ZMAT *QR,*Rout; +{ + unsigned int i,j; + + if ( QR==ZMNULL ) + error(E_NULL,"zmakeR"); + Rout = zm_copy(QR,Rout); + + for ( i=1; im; i++ ) + for ( j=0; jn && jme[i][j].re = Rout->me[i][j].im = 0.0; + + return (Rout); +} + +/* zQRsolve -- solves the system Q.R.x=b where Q & R are stored in compact form + -- returns x, which is created if necessary */ +ZVEC *zQRsolve(QR,diag,b,x) +ZMAT *QR; +ZVEC *diag, *b, *x; +{ + int limit; + STATIC ZVEC *tmp = ZVNULL; + + if ( ! QR || ! diag || ! b ) + error(E_NULL,"zQRsolve"); + limit = min(QR->m,QR->n); + if ( diag->dim < limit || b->dim != QR->m ) + error(E_SIZES,"zQRsolve"); + tmp = zv_resize(tmp,limit); + MEM_STAT_REG(tmp,TYPE_ZVEC); + + x = zv_resize(x,QR->n); + _zQsolve(QR,diag,b,x,tmp); + x = zUsolve(QR,x,x,0.0); + x = zv_resize(x,QR->n); + +#ifdef THREADSAFE + ZV_FREE(tmp); +#endif + + return x; +} + +/* zQRAsolve -- solves the system (Q.R)*.x = b + -- Q & R are stored in compact form + -- returns x, which is created if necessary */ +ZVEC *zQRAsolve(QR,diag,b,x) +ZMAT *QR; +ZVEC *diag, *b, *x; +{ + int j, limit; + Real beta, r_ii, tmp_val; + STATIC ZVEC *tmp = ZVNULL; + + if ( ! QR || ! diag || ! b ) + error(E_NULL,"zQRAsolve"); + limit = min(QR->m,QR->n); + if ( diag->dim < limit || b->dim != QR->n ) + error(E_SIZES,"zQRAsolve"); + + x = zv_resize(x,QR->m); + x = zUAsolve(QR,b,x,0.0); + x = zv_resize(x,QR->m); + + tmp = zv_resize(tmp,x->dim); + MEM_STAT_REG(tmp,TYPE_ZVEC); + /* printf("zQRAsolve: tmp->dim = %d, x->dim = %d\n", tmp->dim, x->dim); */ + + /* apply H/h transforms in reverse order */ + for ( j=limit-1; j>=0; j-- ) + { + zget_col(QR,j,tmp); + tmp = zv_resize(tmp,QR->m); + r_ii = zabs(tmp->ve[j]); + tmp->ve[j] = diag->ve[j]; + tmp_val = (r_ii*zabs(diag->ve[j])); + beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val; + zhhtrvec(tmp,beta,j,x,x); + } + +#ifdef THREADSAFE + ZV_FREE(tmp); +#endif + + return x; +} + +/* zQRCPsolve -- solves A.x = b where A is factored by QRCPfactor() + -- assumes that A is in the compact factored form */ +ZVEC *zQRCPsolve(QR,diag,pivot,b,x) +ZMAT *QR; +ZVEC *diag; +PERM *pivot; +ZVEC *b, *x; +{ + if ( ! QR || ! diag || ! pivot || ! b ) + error(E_NULL,"zQRCPsolve"); + if ( (QR->m > diag->dim && QR->n > diag->dim) || QR->n != pivot->size ) + error(E_SIZES,"zQRCPsolve"); + + x = zQRsolve(QR,diag,b,x); + x = pxinv_zvec(pivot,x,x); + + return x; +} + +/* zUmlt -- compute out = upper_triang(U).x + -- may be in situ */ +ZVEC *zUmlt(U,x,out) +ZMAT *U; +ZVEC *x, *out; +{ + int i, limit; + + if ( U == ZMNULL || x == ZVNULL ) + error(E_NULL,"zUmlt"); + limit = min(U->m,U->n); + if ( limit != x->dim ) + error(E_SIZES,"zUmlt"); + if ( out == ZVNULL || out->dim < limit ) + out = zv_resize(out,limit); + + for ( i = 0; i < limit; i++ ) + out->ve[i] = __zip__(&(x->ve[i]),&(U->me[i][i]),limit - i,Z_NOCONJ); + return out; +} + +/* zUAmlt -- returns out = upper_triang(U)^T.x */ +ZVEC *zUAmlt(U,x,out) +ZMAT *U; +ZVEC *x, *out; +{ + /* complex sum; */ + complex tmp; + int i, limit; + + if ( U == ZMNULL || x == ZVNULL ) + error(E_NULL,"zUAmlt"); + limit = min(U->m,U->n); + if ( out == ZVNULL || out->dim < limit ) + out = zv_resize(out,limit); + + for ( i = limit-1; i >= 0; i-- ) + { + tmp = x->ve[i]; + out->ve[i].re = out->ve[i].im = 0.0; + __zmltadd__(&(out->ve[i]),&(U->me[i][i]),tmp,limit-i-1,Z_CONJ); + } + + return out; +} + + +/* zQRcondest -- returns an estimate of the 2-norm condition number of the + matrix factorised by QRfactor() or QRCPfactor() + -- note that as Q does not affect the 2-norm condition number, + it is not necessary to pass the diag, beta (or pivot) vectors + -- generates a lower bound on the true condition number + -- if the matrix is exactly singular, HUGE_VAL is returned + -- note that QRcondest() is likely to be more reliable for + matrices factored using QRCPfactor() */ +double zQRcondest(QR) +ZMAT *QR; +{ + STATIC ZVEC *y=ZVNULL; + Real norm, norm1, norm2, tmp1, tmp2; + complex sum, tmp; + int i, j, limit; + + if ( QR == ZMNULL ) + error(E_NULL,"zQRcondest"); + + limit = min(QR->m,QR->n); + for ( i = 0; i < limit; i++ ) + /* if ( QR->me[i][i] == 0.0 ) */ + if ( is_zero(QR->me[i][i]) ) + return HUGE_VAL; + + y = zv_resize(y,limit); + MEM_STAT_REG(y,TYPE_ZVEC); + /* use the trick for getting a unit vector y with ||R.y||_inf small + from the LU condition estimator */ + for ( i = 0; i < limit; i++ ) + { + sum.re = sum.im = 0.0; + for ( j = 0; j < i; j++ ) + /* sum -= QR->me[j][i]*y->ve[j]; */ + sum = zsub(sum,zmlt(QR->me[j][i],y->ve[j])); + /* sum -= (sum < 0.0) ? 1.0 : -1.0; */ + norm1 = zabs(sum); + if ( norm1 == 0.0 ) + sum.re = 1.0; + else + { + sum.re += sum.re / norm1; + sum.im += sum.im / norm1; + } + /* y->ve[i] = sum / QR->me[i][i]; */ + y->ve[i] = zdiv(sum,QR->me[i][i]); + } + zUAmlt(QR,y,y); + + /* now apply inverse power method to R*.R */ + for ( i = 0; i < 3; i++ ) + { + tmp1 = zv_norm2(y); + zv_mlt(zmake(1.0/tmp1,0.0),y,y); + zUAsolve(QR,y,y,0.0); + tmp2 = zv_norm2(y); + zv_mlt(zmake(1.0/tmp2,0.0),y,y); + zUsolve(QR,y,y,0.0); + } + /* now compute approximation for ||R^{-1}||_2 */ + norm1 = sqrt(tmp1)*sqrt(tmp2); + + /* now use complementary approach to compute approximation to ||R||_2 */ + for ( i = limit-1; i >= 0; i-- ) + { + sum.re = sum.im = 0.0; + for ( j = i+1; j < limit; j++ ) + sum = zadd(sum,zmlt(QR->me[i][j],y->ve[j])); + if ( is_zero(QR->me[i][i]) ) + return HUGE_VAL; + tmp = zdiv(sum,QR->me[i][i]); + if ( is_zero(tmp) ) + { + y->ve[i].re = 1.0; + y->ve[i].im = 0.0; + } + else + { + norm = zabs(tmp); + y->ve[i].re = sum.re / norm; + y->ve[i].im = sum.im / norm; + } + /* y->ve[i] = (sum >= 0.0) ? 1.0 : -1.0; */ + /* y->ve[i] = (QR->me[i][i] >= 0.0) ? y->ve[i] : - y->ve[i]; */ + } + + /* now apply power method to R*.R */ + for ( i = 0; i < 3; i++ ) + { + tmp1 = zv_norm2(y); + zv_mlt(zmake(1.0/tmp1,0.0),y,y); + zUmlt(QR,y,y); + tmp2 = zv_norm2(y); + zv_mlt(zmake(1.0/tmp2,0.0),y,y); + zUAmlt(QR,y,y); + } + norm2 = sqrt(tmp1)*sqrt(tmp2); + + /* printf("QRcondest: norm1 = %g, norm2 = %g\n",norm1,norm2); */ + +#ifdef THREADSAFE + ZV_FREE(y); +#endif + + return norm1*norm2; +} + diff --git a/zschur.c b/zschur.c new file mode 100644 index 0000000..9a22a5d --- /dev/null +++ b/zschur.c @@ -0,0 +1,386 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + +/* + File containing routines for computing the Schur decomposition + of a complex non-symmetric matrix + See also: hessen.c + Complex version +*/ + + +#include +#include +#include "zmatrix.h" +#include "zmatrix2.h" + +static char rcsid[] = "$Id: zschur.c,v 1.4 1995/04/07 16:28:58 des Exp $"; + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0) +#define b2s(t_or_f) ((t_or_f) ? "TRUE" : "FALSE") + + +/* zschur -- computes the Schur decomposition of the matrix A in situ + -- optionally, gives Q matrix such that Q^*.A.Q is upper triangular + -- returns upper triangular Schur matrix */ +ZMAT *zschur(A,Q) +ZMAT *A, *Q; +{ + int i, j, iter, k, k_min, k_max, k_tmp, n, split; + Real c; + complex det, discrim, lambda, lambda0, lambda1, s, sum, ztmp; + complex x, y; /* for chasing algorithm */ + complex **A_me; + STATIC ZVEC *diag=ZVNULL; + + if ( ! A ) + error(E_NULL,"zschur"); + if ( A->m != A->n || ( Q && Q->m != Q->n ) ) + error(E_SQUARE,"zschur"); + if ( Q != ZMNULL && Q->m != A->m ) + error(E_SIZES,"zschur"); + n = A->n; + diag = zv_resize(diag,A->n); + MEM_STAT_REG(diag,TYPE_ZVEC); + /* compute Hessenberg form */ + zHfactor(A,diag); + + /* save Q if necessary, and make A explicitly Hessenberg */ + zHQunpack(A,diag,Q,A); + + k_min = 0; A_me = A->me; + + while ( k_min < n ) + { + /* find k_max to suit: + submatrix k_min..k_max should be irreducible */ + k_max = n-1; + for ( k = k_min; k < k_max; k++ ) + if ( is_zero(A_me[k+1][k]) ) + { k_max = k; break; } + + if ( k_max <= k_min ) + { + k_min = k_max + 1; + continue; /* outer loop */ + } + + /* now have r x r block with r >= 2: + apply Francis QR step until block splits */ + split = FALSE; iter = 0; + while ( ! split ) + { + complex a00, a01, a10, a11; + iter++; + + /* set up Wilkinson/Francis complex shift */ + /* use the smallest eigenvalue of the bottom 2 x 2 submatrix */ + k_tmp = k_max - 1; + + a00 = A_me[k_tmp][k_tmp]; + a01 = A_me[k_tmp][k_max]; + a10 = A_me[k_max][k_tmp]; + a11 = A_me[k_max][k_max]; + ztmp.re = 0.5*(a00.re - a11.re); + ztmp.im = 0.5*(a00.im - a11.im); + discrim = zsqrt(zadd(zmlt(ztmp,ztmp),zmlt(a01,a10))); + sum.re = 0.5*(a00.re + a11.re); + sum.im = 0.5*(a00.im + a11.im); + lambda0 = zadd(sum,discrim); + lambda1 = zsub(sum,discrim); + det = zsub(zmlt(a00,a11),zmlt(a01,a10)); + + if ( is_zero(lambda0) && is_zero(lambda1) ) + { + lambda.re = lambda.im = 0.0; + } + else if ( zabs(lambda0) > zabs(lambda1) ) + lambda = zdiv(det,lambda0); + else + lambda = zdiv(det,lambda1); + + /* perturb shift if convergence is slow */ + if ( (iter % 10) == 0 ) + { + lambda.re += iter*0.02; + lambda.im += iter*0.02; + } + + /* set up Householder transformations */ + k_tmp = k_min + 1; + + x = zsub(A->me[k_min][k_min],lambda); + y = A->me[k_min+1][k_min]; + + /* use Givens' rotations to "chase" off-Hessenberg entry */ + for ( k = k_min; k <= k_max-1; k++ ) + { + zgivens(x,y,&c,&s); + zrot_cols(A,k,k+1,c,s,A); + zrot_rows(A,k,k+1,c,s,A); + if ( Q != ZMNULL ) + zrot_cols(Q,k,k+1,c,s,Q); + + /* zero things that should be zero */ + if ( k > k_min ) + A->me[k+1][k-1].re = A->me[k+1][k-1].im = 0.0; + + /* get next entry to chase along sub-diagonal */ + x = A->me[k+1][k]; + if ( k <= k_max - 2 ) + y = A->me[k+2][k]; + else + y.re = y.im = 0.0; + } + + for ( k = k_min; k <= k_max-2; k++ ) + { + /* zero appropriate sub-diagonals */ + A->me[k+2][k].re = A->me[k+2][k].im = 0.0; + } + + /* test to see if matrix should split */ + for ( k = k_min; k < k_max; k++ ) + if ( zabs(A_me[k+1][k]) < MACHEPS* + (zabs(A_me[k][k])+zabs(A_me[k+1][k+1])) ) + { + A_me[k+1][k].re = A_me[k+1][k].im = 0.0; + split = TRUE; + } + + } + } + + /* polish up A by zeroing strictly lower triangular elements + and small sub-diagonal elements */ + for ( i = 0; i < A->m; i++ ) + for ( j = 0; j < i-1; j++ ) + A_me[i][j].re = A_me[i][j].im = 0.0; + for ( i = 0; i < A->m - 1; i++ ) + if ( zabs(A_me[i+1][i]) < MACHEPS* + (zabs(A_me[i][i])+zabs(A_me[i+1][i+1])) ) + A_me[i+1][i].re = A_me[i+1][i].im = 0.0; + +#ifdef THREADSAFE + ZV_FREE(diag); +#endif + + return A; +} + + +#if 0 +/* schur_vecs -- returns eigenvectors computed from the real Schur + decomposition of a matrix + -- T is the block upper triangular Schur matrix + -- Q is the orthognal matrix where A = Q.T.Q^T + -- if Q is null, the eigenvectors of T are returned + -- X_re is the real part of the matrix of eigenvectors, + and X_im is the imaginary part of the matrix. + -- X_re is returned */ +MAT *schur_vecs(T,Q,X_re,X_im) +MAT *T, *Q, *X_re, *X_im; +{ + int i, j, limit; + Real t11_re, t11_im, t12, t21, t22_re, t22_im; + Real l_re, l_im, det_re, det_im, invdet_re, invdet_im, + val1_re, val1_im, val2_re, val2_im, + tmp_val1_re, tmp_val1_im, tmp_val2_re, tmp_val2_im, **T_me; + Real sum, diff, discrim, magdet, norm, scale; + STATIC VEC *tmp1_re=VNULL, *tmp1_im=VNULL, + *tmp2_re=VNULL, *tmp2_im=VNULL; + + if ( ! T || ! X_re ) + error(E_NULL,"schur_vecs"); + if ( T->m != T->n || X_re->m != X_re->n || + ( Q != MNULL && Q->m != Q->n ) || + ( X_im != MNULL && X_im->m != X_im->n ) ) + error(E_SQUARE,"schur_vecs"); + if ( T->m != X_re->m || + ( Q != MNULL && T->m != Q->m ) || + ( X_im != MNULL && T->m != X_im->m ) ) + error(E_SIZES,"schur_vecs"); + + tmp1_re = v_resize(tmp1_re,T->m); + tmp1_im = v_resize(tmp1_im,T->m); + tmp2_re = v_resize(tmp2_re,T->m); + tmp2_im = v_resize(tmp2_im,T->m); + MEM_STAT_REG(tmp1_re,TYPE_VEC); + MEM_STAT_REG(tmp1_im,TYPE_VEC); + MEM_STAT_REG(tmp2_re,TYPE_VEC); + MEM_STAT_REG(tmp2_im,TYPE_VEC); + + T_me = T->me; + i = 0; + while ( i < T->m ) + { + if ( i+1 < T->m && T->me[i+1][i] != 0.0 ) + { /* complex eigenvalue */ + sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]); + diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]); + discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i]; + l_re = l_im = 0.0; + if ( discrim < 0.0 ) + { /* yes -- complex e-vals */ + l_re = sum; + l_im = sqrt(-discrim); + } + else /* not correct Real Schur form */ + error(E_RANGE,"schur_vecs"); + } + else + { + l_re = T_me[i][i]; + l_im = 0.0; + } + + v_zero(tmp1_im); + v_rand(tmp1_re); + sv_mlt(MACHEPS,tmp1_re,tmp1_re); + + /* solve (T-l.I)x = tmp1 */ + limit = ( l_im != 0.0 ) ? i+1 : i; + /* printf("limit = %d\n",limit); */ + for ( j = limit+1; j < T->m; j++ ) + tmp1_re->ve[j] = 0.0; + j = limit; + while ( j >= 0 ) + { + if ( j > 0 && T->me[j][j-1] != 0.0 ) + { /* 2 x 2 diagonal block */ + /* printf("checkpoint A\n"); */ + val1_re = tmp1_re->ve[j-1] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j-1][j+1]),limit-j); + /* printf("checkpoint B\n"); */ + val1_im = tmp1_im->ve[j-1] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j-1][j+1]),limit-j); + /* printf("checkpoint C\n"); */ + val2_re = tmp1_re->ve[j] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint D\n"); */ + val2_im = tmp1_im->ve[j] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint E\n"); */ + + t11_re = T_me[j-1][j-1] - l_re; + t11_im = - l_im; + t22_re = T_me[j][j] - l_re; + t22_im = - l_im; + t12 = T_me[j-1][j]; + t21 = T_me[j][j-1]; + + scale = fabs(T_me[j-1][j-1]) + fabs(T_me[j][j]) + + fabs(t12) + fabs(t21) + fabs(l_re) + fabs(l_im); + + det_re = t11_re*t22_re - t11_im*t22_im - t12*t21; + det_im = t11_re*t22_im + t11_im*t22_re; + magdet = det_re*det_re+det_im*det_im; + if ( sqrt(magdet) < MACHEPS*scale ) + { + det_re = MACHEPS*scale; + magdet = det_re*det_re+det_im*det_im; + } + invdet_re = det_re/magdet; + invdet_im = - det_im/magdet; + tmp_val1_re = t22_re*val1_re-t22_im*val1_im-t12*val2_re; + tmp_val1_im = t22_im*val1_re+t22_re*val1_im-t12*val2_im; + tmp_val2_re = t11_re*val2_re-t11_im*val2_im-t21*val1_re; + tmp_val2_im = t11_im*val2_re+t11_re*val2_im-t21*val1_im; + tmp1_re->ve[j-1] = invdet_re*tmp_val1_re - + invdet_im*tmp_val1_im; + tmp1_im->ve[j-1] = invdet_im*tmp_val1_re + + invdet_re*tmp_val1_im; + tmp1_re->ve[j] = invdet_re*tmp_val2_re - + invdet_im*tmp_val2_im; + tmp1_im->ve[j] = invdet_im*tmp_val2_re + + invdet_re*tmp_val2_im; + j -= 2; + } + else + { + t11_re = T_me[j][j] - l_re; + t11_im = - l_im; + magdet = t11_re*t11_re + t11_im*t11_im; + scale = fabs(T_me[j][j]) + fabs(l_re); + if ( sqrt(magdet) < MACHEPS*scale ) + { + t11_re = MACHEPS*scale; + magdet = t11_re*t11_re + t11_im*t11_im; + } + invdet_re = t11_re/magdet; + invdet_im = - t11_im/magdet; + /* printf("checkpoint F\n"); */ + val1_re = tmp1_re->ve[j] - + __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint G\n"); */ + val1_im = tmp1_im->ve[j] - + __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j); + /* printf("checkpoint H\n"); */ + tmp1_re->ve[j] = invdet_re*val1_re - invdet_im*val1_im; + tmp1_im->ve[j] = invdet_im*val1_re + invdet_re*val1_im; + j -= 1; + } + } + + norm = v_norm_inf(tmp1_re) + v_norm_inf(tmp1_im); + sv_mlt(1/norm,tmp1_re,tmp1_re); + if ( l_im != 0.0 ) + sv_mlt(1/norm,tmp1_im,tmp1_im); + mv_mlt(Q,tmp1_re,tmp2_re); + if ( l_im != 0.0 ) + mv_mlt(Q,tmp1_im,tmp2_im); + if ( l_im != 0.0 ) + norm = sqrt(in_prod(tmp2_re,tmp2_re)+in_prod(tmp2_im,tmp2_im)); + else + norm = v_norm2(tmp2_re); + sv_mlt(1/norm,tmp2_re,tmp2_re); + if ( l_im != 0.0 ) + sv_mlt(1/norm,tmp2_im,tmp2_im); + + if ( l_im != 0.0 ) + { + if ( ! X_im ) + error(E_NULL,"schur_vecs"); + set_col(X_re,i,tmp2_re); + set_col(X_im,i,tmp2_im); + sv_mlt(-1.0,tmp2_im,tmp2_im); + set_col(X_re,i+1,tmp2_re); + set_col(X_im,i+1,tmp2_im); + i += 2; + } + else + { + set_col(X_re,i,tmp2_re); + if ( X_im != MNULL ) + set_col(X_im,i,tmp1_im); /* zero vector */ + i += 1; + } + } + + return X_re; +} + +#endif + diff --git a/zsolve.c b/zsolve.c new file mode 100644 index 0000000..3e5cee9 --- /dev/null +++ b/zsolve.c @@ -0,0 +1,300 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + Matrix factorisation routines to work with the other matrix files. + Complex case +*/ + +static char rcsid[] = "$Id: zsolve.c,v 1.1 1994/01/13 04:20:33 des Exp $"; + +#include +#include +#include "zmatrix2.h" + + +#define is_zero(z) ((z).re == 0.0 && (z).im == 0.0 ) + +/* Most matrix factorisation routines are in-situ unless otherwise specified */ + +/* zUsolve -- back substitution with optional over-riding diagonal + -- can be in-situ but doesn't need to be */ +ZVEC *zUsolve(matrix,b,out,diag) +ZMAT *matrix; +ZVEC *b, *out; +double diag; +{ + unsigned int dim /* , j */; + int i, i_lim; + complex **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum; + + if ( matrix==ZMNULL || b==ZVNULL ) + error(E_NULL,"zUsolve"); + dim = min(matrix->m,matrix->n); + if ( b->dim < dim ) + error(E_SIZES,"zUsolve"); + if ( out==ZVNULL || out->dim < dim ) + out = zv_resize(out,matrix->n); + mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; + + for ( i=dim-1; i>=0; i-- ) + if ( ! is_zero(b_ent[i]) ) + break; + else + out_ent[i].re = out_ent[i].im = 0.0; + i_lim = i; + + for ( i = i_lim; i>=0; i-- ) + { + sum = b_ent[i]; + mat_row = &(mat_ent[i][i+1]); + out_col = &(out_ent[i+1]); + sum = zsub(sum,__zip__(mat_row,out_col,i_lim-i,Z_NOCONJ)); + /****************************************************** + for ( j=i+1; j<=i_lim; j++ ) + sum -= mat_ent[i][j]*out_ent[j]; + sum -= (*mat_row++)*(*out_col++); + ******************************************************/ + if ( diag == 0.0 ) + { + if ( is_zero(mat_ent[i][i]) ) + error(E_SING,"zUsolve"); + else + /* out_ent[i] = sum/mat_ent[i][i]; */ + out_ent[i] = zdiv(sum,mat_ent[i][i]); + } + else + { + /* out_ent[i] = sum/diag; */ + out_ent[i].re = sum.re / diag; + out_ent[i].im = sum.im / diag; + } + } + + return (out); +} + +/* zLsolve -- forward elimination with (optional) default diagonal value */ +ZVEC *zLsolve(matrix,b,out,diag) +ZMAT *matrix; +ZVEC *b,*out; +double diag; +{ + unsigned int dim, i, i_lim /* , j */; + complex **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum; + + if ( matrix==ZMNULL || b==ZVNULL ) + error(E_NULL,"zLsolve"); + dim = min(matrix->m,matrix->n); + if ( b->dim < dim ) + error(E_SIZES,"zLsolve"); + if ( out==ZVNULL || out->dim < dim ) + out = zv_resize(out,matrix->n); + mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; + + for ( i=0; im,U->n); + if ( b->dim < dim ) + error(E_SIZES,"zUAsolve"); + out = zv_resize(out,U->n); + U_me = U->me; b_ve = b->ve; out_ve = out->ve; + + for ( i=0; idim); + /* MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]), + (dim-i_lim)*sizeof(complex)); */ + MEMCOPY(&(b_ve[i_lim]),&(out_ve[i_lim]),dim-i_lim,complex); + } + + if ( diag == 0.0 ) + { + for ( ; im,A->n); + if ( b->dim < dim ) + error(E_SIZES,"zDsolve"); + x = zv_resize(x,A->n); + + dim = b->dim; + for ( i=0; ime[i][i]) ) + error(E_SING,"zDsolve"); + else + x->ve[i] = zdiv(b->ve[i],A->me[i][i]); + + return (x); +} + +/* zLAsolve -- back substitution with optional over-riding diagonal + using the LOWER triangular part of matrix + -- can be in-situ but doesn't need to be */ +ZVEC *zLAsolve(L,b,out,diag) +ZMAT *L; +ZVEC *b, *out; +double diag; +{ + unsigned int dim; + int i, i_lim; + complex **L_me, *b_ve, *out_ve, tmp; + Real invdiag; + + if ( ! L || ! b ) + error(E_NULL,"zLAsolve"); + dim = min(L->m,L->n); + if ( b->dim < dim ) + error(E_SIZES,"zLAsolve"); + out = zv_resize(out,L->n); + L_me = L->me; b_ve = b->ve; out_ve = out->ve; + + for ( i=dim-1; i>=0; i-- ) + if ( ! is_zero(b_ve[i]) ) + break; + i_lim = i; + + if ( b != out ) + { + __zzero__(out_ve,out->dim); + /* MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(complex)); */ + MEMCOPY(b_ve,out_ve,i_lim+1,complex); + } + + if ( diag == 0.0 ) + { + for ( ; i>=0; i-- ) + { + tmp = zconj(L_me[i][i]); + if ( is_zero(tmp) ) + error(E_SING,"zLAsolve"); + out_ve[i] = zdiv(out_ve[i],tmp); + tmp.re = - out_ve[i].re; + tmp.im = - out_ve[i].im; + __zmltadd__(out_ve,L_me[i],tmp,i,Z_CONJ); + } + } + else + { + invdiag = 1.0/diag; + for ( ; i>=0; i-- ) + { + out_ve[i].re *= invdiag; + out_ve[i].im *= invdiag; + tmp.re = - out_ve[i].re; + tmp.im = - out_ve[i].im; + __zmltadd__(out_ve,L_me[i],tmp,i,Z_CONJ); + } + } + + return (out); +} diff --git a/ztorture.c b/ztorture.c new file mode 100644 index 0000000..9923b3c --- /dev/null +++ b/ztorture.c @@ -0,0 +1,720 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +/* + This file contains a series of tests for the Meschach matrix + library, complex routines +*/ + +static char rcsid[] = "$Id: $"; + +#include +#include +#include "zmatrix2.h" +#include "matlab.h" + + +#define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__) +#define notice(mesg) printf("# Testing %s...\n",mesg); + +/* extern int malloc_chain_check(); */ +/* #define MEMCHK() if ( malloc_chain_check(0) ) \ +{ printf("Error in malloc chain: \"%s\", line %d\n", \ + __FILE__, __LINE__); exit(0); } */ +#define MEMCHK() + +#define checkpt() printf("At line %d in file \"%s\"\n",__LINE__,__FILE__) + +/* cmp_perm -- returns 1 if pi1 == pi2, 0 otherwise */ +int cmp_perm(pi1, pi2) +PERM *pi1, *pi2; +{ + int i; + + if ( ! pi1 || ! pi2 ) + error(E_NULL,"cmp_perm"); + if ( pi1->size != pi2->size ) + return 0; + for ( i = 0; i < pi1->size; i++ ) + if ( pi1->pe[i] != pi2->pe[i] ) + return 0; + return 1; +} + +/* px_rand -- generates sort-of random permutation */ +PERM *px_rand(pi) +PERM *pi; +{ + int i, j, k; + + if ( ! pi ) + error(E_NULL,"px_rand"); + + for ( i = 0; i < 3*pi->size; i++ ) + { + j = (rand() >> 8) % pi->size; + k = (rand() >> 8) % pi->size; + px_transp(pi,j,k); + } + + return pi; +} + +#define SAVE_FILE "asx5213a.mat" +#define MATLAB_NAME "alpha" +char name[81] = MATLAB_NAME; + +void main(argc, argv) +int argc; +char *argv[]; +{ + ZVEC *x = ZVNULL, *y = ZVNULL, *z = ZVNULL, *u = ZVNULL; + ZVEC *diag = ZVNULL; + PERM *pi1 = PNULL, *pi2 = PNULL, *pivot = PNULL; + ZMAT *A = ZMNULL, *B = ZMNULL, *C = ZMNULL, *D = ZMNULL, + *Q = ZMNULL; + complex ONE; + complex z1, z2, z3; + Real cond_est, s1, s2, s3; + int i, seed; + FILE *fp; + char *cp; + + + mem_info_on(TRUE); + + setbuf(stdout,(char *)NULL); + + seed = 1111; + if ( argc > 2 ) + { + printf("usage: %s [seed]\n",argv[0]); + exit(0); + } + else if ( argc == 2 ) + sscanf(argv[1], "%d", &seed); + + /* set seed for rand() */ + smrand(seed); + + /* print out version information */ + m_version(); + + printf("# Meschach Complex numbers & vectors torture test\n\n"); + printf("# grep \"^Error\" the output for a listing of errors\n"); + printf("# Don't panic if you see \"Error\" appearing; \n"); + printf("# Also check the reported size of error\n"); + printf("# This program uses randomly generated problems and therefore\n"); + printf("# may occasionally produce ill-conditioned problems\n"); + printf("# Therefore check the size of the error compared with MACHEPS\n"); + printf("# If the error is within 1000*MACHEPS then don't worry\n"); + printf("# If you get an error of size 0.1 or larger there is \n"); + printf("# probably a bug in the code or the compilation procedure\n\n"); + printf("# seed = %d\n",seed); + + printf("\n"); + + mem_stat_mark(1); + + notice("complex arithmetic & special functions"); + + ONE = zmake(1.0,0.0); + printf("# ONE = "); z_output(ONE); + z1.re = mrand(); z1.im = mrand(); + z2.re = mrand(); z2.im = mrand(); + z3 = zadd(z1,z2); + if ( fabs(z1.re+z2.re-z3.re) + fabs(z1.im+z2.im-z3.im) > 10*MACHEPS ) + errmesg("zadd"); + z3 = zsub(z1,z2); + if ( fabs(z1.re-z2.re-z3.re) + fabs(z1.im-z2.im-z3.im) > 10*MACHEPS ) + errmesg("zadd"); + z3 = zmlt(z1,z2); + if ( fabs(z1.re*z2.re - z1.im*z2.im - z3.re) + + fabs(z1.im*z2.re + z1.re*z2.im - z3.im) > 10*MACHEPS ) + errmesg("zmlt"); + s1 = zabs(z1); + if ( fabs(s1*s1 - (z1.re*z1.re+z1.im*z1.im)) > 10*MACHEPS ) + errmesg("zabs"); + if ( zabs(zsub(z1,zmlt(z2,zdiv(z1,z2)))) > 10*MACHEPS || + zabs(zsub(ONE,zdiv(z1,zmlt(z2,zdiv(z1,z2))))) > 10*MACHEPS ) + errmesg("zdiv"); + + z3 = zsqrt(z1); + if ( zabs(zsub(z1,zmlt(z3,z3))) > 10*MACHEPS ) + errmesg("zsqrt"); + if ( zabs(zsub(z1,zlog(zexp(z1)))) > 10*MACHEPS ) + errmesg("zexp/zlog"); + + + printf("# Check: MACHEPS = %g\n",MACHEPS); + /* allocate, initialise, copy and resize operations */ + /* ZVEC */ + notice("vector initialise, copy & resize"); + x = zv_get(12); + y = zv_get(15); + z = zv_get(12); + zv_rand(x); + zv_rand(y); + z = zv_copy(x,z); + if ( zv_norm2(zv_sub(x,z,z)) >= MACHEPS ) + errmesg("ZVEC copy"); + zv_copy(x,y); + x = zv_resize(x,10); + y = zv_resize(y,10); + if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS ) + errmesg("ZVEC copy/resize"); + x = zv_resize(x,15); + y = zv_resize(y,15); + if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS ) + errmesg("VZEC resize"); + + /* ZMAT */ + notice("matrix initialise, copy & resize"); + A = zm_get(8,5); + B = zm_get(3,9); + C = zm_get(8,5); + zm_rand(A); + zm_rand(B); + C = zm_copy(A,C); + if ( zm_norm_inf(zm_sub(A,C,C)) >= MACHEPS ) + errmesg("ZMAT copy"); + zm_copy(A,B); + A = zm_resize(A,3,5); + B = zm_resize(B,3,5); + if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS ) + errmesg("ZMAT copy/resize"); + A = zm_resize(A,10,10); + B = zm_resize(B,10,10); + if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS ) + errmesg("ZMAT resize"); + + MEMCHK(); + + /* PERM */ + notice("permutation initialise, inverting & permuting vectors"); + pi1 = px_get(15); + pi2 = px_get(12); + px_rand(pi1); + zv_rand(x); + px_zvec(pi1,x,z); + y = zv_resize(y,x->dim); + pxinv_zvec(pi1,z,y); + if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS ) + errmesg("PERMute vector"); + + /* testing catch() etc */ + notice("error handling routines"); + catch(E_NULL, + catchall(zv_add(ZVNULL,ZVNULL,ZVNULL); + errmesg("tracecatch() failure"), + printf("# tracecatch() caught error\n"); + error(E_NULL,"main")); + errmesg("catch() failure"), + printf("# catch() caught E_NULL error\n")); + + /* testing inner products and v_mltadd() etc */ + notice("inner products and linear combinations"); + u = zv_get(x->dim); + zv_rand(u); + zv_rand(x); + zv_resize(y,x->dim); + zv_rand(y); + zv_mltadd(y,x,zneg(zdiv(zin_prod(x,y),zin_prod(x,x))),z); + if ( zabs(zin_prod(x,z)) >= 5*MACHEPS*x->dim ) + { + errmesg("zv_mltadd()/zin_prod()"); + printf("# error norm = %g\n", zabs(zin_prod(x,z))); + } + + z1 = zneg(zdiv(zin_prod(x,y),zmake(zv_norm2(x)*zv_norm2(x),0.0))); + zv_mlt(z1,x,u); + zv_add(y,u,u); + if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim ) + { + errmesg("zv_mlt()/zv_norm2()"); + printf("# error norm = %g\n", zv_norm2(u)); + } + +#ifdef ANSI_C + zv_linlist(u,x,z1,y,ONE,VNULL); + if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim ) + errmesg("zv_linlist()"); +#endif +#ifdef VARARGS + zv_linlist(u,x,z1,y,ONE,VNULL); + if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim ) + errmesg("zv_linlist()"); +#endif + + MEMCHK(); + + /* vector norms */ + notice("vector norms"); + x = zv_resize(x,12); + zv_rand(x); + for ( i = 0; i < x->dim; i++ ) + if ( zabs(zv_entry(x,i)) >= 0.7 ) + zv_set_val(x,i,ONE); + else + zv_set_val(x,i,zneg(ONE)); + s1 = zv_norm1(x); + s2 = zv_norm2(x); + s3 = zv_norm_inf(x); + if ( fabs(s1 - x->dim) >= MACHEPS*x->dim || + fabs(s2 - sqrt((double)(x->dim))) >= MACHEPS*x->dim || + fabs(s3 - 1.0) >= MACHEPS ) + errmesg("zv_norm1/2/_inf()"); + + /* test matrix multiply etc */ + notice("matrix multiply and invert"); + A = zm_resize(A,10,10); + B = zm_resize(B,10,10); + zm_rand(A); + zm_inverse(A,B); + zm_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + zm_sub_val(C,i,i,ONE); + if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zm_inverse()/zm_mlt()"); + + MEMCHK(); + + /* ... and adjoints */ + notice("adjoints and adjoint-multiplies"); + zm_adjoint(A,A); /* can do square matrices in situ */ + zmam_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE)); + if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zm_adjoint()/zmam_mlt()"); + zm_adjoint(A,A); + zm_adjoint(B,B); + zmma_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE)); + if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zm_adjoint()/zmma_mlt()"); + zsm_mlt(zmake(3.71,2.753),B,B); + zmma_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + zm_set_val(C,i,i,zsub(zm_entry(C,i,i),zmake(3.71,-2.753))); + if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("szm_mlt()/zmma_mlt()"); + zm_adjoint(B,B); + zsm_mlt(zdiv(ONE,zmake(3.71,-2.753)),B,B); + + MEMCHK(); + + /* ... and matrix-vector multiplies */ + notice("matrix-vector multiplies"); + x = zv_resize(x,A->n); + y = zv_resize(y,A->m); + z = zv_resize(z,A->m); + u = zv_resize(u,A->n); + zv_rand(x); + zv_rand(y); + zmv_mlt(A,x,z); + z1 = zin_prod(y,z); + zvm_mlt(A,y,u); + z2 = zin_prod(u,x); + if ( zabs(zsub(z1,z2)) >= (MACHEPS*x->dim)*x->dim ) + { + errmesg("zmv_mlt()/zvm_mlt()"); + printf("# difference between inner products is %g\n", + zabs(zsub(z1,z2))); + } + zmv_mlt(B,z,u); + if ( zv_norm2(zv_sub(u,x,u)) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zmv_mlt()/zvm_mlt()"); + + MEMCHK(); + + /* get/set row/col */ + notice("getting and setting rows and cols"); + x = zv_resize(x,A->n); + y = zv_resize(y,B->m); + x = zget_row(A,3,x); + y = zget_col(B,3,y); + if ( zabs(zsub(_zin_prod(x,y,0,Z_NOCONJ),ONE)) >= + MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zget_row()/zget_col()"); + zv_mlt(zmake(-1.0,0.0),x,x); + zv_mlt(zmake(-1.0,0.0),y,y); + zset_row(A,3,x); + zset_col(B,3,y); + zm_mlt(A,B,C); + for ( i = 0; i < C->m; i++ ) + zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE)); + if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 ) + errmesg("zset_row()/zset_col()"); + + MEMCHK(); + + /* matrix norms */ + notice("matrix norms"); + A = zm_resize(A,11,15); + zm_rand(A); + s1 = zm_norm_inf(A); + B = zm_adjoint(A,B); + s2 = zm_norm1(B); + if ( fabs(s1 - s2) >= MACHEPS*A->m ) + errmesg("zm_norm1()/zm_norm_inf()"); + C = zmam_mlt(A,A,C); + z1.re = z1.im = 0.0; + for ( i = 0; i < C->m && i < C->n; i++ ) + z1 = zadd(z1,zm_entry(C,i,i)); + if ( fabs(sqrt(z1.re) - zm_norm_frob(A)) >= MACHEPS*A->m*A->n ) + errmesg("zm_norm_frob"); + + MEMCHK(); + + /* permuting rows and columns */ + /****************************** + notice("permuting rows & cols"); + A = zm_resize(A,11,15); + B = zm_resize(B,11,15); + pi1 = px_resize(pi1,A->m); + px_rand(pi1); + x = zv_resize(x,A->n); + y = zmv_mlt(A,x,y); + px_rows(pi1,A,B); + px_zvec(pi1,y,z); + zmv_mlt(B,x,u); + if ( zv_norm2(zv_sub(z,u,u)) >= MACHEPS*A->m ) + errmesg("px_rows()"); + pi1 = px_resize(pi1,A->n); + px_rand(pi1); + px_cols(pi1,A,B); + pxinv_zvec(pi1,x,z); + zmv_mlt(B,z,u); + if ( zv_norm2(zv_sub(y,u,u)) >= MACHEPS*A->n ) + errmesg("px_cols()"); + ******************************/ + + MEMCHK(); + + /* MATLAB save/load */ + notice("MATLAB save/load"); + A = zm_resize(A,12,11); + if ( (fp=fopen(SAVE_FILE,"w")) == (FILE *)NULL ) + printf("Cannot perform MATLAB save/load test\n"); + else + { + zm_rand(A); + zm_save(fp, A, name); + fclose(fp); + if ( (fp=fopen(SAVE_FILE,"r")) == (FILE *)NULL ) + printf("Cannot open save file \"%s\"\n",SAVE_FILE); + else + { + ZM_FREE(B); + B = zm_load(fp,&cp); + if ( strcmp(name,cp) || zm_norm1(zm_sub(A,B,C)) >= + MACHEPS*A->m ) + { + errmesg("zm_load()/zm_save()"); + printf("# orig. name = %s, restored name = %s\n", name, cp); + printf("# orig. A =\n"); zm_output(A); + printf("# restored A =\n"); zm_output(B); + } + } + } + + MEMCHK(); + + /* Now, onto matrix factorisations */ + A = zm_resize(A,10,10); + B = zm_resize(B,A->m,A->n); + zm_copy(A,B); + x = zv_resize(x,A->n); + y = zv_resize(y,A->m); + z = zv_resize(z,A->n); + u = zv_resize(u,A->m); + zv_rand(x); + zmv_mlt(B,x,y); + z = zv_copy(x,z); + + notice("LU factor/solve"); + pivot = px_get(A->m); + zLUfactor(A,pivot); + tracecatch(zLUsolve(A,pivot,y,x),"main"); + tracecatch(cond_est = zLUcondest(A,pivot),"main"); + printf("# cond(A) approx= %g\n", cond_est); + if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est) + { + errmesg("zLUfactor()/zLUsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(zv_sub(x,z,u)), MACHEPS); + } + + + zv_copy(y,x); + tracecatch(zLUsolve(A,pivot,x,x),"main"); + tracecatch(cond_est = zLUcondest(A,pivot),"main"); + if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est) + { + errmesg("zLUfactor()/zLUsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(zv_sub(x,z,u)), MACHEPS); + } + + zvm_mlt(B,z,y); + zv_copy(y,x); + tracecatch(zLUAsolve(A,pivot,x,x),"main"); + if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est) + { + errmesg("zLUfactor()/zLUAsolve()"); + printf("# LU solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(zv_sub(x,z,u)), MACHEPS); + } + + MEMCHK(); + + /* QR factorisation */ + zm_copy(B,A); + zmv_mlt(B,z,y); + notice("QR factor/solve:"); + diag = zv_get(A->m); + zQRfactor(A,diag); + zQRsolve(A,diag,y,x); + if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est ) + { + errmesg("zQRfactor()/zQRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(zv_sub(x,z,u)), MACHEPS); + } + printf("# QR cond(A) approx= %g\n", zQRcondest(A)); + Q = zm_get(A->m,A->m); + zmakeQ(A,diag,Q); + zmakeR(A,A); + zm_mlt(Q,A,C); + zm_sub(B,C,C); + if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) ) + { + errmesg("zQRfactor()/zmakeQ()/zmakeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + zm_norm1(C), MACHEPS); + } + + MEMCHK(); + + /* now try with a non-square matrix */ + A = zm_resize(A,15,7); + zm_rand(A); + B = zm_copy(A,B); + diag = zv_resize(diag,A->n); + x = zv_resize(x,A->n); + y = zv_resize(y,A->m); + zv_rand(y); + zQRfactor(A,diag); + x = zQRsolve(A,diag,y,x); + /* z is the residual vector */ + zmv_mlt(B,x,z); zv_sub(z,y,z); + /* check B*.z = 0 */ + zvm_mlt(B,z,u); + if ( zv_norm2(u) >= 100*MACHEPS*zm_norm1(B)*zv_norm2(y) ) + { + errmesg("zQRfactor()/zQRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(u), MACHEPS); + } + Q = zm_resize(Q,A->m,A->m); + zmakeQ(A,diag,Q); + zmakeR(A,A); + zm_mlt(Q,A,C); + zm_sub(B,C,C); + if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) ) + { + errmesg("zQRfactor()/zmakeQ()/zmakeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + zm_norm1(C), MACHEPS); + } + D = zm_get(A->m,Q->m); + zmam_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + zm_set_val(D,i,i,zsub(zm_entry(D,i,i),ONE)); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q) ) + { + errmesg("QRfactor()/makeQ()/makeR()"); + printf("# QR orthogonality error = %g [cf MACHEPS = %g]\n", + zm_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* QRCP factorisation */ + zm_copy(B,A); + notice("QR factor/solve with column pivoting"); + pivot = px_resize(pivot,A->n); + zQRCPfactor(A,diag,pivot); + z = zv_resize(z,A->n); + zQRCPsolve(A,diag,pivot,y,z); + /* pxinv_zvec(pivot,z,x); */ + /* now compute residual (z) vector */ + zmv_mlt(B,x,z); zv_sub(z,y,z); + /* check B^T.z = 0 */ + zvm_mlt(B,z,u); + if ( zv_norm2(u) >= MACHEPS*zm_norm1(B)*zv_norm2(y) ) + { + errmesg("QRCPfactor()/QRsolve()"); + printf("# QR solution error = %g [cf MACHEPS = %g]\n", + zv_norm2(u), MACHEPS); + } + + Q = zm_resize(Q,A->m,A->m); + zmakeQ(A,diag,Q); + zmakeR(A,A); + zm_mlt(Q,A,C); + ZM_FREE(D); + D = zm_get(B->m,B->n); + /****************************** + px_cols(pivot,C,D); + zm_sub(B,D,D); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) ) + { + errmesg("QRCPfactor()/makeQ()/makeR()"); + printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n", + zm_norm1(D), MACHEPS); + } + ******************************/ + + /* Now check eigenvalue/SVD routines */ + notice("complex Schur routines"); + A = zm_resize(A,11,11); + B = zm_resize(B,A->m,A->n); + C = zm_resize(C,A->m,A->n); + D = zm_resize(D,A->m,A->n); + Q = zm_resize(Q,A->m,A->n); + + MEMCHK(); + + /* now test complex Schur decomposition */ + /* zm_copy(A,B); */ + ZM_FREE(A); + A = zm_get(11,11); + zm_rand(A); + B = zm_copy(A,B); + MEMCHK(); + + B = zschur(B,Q); + checkpt(); + + zm_mlt(Q,B,C); + zmma_mlt(C,Q,D); + MEMCHK(); + zm_sub(A,D,D); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*zm_norm1(B)*5 ) + { + errmesg("zschur()"); + printf("# Schur reconstruction error = %g [cf MACHEPS = %g]\n", + zm_norm1(D), MACHEPS); + } + + /* orthogonality check */ + zmma_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + zm_set_val(D,i,i,zsub(zm_entry(D,i,i),ONE)); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*10 ) + { + errmesg("zschur()"); + printf("# Schur orthogonality error = %g [cf MACHEPS = %g]\n", + zm_norm1(D), MACHEPS); + } + + MEMCHK(); + + /* now test SVD */ + /****************************** + A = zm_resize(A,11,7); + zm_rand(A); + U = zm_get(A->n,A->n); + Q = zm_resize(Q,A->m,A->m); + u = zv_resize(u,max(A->m,A->n)); + svd(A,Q,U,u); + ******************************/ + /* check reconstruction of A */ + /****************************** + D = zm_resize(D,A->m,A->n); + C = zm_resize(C,A->m,A->n); + zm_zero(D); + for ( i = 0; i < min(A->m,A->n); i++ ) + zm_set_val(D,i,i,v_entry(u,i)); + zmam_mlt(Q,D,C); + zm_mlt(C,U,D); + zm_sub(A,D,D); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(Q)*zm_norm1(A) ) + { + errmesg("svd()"); + printf("# SVD reconstruction error = %g [cf MACHEPS = %g]\n", + zm_norm1(D), MACHEPS); + } + ******************************/ + /* check orthogonality of Q and U */ + /****************************** + D = zm_resize(D,Q->n,Q->n); + zmam_mlt(Q,Q,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*5 ) + { + errmesg("svd()"); + printf("# SVD orthognality error (Q) = %g [cf MACHEPS = %g\n", + zm_norm1(D), MACHEPS); + } + D = zm_resize(D,U->n,U->n); + zmam_mlt(U,U,D); + for ( i = 0; i < D->m; i++ ) + m_set_val(D,i,i,m_entry(D,i,i)-1.0); + if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(U)*5 ) + { + errmesg("svd()"); + printf("# SVD orthognality error (U) = %g [cf MACHEPS = %g\n", + zm_norm1(D), MACHEPS); + } + for ( i = 0; i < u->dim; i++ ) + if ( v_entry(u,i) < 0 || (i < u->dim-1 && + v_entry(u,i+1) > v_entry(u,i)) ) + break; + if ( i < u->dim ) + { + errmesg("svd()"); + printf("# SVD sorting error\n"); + } + ******************************/ + + ZV_FREE(x); ZV_FREE(y); ZV_FREE(z); + ZV_FREE(u); ZV_FREE(diag); + PX_FREE(pi1); PX_FREE(pi2); PX_FREE(pivot); + ZM_FREE(A); ZM_FREE(B); ZM_FREE(C); + ZM_FREE(D); ZM_FREE(Q); + + mem_stat_free(1); + + MEMCHK(); + printf("# Finished torture test for complex numbers/vectors/matrices\n"); + mem_info(); +} + diff --git a/zvecop.c b/zvecop.c new file mode 100644 index 0000000..30a8fc1 --- /dev/null +++ b/zvecop.c @@ -0,0 +1,568 @@ + +/************************************************************************** +** +** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. +** +** Meschach Library +** +** This Meschach Library is provided "as is" without any express +** or implied warranty of any kind with respect to this software. +** In particular the authors shall not be liable for any direct, +** indirect, special, incidental or consequential damages arising +** in any way from use of the software. +** +** Everyone is granted permission to copy, modify and redistribute this +** Meschach Library, provided: +** 1. All copies contain this copyright notice. +** 2. All modified copies shall carry a notice stating who +** made the last modification and the date of such modification. +** 3. No charge is made for this software or works derived from it. +** This clause shall not be construed as constraining other software +** distributed on the same medium as this software, nor is a +** distribution fee considered a charge. +** +***************************************************************************/ + + +#include +#include "matrix.h" +#include "zmatrix.h" +static char rcsid[] = "$Id: zvecop.c,v 1.3 1997/10/07 16:13:54 stewart Exp stewart $"; + + + +/* _zin_prod -- inner product of two vectors from i0 downwards + -- flag != 0 means compute sum_i a[i]*.b[i]; + -- flag == 0 means compute sum_i a[i].b[i] */ +#ifndef ANSI_C +complex _zin_prod(a,b,i0,flag) +ZVEC *a,*b; +unsigned int i0, flag; +#else +complex _zin_prod(const ZVEC *a, const ZVEC *b, + unsigned int i0, unsigned int flag) +#endif +{ + unsigned int limit; + + if ( a==ZVNULL || b==ZVNULL ) + error(E_NULL,"_zin_prod"); + limit = min(a->dim,b->dim); + if ( i0 > limit ) + error(E_BOUNDS,"_zin_prod"); + + return __zip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0),flag); +} + +/* zv_mlt -- scalar-vector multiply -- may be in-situ */ +#ifndef ANSI_C +ZVEC *zv_mlt(scalar,vector,out) +complex scalar; +ZVEC *vector,*out; +#else +ZVEC *zv_mlt(complex scalar, const ZVEC *vector, ZVEC *out) +#endif +{ + /* unsigned int dim, i; */ + /* complex *out_ve, *vec_ve; */ + + if ( vector==ZVNULL ) + error(E_NULL,"zv_mlt"); + if ( out==ZVNULL || out->dim != vector->dim ) + out = zv_resize(out,vector->dim); + if ( scalar.re == 0.0 && scalar.im == 0.0 ) + return zv_zero(out); + if ( scalar.re == 1.0 && scalar.im == 0.0 ) + return zv_copy(vector,out); + + __zmlt__(vector->ve,scalar,out->ve,(int)(vector->dim)); + + return (out); +} + +/* zv_add -- vector addition -- may be in-situ */ +#ifndef ANSI_C +ZVEC *zv_add(vec1,vec2,out) +ZVEC *vec1,*vec2,*out; +#else +ZVEC *zv_add(const ZVEC *vec1, const ZVEC *vec2, ZVEC *out) +#endif +{ + unsigned int dim; + + if ( vec1==ZVNULL || vec2==ZVNULL ) + error(E_NULL,"zv_add"); + if ( vec1->dim != vec2->dim ) + error(E_SIZES,"zv_add"); + if ( out==ZVNULL || out->dim != vec1->dim ) + out = zv_resize(out,vec1->dim); + dim = vec1->dim; + __zadd__(vec1->ve,vec2->ve,out->ve,(int)dim); + + return (out); +} + +/* zv_mltadd -- scalar/vector multiplication and addition + -- out = v1 + scale.v2 */ +#ifndef ANSI_C +ZVEC *zv_mltadd(v1,v2,scale,out) +ZVEC *v1,*v2,*out; +complex scale; +#else +ZVEC *zv_mltadd(const ZVEC *v1, const ZVEC *v2, complex scale, ZVEC *out) +#endif +{ + /* register unsigned int dim, i; */ + /* complex *out_ve, *v1_ve, *v2_ve; */ + + if ( v1==ZVNULL || v2==ZVNULL ) + error(E_NULL,"zv_mltadd"); + if ( v1->dim != v2->dim ) + error(E_SIZES,"zv_mltadd"); + if ( scale.re == 0.0 && scale.im == 0.0 ) + return zv_copy(v1,out); + if ( scale.re == 1.0 && scale.im == 0.0 ) + return zv_add(v1,v2,out); + + if ( v2 != out ) + { + tracecatch(out = zv_copy(v1,out),"zv_mltadd"); + + /* dim = v1->dim; */ + __zmltadd__(out->ve,v2->ve,scale,(int)(v1->dim),0); + } + else + { + tracecatch(out = zv_mlt(scale,v2,out),"zv_mltadd"); + out = zv_add(v1,out,out); + } + + return (out); +} + +/* zv_sub -- vector subtraction -- may be in-situ */ +#ifndef ANSI_C +ZVEC *zv_sub(vec1,vec2,out) +ZVEC *vec1,*vec2,*out; +#else +ZVEC *zv_sub(const ZVEC *vec1, const ZVEC *vec2, ZVEC *out) +#endif +{ + /* unsigned int i, dim; */ + /* complex *out_ve, *vec1_ve, *vec2_ve; */ + + if ( vec1==ZVNULL || vec2==ZVNULL ) + error(E_NULL,"zv_sub"); + if ( vec1->dim != vec2->dim ) + error(E_SIZES,"zv_sub"); + if ( out==ZVNULL || out->dim != vec1->dim ) + out = zv_resize(out,vec1->dim); + + __zsub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim)); + + return (out); +} + +/* zv_map -- maps function f over components of x: out[i] = f(x[i]) + -- _zv_map sets out[i] = f(x[i],params) */ +#ifndef ANSI_C +ZVEC *zv_map(f,x,out) +#ifdef PROTOYPES_IN_STRUCT +complex (*f)(complex); +#else +complex (*f)(); +#endif +ZVEC *x, *out; +#else +ZVEC *zv_map(complex (*f)(complex), const ZVEC *x, ZVEC *out) +#endif +{ + complex *x_ve, *out_ve; + int i, dim; + + if ( ! x || ! f ) + error(E_NULL,"zv_map"); + if ( ! out || out->dim != x->dim ) + out = zv_resize(out,x->dim); + + dim = x->dim; x_ve = x->ve; out_ve = out->ve; + for ( i = 0; i < dim; i++ ) + out_ve[i] = (*f)(x_ve[i]); + + return out; +} + +#ifndef ANSI_C +ZVEC *_zv_map(f,params,x,out) +#ifdef PROTOTYPES_IN_STRUCT +complex (*f)(void *,complex); +#else +complex (*f)(); +#endif +ZVEC *x, *out; +void *params; +#else +ZVEC *_zv_map(complex (*f)(void *,complex), void *params, + const ZVEC *x, ZVEC *out) +#endif +{ + complex *x_ve, *out_ve; + int i, dim; + + if ( ! x || ! f ) + error(E_NULL,"_zv_map"); + if ( ! out || out->dim != x->dim ) + out = zv_resize(out,x->dim); + + dim = x->dim; x_ve = x->ve; out_ve = out->ve; + for ( i = 0; i < dim; i++ ) + out_ve[i] = (*f)(params,x_ve[i]); + + return out; +} + +/* zv_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */ +#ifndef ANSI_C +ZVEC *zv_lincomb(n,v,a,out) +int n; /* number of a's and v's */ +complex a[]; +ZVEC *v[], *out; +#else +ZVEC *zv_lincomb(int n, const ZVEC *v[], const complex a[], ZVEC *out) +#endif +{ + int i; + + if ( ! a || ! v ) + error(E_NULL,"zv_lincomb"); + if ( n <= 0 ) + return ZVNULL; + + for ( i = 1; i < n; i++ ) + if ( out == v[i] ) + error(E_INSITU,"zv_lincomb"); + + out = zv_mlt(a[0],v[0],out); + for ( i = 1; i < n; i++ ) + { + if ( ! v[i] ) + error(E_NULL,"zv_lincomb"); + if ( v[i]->dim != out->dim ) + error(E_SIZES,"zv_lincomb"); + out = zv_mltadd(out,v[i],a[i],out); + } + + return out; +} + + +#ifdef ANSI_C + + +/* zv_linlist -- linear combinations taken from a list of arguments; + calling: + zv_linlist(out,v1,a1,v2,a2,...,vn,an,NULL); + where vi are vectors (ZVEC *) and ai are numbers (complex) +*/ + +ZVEC *zv_linlist(ZVEC *out,ZVEC *v1,complex a1,...) +{ + va_list ap; + ZVEC *par; + complex a_par; + + if ( ! v1 ) + return ZVNULL; + + va_start(ap, a1); + out = zv_mlt(a1,v1,out); + + while (par = va_arg(ap,ZVEC *)) { /* NULL ends the list*/ + a_par = va_arg(ap,complex); + if (a_par.re == 0.0 && a_par.im == 0.0) continue; + if ( out == par ) + error(E_INSITU,"zv_linlist"); + if ( out->dim != par->dim ) + error(E_SIZES,"zv_linlist"); + + if (a_par.re == 1.0 && a_par.im == 0.0) + out = zv_add(out,par,out); + else if (a_par.re == -1.0 && a_par.im == 0.0) + out = zv_sub(out,par,out); + else + out = zv_mltadd(out,par,a_par,out); + } + + va_end(ap); + return out; +} + + +#elif VARARGS + +/* zv_linlist -- linear combinations taken from a list of arguments; + calling: + zv_linlist(out,v1,a1,v2,a2,...,vn,an,NULL); + where vi are vectors (ZVEC *) and ai are numbers (complex) +*/ +ZVEC *zv_linlist(va_alist) va_dcl +{ + va_list ap; + ZVEC *par, *out; + complex a_par; + + va_start(ap); + out = va_arg(ap,ZVEC *); + par = va_arg(ap,ZVEC *); + if ( ! par ) { + va_end(ap); + return ZVNULL; + } + + a_par = va_arg(ap,complex); + out = zv_mlt(a_par,par,out); + + while (par = va_arg(ap,ZVEC *)) { /* NULL ends the list*/ + a_par = va_arg(ap,complex); + if (a_par.re == 0.0 && a_par.im == 0.0) continue; + if ( out == par ) + error(E_INSITU,"zv_linlist"); + if ( out->dim != par->dim ) + error(E_SIZES,"zv_linlist"); + + if (a_par.re == 1.0 && a_par.im == 0.0) + out = zv_add(out,par,out); + else if (a_par.re == -1.0 && a_par.im == 0.0) + out = zv_sub(out,par,out); + else + out = zv_mltadd(out,par,a_par,out); + } + + va_end(ap); + return out; +} + + +#endif + + + +/* zv_star -- computes componentwise (Hadamard) product of x1 and x2 + -- result out is returned */ +#ifndef ANSI_C +ZVEC *zv_star(x1, x2, out) +ZVEC *x1, *x2, *out; +#else +ZVEC *zv_star(const ZVEC *x1, const ZVEC *x2, ZVEC *out) +#endif +{ + int i; + Real t_re, t_im; + + if ( ! x1 || ! x2 ) + error(E_NULL,"zv_star"); + if ( x1->dim != x2->dim ) + error(E_SIZES,"zv_star"); + out = zv_resize(out,x1->dim); + + for ( i = 0; i < x1->dim; i++ ) + { + /* out->ve[i] = x1->ve[i] * x2->ve[i]; */ + t_re = x1->ve[i].re*x2->ve[i].re - x1->ve[i].im*x2->ve[i].im; + t_im = x1->ve[i].re*x2->ve[i].im + x1->ve[i].im*x2->ve[i].re; + out->ve[i].re = t_re; + out->ve[i].im = t_im; + } + + return out; +} + +/* zv_slash -- computes componentwise ratio of x2 and x1 + -- out[i] = x2[i] / x1[i] + -- if x1[i] == 0 for some i, then raise E_SING error + -- result out is returned */ +#ifndef ANSI_C +ZVEC *zv_slash(x1, x2, out) +ZVEC *x1, *x2, *out; +#else +ZVEC *zv_slash(const ZVEC *x1, const ZVEC *x2, ZVEC *out) +#endif +{ + int i; + Real r2, t_re, t_im; + complex tmp; + + if ( ! x1 || ! x2 ) + error(E_NULL,"zv_slash"); + if ( x1->dim != x2->dim ) + error(E_SIZES,"zv_slash"); + out = zv_resize(out,x1->dim); + + for ( i = 0; i < x1->dim; i++ ) + { + r2 = x1->ve[i].re*x1->ve[i].re + x1->ve[i].im*x1->ve[i].im; + if ( r2 == 0.0 ) + error(E_SING,"zv_slash"); + tmp.re = x1->ve[i].re / r2; + tmp.im = - x1->ve[i].im / r2; + t_re = tmp.re*x2->ve[i].re - tmp.im*x2->ve[i].im; + t_im = tmp.re*x2->ve[i].im + tmp.im*x2->ve[i].re; + out->ve[i].re = t_re; + out->ve[i].im = t_im; + } + + return out; +} + +/* zv_sum -- returns sum of entries of a vector */ +#ifndef ANSI_C +complex zv_sum(x) +ZVEC *x; +#else +complex zv_sum(const ZVEC *x) +#endif +{ + int i; + complex sum; + + if ( ! x ) + error(E_NULL,"zv_sum"); + + sum.re = sum.im = 0.0; + for ( i = 0; i < x->dim; i++ ) + { + sum.re += x->ve[i].re; + sum.im += x->ve[i].im; + } + + return sum; +} + +/* px_zvec -- permute vector */ +#ifndef ANSI_C +ZVEC *px_zvec(px,vector,out) +PERM *px; +ZVEC *vector,*out; +#else +ZVEC *px_zvec(PERM *px, ZVEC *vector, ZVEC *out) +#endif +{ + unsigned int old_i, i, size, start; + complex tmp; + + if ( px==PNULL || vector==ZVNULL ) + error(E_NULL,"px_zvec"); + if ( px->size > vector->dim ) + error(E_SIZES,"px_zvec"); + if ( out==ZVNULL || out->dim < vector->dim ) + out = zv_resize(out,vector->dim); + + size = px->size; + if ( size == 0 ) + return zv_copy(vector,out); + + if ( out != vector ) + { + for ( i=0; ipe[i] >= size ) + error(E_BOUNDS,"px_vec"); + else + out->ve[i] = vector->ve[px->pe[i]]; + } + else + { /* in situ algorithm */ + start = 0; + while ( start < size ) + { + old_i = start; + i = px->pe[old_i]; + if ( i >= size ) + { + start++; + continue; + } + tmp = vector->ve[start]; + while ( TRUE ) + { + vector->ve[old_i] = vector->ve[i]; + px->pe[old_i] = i+size; + old_i = i; + i = px->pe[old_i]; + if ( i >= size ) + break; + if ( i == start ) + { + vector->ve[old_i] = tmp; + px->pe[old_i] = i+size; + break; + } + } + start++; + } + + for ( i = 0; i < size; i++ ) + if ( px->pe[i] < size ) + error(E_BOUNDS,"px_vec"); + else + px->pe[i] = px->pe[i]-size; + } + + return out; +} + +/* pxinv_zvec -- apply the inverse of px to x, returning the result in out + -- may NOT be in situ */ +#ifndef ANSI_C +ZVEC *pxinv_zvec(px,x,out) +PERM *px; +ZVEC *x, *out; +#else +ZVEC *pxinv_zvec(PERM *px, ZVEC *x, ZVEC *out) +#endif +{ + unsigned int i, size; + + if ( ! px || ! x ) + error(E_NULL,"pxinv_zvec"); + if ( px->size > x->dim ) + error(E_SIZES,"pxinv_zvec"); + if ( ! out || out->dim < x->dim ) + out = zv_resize(out,x->dim); + + size = px->size; + if ( size == 0 ) + return zv_copy(x,out); + if ( out != x ) + { + for ( i=0; ipe[i] >= size ) + error(E_BOUNDS,"pxinv_vec"); + else + out->ve[px->pe[i]] = x->ve[i]; + } + else + { /* in situ algorithm --- cheat's way out */ + px_inv(px,px); + px_zvec(px,x,out); + px_inv(px,px); + } + + + return out; +} + +/* zv_rand -- randomise a complex vector; uniform in [0,1)+[0,1)*i */ +#ifndef ANSI_C +ZVEC *zv_rand(x) +ZVEC *x; +#else +ZVEC *zv_rand(ZVEC *x) +#endif +{ + if ( ! x ) + error(E_NULL,"zv_rand"); + + mrandlist((Real *)(x->ve),2*x->dim); + + return x; +}